Blending and multitexturing.

Heh, I’m sure this question has been asked many times, but Google is failing me right now =/

Anyway, I want to blend two textures on top of each other (essentially a crossfade over time). Here’s what I have so far (it almost does what I want):

glActiveTextureARB(GL_TEXTURE0_ARB);
textureList.BindTexture(tex2, false);

glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
textureList.BindTexture(tex1, false);

//this sets up TU1’s output to interpolate mode
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT);
//the first factor will be TU0’s output, which is basically layer A’s
//texture modulated with the colour & lighting and what-not.
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
//the second factor will be this TU’s texture - which is layer B
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
//this sets the interpolating factor to be the alpha value of the
//colour set with a call to glColor*(). So, by modifying the alpha
//of the colour, I switch the bias between layer A and layer B
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
//the alpha component of the output of a TU is independent of the colour component!
//Since my layer A and layer B textures also contain varying alpha values,
//they’re RGBA textures, we need to tell the TU to interpolate the alpha values too
//This is done in the same way as the RGBs above
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_INTERPOLATE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);

glColor4f(poly->r, poly->g, poly->b, alpha);
glDrawArrays(GL_TRIANGLE_FAN, poly->index, poly->numPts);

glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB);

The problem is I have to set the blending value with glColor*, which I don’t want to do. The underlaying geometry is usually opaque, but it would be nice if I could support semi-transparent geometry as well with this. Is there a way I can set the blending value with GL_TEXTURE_ENV_COLOR so it would be independant of the geometry (ideal solution) or even just ignore the alpha value for the geometry and only use it for the texture blending (which is how it’s set up for the multipass version)?

you can use glTexEnv to set the environment color.
It`s token is GL_CONSTANT if Im not mistaken (I dont have any manuals with me).

Replace GL_PRIMARY_COLOR with GL_CONSTANT but you have to set the constant for each unit

Cool, thanks for the quick response! Anyway, that is definitely much closer to what I’m looking for, but now I get an odd flickering during the blending.

Best way to describe this is with a video (FRAPS is pretty cool): http://members.shaw.ca/timstump/zdoomgl/multitex.mpg (~1.6MB). It works fine (no flicker) if I turn multitexturing off, of course.

edit: added video of how it should look (Shaw Communications).

[This message has been edited by timmie (edited 08-13-2003).]

[This message has been edited by timmie (edited 08-13-2003).]

Ok, got it all sorted. Here’s how it looks now:

// interpolate textures
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
textureList.BindTexture(tex2, false);
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, colors); // colors = { 0.f, 0.f, 0.f, blend_pct}
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
// modulate with actual color
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
textureList.BindTexture(tex1, false);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
// set actual color/alpha
glColor4f(poly->r, poly->g, poly->b, poly->a);
glDrawArrays(GL_TRIANGLE_FAN, poly->index, poly->numPts);
// clean up afterwards
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);