problem w/ reflection maps when going from multipass to multitexture

Hello!

this group has been helpful to me in the past, and I’ve got another problem that I am stuck on :O) The issue has to do with reflection maps on my models in OpenGL. Currently, I am applying the reflection maps with multipass, like this:

// pass 1: draw reflection map
glActiveTextureARB(GL_TEXTURE0_ARB);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, reflection_map);
glBlendFunc(GL_ONE, GL_ZERO);
glBegin();
… draw triangles
glEnd();

// pass 2: draw base texture map which has 1-bit alpha (format is 1555)
glActiveTextureARB(GL_TEXTURE1_ARB);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, base_map);
glBlendFunc(GL_ONE, GL_SRC_ALPHA);
glBegin();
… draw triangles
glEnd();

This way, I use the alpha in the base map to ensure that the reflection map is only applied to the parts that I want (where the alpha is on). However, when I try to do this w/ multitexturing in a single pass, the result is not what I expect; I set it up like so:

glActiveTextureARB(GL_TEXTURE0_ARB);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, reflection_map);
glBlendFunc(GL_ONE, GL_ZERO);

glActiveTextureARB(GL_TEXTURE1_ARB);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, base_map);
glBlendFunc(GL_ONE, GL_SRC_ALPHA);
glBegin();
… draw triangles (w/ 2 sets of uv coords, everything as it should be in here)
glEnd();

What I get from this is that the base texture is not getting drawn at all in the areas where its alpha is one on the base map, and where it is zero, I see the reflection map blended with the frame buffer color. Any ideas what is up with that? I have tried numerous other combinations of blend-functions, to no avail. I am using a gForce2 under Win2K, so I know the card supports multitexture. Any thoughts are appreciated! Hopefully once I am no longer a newbie to OpenGL (I come from D3D-land), I can be of some help to others myself here )

I haven’t done much with multitexturing myself, but what strikes me in your code is the use of glBlendFunc(). I don’t think the blending is handled on a per texture unit base, but for rasterizer as a whole.
Texture combiners should solve your problem.
What you probably want to look at is the brandnew NVShaderAid toolkit on NVIDIA’s developer relation pages.
More here: http://www.nvidia.com/Marketing/Developer/DevRel.nsf/ProgrammingResourcesFrame?OpenPage

Thanks for the tip, I have found nvidia’s site to be a big help in the past (for D3D and GL stuff), but I hadn’t checked out that demo yet. Also, as for the glendFunc() call, it definately works on each texture unit; the first call affects the blending between the first texture and the frame buffer, then the second call affects the blending of the output of the first texture unit with the second texture.

So far I have to say that I think I like D3D’s multitexture blending syntax a little better; it seems to be much more flexible than GL, but perhaps I just haven’t been using GL long enough )

Thanks again!

Hey DJ!

I hate to break it to ya but Relic is right. the glBlendFunc is for blending different fragments (ie seperate polygons). If you’re using multitexturing, the blending occurs before glBlendFunc does anything. This is why when done it 2 passes you get what you expect and in one pass you get the wrong thing. The device used to combine texture units is the glTexEnvi() call. However this call is severly limiting. You may want to blend the textures using Nvidia’s Register Combiners if glTexEnv isn’t flexible enough.

DJ,

Actually, Relic was correct here. The glBlendFunc call only applies to the post-multi-textured fragment. You use glTexEnv or other “combiner” calls to modify the color of the fragment before it reaches the blend unit. Here’s how you would do this (given your current setup) with GL_NV_register_combiners on NVIDIA GeForce hardware and beyond.

glCombinerParameterNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
// A = reflection_map
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);

// B = base_texture_alpha
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);

// C = base_texture_rgb
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);

// D = 1
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);

// output: spare0 = reflection_map*base_texture_alpha + base_texture_rgb
glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, GL_FALSE, GL_FALSE, GL_FALSE, GL_NONE, GL_NONE, GL_DISCARD, GL_DISCARD, GL_SPARE0_NV);

glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
// write the results as the final texturing output
glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);

glEnable(GL_REGISTER_COMBINERS_NV);

// reflection map
glActiveTextureARB(GL_TEXTURE0_ARB);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, reflection_map);

// base texture
glActiveTextureARB(GL_TEXTURE1_ARB);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, base_map);

draw_triangles();

[This message has been edited by cass (edited 08-11-2000).]

Wow, OK didn’t know that, heheh. Well, that kind of stinks :stuck_out_tongue: So I take it that there is nothing in the standard GL multitexture extension that allows me to control multitexture blending beyond what I can get at with using glTexEnvi()? I think I’m going to go cry now, hehe…