PDA

View Full Version : blend 3 textures with 1 alpha map



soconne
10-01-2003, 09:31 AM
Does anybody know how to blend 3 textures with 1 alpha map? I've read the article on delphi3d.net on doing it but it doesn't make sense. It seems that he uses the RGB components of one alph map, R - grass, G - rock, B - dirt....

But I can't see in the code how each of these is extracted to perform the interpolation. How can you make calls to glTexEnvf with the GL_INTERPOLATE_ARB using only the R component, or G or B?

I figured to blend 3 textures I could set one as the base, then in the alpha map, set the color to be used for let's say the rock textures, and the alpha channel for the dirt texture, that was in the glTexEnvf calls for textures 2 and 3, I just pass in GL_SRC_COLOR and GL_SRC_ALPHA for which components of the alphamap to use.

Anybody have a better idea or know how Delphi3d does it?

jwatte
10-01-2003, 10:11 AM
You may need the GL_COMBINE TexEnv mode, and you need support for ARB_texture_env_crossbar or the NVIDIA extesion NV_texture_env_combine4 that implies the same support except for one particular case of sourcing undefined textures. I believe these are all core in OpenGL 1.4, so you don't need to test for the extensions if OpenGL version advertized is 1.4 or higher.

I haven't taken the time to figure out exactly what the set-up is -- it may be that you need two texenvs (or NVIDIA register combiners) per map you want to support, so that one env can do a DP3 with some constant to figure out which channel to use, and then modulate that with the source texture. Or maybe you can route a component into the alpha input, but I don't seem to recall that being possible.

RADEON 8500+ have 6 texture units and thus 6 TexEnvs, so you can probably do it with traditional TexEnv. GEFORCE 3+ have 4 texture units, which leads to 4 TexEnvs, which isn't enough, but if you use register combiners on those cards, you get 8 general combiners, which is enough. So you'd need two code paths. (Well, more than that if you want to support earlier cards)

soconne
10-01-2003, 10:28 AM
I've already done this with 2 textures and an alpha map using texture combiners. I'm using a radeon 9000 so I do have the crossbar extension. My question how to differentiate between the RGB components in the alpha texture to make R be the transparency for the first texture, G be for the 2nd and so on.

DarkWIng
10-01-2003, 11:34 AM
You could use dot3 to extract color chanes from RGB texture:

R = RGB dot (1,0,0)
G = RGB dot (0,1,0)
B = RGB dot (0,0,1)

I hope I understod your question.

[This message has been edited by DarkWIng (edited 10-01-2003).]

soconne
10-01-2003, 11:52 AM
I can put the dot3 stuff into one of the glTexEnvf functions? I'm using the GL_TEXTURE_COMBINE extension, and I don't think you can do that with it. Any ideas on this?

Tom Nuydens
10-01-2003, 12:14 PM
I wrote that article you're referring to. It comes with a demo as well, so use the source, Luke http://www.opengl.org/discussion_boards/ubb/smile.gif

What I did is to put the blending factors in the vertex colors. There's only two of them, even though there's three textures. They're stored in RGB and A respectively (i.e. R, G and B are the same).

The article explains how to go from three blending factors for a weighted average of three textures to only two factors and two interpolations, to get the same end result. If that's what confuses you, I have a full mathematical derivation of that somewhere which is not given in the article. If you'd like to see it, just ask.

Given the three textures and two blending factors, the texture units are configured as follows:

Unit 0: bind tile 0; output current texture.
Unit 1: bind tile 1; output LERP(previous, current, vertex.rgb).
Unit 2: bind tile 2; output LERP(previous, current, vertex.alpha).

You need ARB_texture_env_combine and three texture units (four if you want the lightmap as in my demo) to do it. All texture units only reference the current texture and the result of the previous unit, so crossbar, combine4, dot3, register combiners or other fancy stuff are not needed. There's no need to extract R, G or B separately -- you just use GL_SRC_COLOR.

Hope this helps,

-- Tom

soconne
10-01-2003, 02:18 PM
So when i read in the alpha map, if red is for texture2, and g is for texture3, then set the alpha values to the green component, and set green and blue to the red component. right? that makes sense. thanks

soconne
10-01-2003, 03:08 PM
Well I've tried coding this up but it doesn't seem to be working. The first and second textures are blended correctly using the RGB values from the alpha map. I then try and blend the third using the alpha values from the alpha map, but the entire texture is blended across the entire quad. here's the code

<CODE>
//base texture - grass
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture0);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_RGB_EXT);
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);

//alpha texture - RGB (transparency for texture2) ALPHA (transparency for texture3)
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, alphamap);

//second texture - rock
glActiveTextureARB(GL_TEXTURE2_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture1);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_INT ERPOLATE_ARB);

glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SR C_COLOR);

glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_TEX TURE2);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SR C_COLOR);

glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE2_RGB_ARB,GL_TEX TURE1);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND2_RGB_ARB,GL_SR C_COLOR);

//third texture - dirt
glActiveTextureARB(GL_TEXTURE3_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture2);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_INT ERPOLATE_ARB);

glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PRE VIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SR C_COLOR);

glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_TEX TURE3);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SR C_COLOR);

glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE2_RGB_ARB,GL_TEX TURE1);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND2_RGB_ARB,GL_SR C_ALPHA);
</CODE>

Anyone see any mistakes?

Tom Nuydens
10-02-2003, 12:43 AM
Originally posted by oconnellseanm:
So when i read in the alpha map, if red is for texture2, and g is for texture3, then set the alpha values to the green component, and set green and blue to the red component. right? that makes sense. thanks

No, not exactly. Given your three blending factors R, G and B, you need to calculate two new factors A1 and A2 such that Tex0*R + Tex1*G + Tex2*B = LERP(A1, LERP(A2, Tex0, Tex1), Tex2). Then you create your "alpha map" by setting each RGBA texel to (A1, A1, A1, A2). This is the calculation that I offered to give you a full derivation of, but the answer is in my article. The answer somewhat depends on the exact TexEnv setup you use, though.

-- Tom