Skip to main content
gamedev.net
🔒 Locked

Using separate alpha textures

Started by tomshackell 5 replies 1.5k views
Original Post
tomshackell
tomshackell
Hello, My question is about alpha textures and multi-texturing. Here is the basic idea: You have a base texture and then you place other texture layers over the top of it to get a combined effect. Each new layer consists of a color texture and an alpha texture. The color texture describes what is being merged with the base and the alpha texture is describing how it is merged with the base. There are lots of different color textures that might want to be merged with the base, and lots of different ways that they could be merged. Now usually in OpenGL the color texture and the alpha texture are combined, you would just load an RGBA texture that included both component. But is it also possible to do this with the color textures and alpha textures being separate? The reason being that if you've got 16 color textures, and 16 different ways of merging them with the base, then that's 256 different possible combinations. In contrast if the alpha textures can be separate then you only need 32 textures: the 16 color textures and 16 alpha textures. The more textures you have, and the more ways of merging, the bigger this discrepancy gets. Now clearly it would be possible to write a fragment shader to do this, my question is: is it possible without using a shader? I've researched this question on the internet quite a bit, but I've not been able to come up with an answer, so I would be really grateful if anyone knows :-) Cheers Tom EDIT: Also, if possible, it would be nice if it could be done single pass :) Additionally is it wise to try and do this without a shader, is it quicker with one? [Edited by - tomshackell on January 27, 2008 10:34:05 AM]
V-man
V-man
IIRC, if you load a LUMINANCE texture or ALPHA texture and read it, it will result in
red=L, green=L, blue=L, alpha=1.0

so I think it can't be done without shaders.
kauna
kauna

Hi,

As far as I know, what you are after, is doable without shaders. I am not from OpenGL background, but you'll need to use multitexturing (perhaps alpha for stage 0 and diffuse for stage 1). I don't know which functions you'll need to call, but it is about combining the textures in a way that the alpha is taken from level 0 and diffuse from level 1).

Under D3D it is quite simple thing to do. I assume that there could be some example about this in GameDev or perhaps you could look for texture splatting on the internet.

Good luck!
V-man
V-man
Ah yes, I have to correct myself. If you make a RGBA texture and you don't care about the RGB part, then you are alright. You can use multitexture and texture combiners to do your effect.

glActiveTexture(GL_TEXTURE0);//we only care about RGBglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);glActiveTexture(GL_TEXTURE1);//we only care about ALPHAglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);

tomshackell
tomshackell
Quote:
Original post by V-man
Ah yes, I have to correct myself. If you make a RGBA texture and you don't care about the RGB part, then you are alright. You can use multitexture and texture combiners to do your effect.

<snip example>

Ah that's interesting, I can see how that would work using multiple passes but can you do it in a single pass? i.e. take the base texture and apply all the layers over the top in one pass?

That would require 'blending' to work between layers, i.e. you'd combine the color texture and the alpha texture (using GL_REPLACE) and then "blend" it with the base texture. Is there an operation that acts between texture units that blends them together based on the alpha component?

Cheers :)


Tom

V-man
V-man
That is a single pass. It uses multitexdturing. That is what glActiveTexture is for.
To blend them using alpha, you would use GL_INTERPOLATE. Do a google.
tomshackell
tomshackell
Thanks V-man, GL_INTERPOLATE did the trick. I've seen ARB_texture_env_combine before but I've never really understood it. OpenGL is on the whole very well documented, but that particular extension is very hard to find examples for.

For anyone who is interested this the solution I used in the end. So we're trying to merge a base texture, a layer-color texture and a layer-alpha texture. This kind of thing is quite handy for texture splatting, you have a base and layers placed over the top. Ideally we'd like to do this in a single pass.

The idea is to have a number of texture environments each combined with several functions:

GL_TEXTURE0_ARB: Base            RGB-func:  GL_REPLACE(GL_TEXTURE:GL_SRC_COLOR)      A-func:    GL_REPLACE(GL_TEXTURE:GL_SRC_ALPHA)GL_TEXTURE1_ARB: Layer0-RGB       RGB-func:  GL_REPLACE(GL_TEXTURE:GL_SRC_COLOR)      A-func:    GL_REPLACE(GL_TEXTURE:GL_SRC_ALPHA)GL_TEXTURE2_ARB: Layer0-A         RGB-func:  GL_INTERPOLATE(GL_PREVIOUS:GL_SRC_COLOR, GL_TEXTURE0:GL_SRC_COLOR, GL_TEXTURE:GL_SRC_ALPHA)     A-func:    GL_REPLACE(GL_TEXTURE0:GL_SRC_ALPHA)GL_TEXTURE3_ARB: Layer1-RGB     RGB-func:  GL_REPLACE(GL_TEXTURE:GL_SRC_COLOR)      A-func:    GL_REPLACE(GL_TEXTURE:GL_SRC_ALPHA)GL_TEXTURE4_ARB: Layer1-A     RGB-func:  GL_INTERPOLATE(GL_PREVIOUS:GL_SRC_COLOR, GL_TEXTURE2:GL_SRC_COLOR, GL_TEXTURE:GL_SRC_ALPHA)     A-func:    GL_REPLACE(GL_TEXTURE2:GL_SRC_ALPHA)

This translates into code such as:

glActiveTextureARB(GL_TEXTURE0_ARB);glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, base);glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);glActiveTextureARB(GL_TEXTURE1_ARB);glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, layer0_rgb);glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);glActiveTextureARB(GL_TEXTURE2_ARB);glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, layer0_alpha);glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE);            glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE0);    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE0);    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);// ... etc ...

This obviously requires the ARB_texture_env_crossbar extension as we need to refer to previous textures other than just the last one. If you've only got one layer to add you can do it without the crossbar by playing with the order.

GL_TEXTURE0_ARB: Layer0-RGB            RGB-func:  GL_REPLACE(GL_TEXTURE:GL_SRC_COLOR)      A-func:    GL_REPLACE(GL_TEXTURE:GL_SRC_ALPHA)GL_TEXTURE1_ARB: Layer0-A     RGB-func:  GL_REPLACE(GL_PREVIOUS:GL_SRC_COLOR)      A-func:    GL_REPLACE(GL_TEXTURE:GL_SRC_ALPHA)GL_TEXTURE2_ARB: Base     RGB-func:  GL_INTERPOLATE(GL_PREVIOUS:GL_SRC_COLOR, GL_TEXTURE:GL_SRC_COLOR, GL_PREVIOUS:GL_SRC_ALPHA)     A-func:    GL_REPLACE(GL_TEXTURE:GL_SRC_ALPHA)

I can't see any way to do more than one layer in a single pass without the crossbar extension. Funnily all that you'd need is GL_PREVIOUS_PREVIOUS :) However if anyone does know a way to do it then I'd be interested :)

Anyway thanks greatly for all the help :)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.