Specular and cube map

I have a lightmap, a texture with an alpha channel, and a cubemap. I want the cubemap to show through the transparent pixels in the texture. Can I draw these using only 3 texture units? What order should I draw the texture and cubemap in? How do I make the cubemap shine through the transparent pixels of the texture, without using two passes?

If you want to do
texture_alpha * (lightmap_color * cubemap_color) + texture_color * (1-texture_alpha)

glActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

glActiveTexture(GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glActiveTexture(GL_TEXTURE2);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);

If you want to do
(1 - texture_alpha) * (lightmap_color * cubemap_color) + texture_color * texture_alpha

glActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

glActiveTexture(GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glActiveTexture(GL_TEXTURE2);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);

Thank you for your comment.

One set of commands shows only the solid cubemap. The other set shows only the texture with no cube map. I have some textures in the scene which do have alpha channels.

Let’s simplify:

glActiveTexture(GL_TEXTURE0)
glEnable GL_TEXTURE_2D
glbindtexture GL_TEXTURE_2D,texture
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)
glActiveTexture(GL_TEXTURE1)
glEnable GL_TEXTURE_CUBE_MAP
glbindtexture GL_TEXTURE_CUBE_MAP,cubemap

Then I add the combiner commands for the cubemap to follow.

The first set of combiner instructions you gave makes only the cubemap visible. Your second set of instructions makes only the texture visible.

I am not using any blending or anything special on the texture. By temporarily turning glalphatest on, I was able to verify that the textures do have an alpha channel that is making its way into OpenGL. What am I missing here?

Originally posted by V-man:
[b] If you want to do texture_alpha * (lightmap_color * cubemap_color) + texture_color * (1-texture_alpha)

glActiveTexture(GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

glActiveTexture(GL_TEXTURE1);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glActiveTexture(GL_TEXTURE2);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA);

[/b]

I think that should be:
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS);

That’s assuming the alpha is in texture stage 1 and texture stage 0 has an alpha of 1 (or no alpha channel). Otherwise you could crossbar it to texture 1 or whatever.

However, I suspect that what you want is not to iterpolate but do a multiply and add which, ever so absurdly, you cannot do with 3 units.

I’ve never understood what whoever wrote the spec was ever thinking when they didn’t put in the equivalent of MAD and yet put in things like interpolate and dot3…??? I’ve been ranting about this for years now. I mean really, what?!

I think that should be:
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS);

Stage 2 contains the texture and alpha so I think I have it correct.
The math for INTERPOLATE is
Arg0  Arg2 + Arg1  (1 − Arg2)


The first set of combiner instructions you gave makes only the cubemap visible. Your second set of instructions makes only the texture visible.

texture_alpha * (lightmap_color * cubemap_color) + texture_color * (1-texture_alpha)

so your alpha is all 1.0

Turning on alphatest doesn’t necessarily mean a texture has alpha.
Alphatest processes fragments. All fragments have color, alpha, depth, stencil.
If your texture is RGB, GL inputs 1.0 for alpha

The texture is RGBA. It is a wall with a window in it. The alpha channel is about 64,64,64 where the windows are, and 255,255,255 everywhere else. I verified this by turning on alpha testing and/or alpha blending, and seeing that the parts I was expecting to be see-through looked that way in OpenGL.

Thank you for your input. I got the cubemaps partially working. They appear correctly, but the lightmap doesn’t affect them.

 [img]http://www.leadwerks.com/post/spec.jpg[/img]

If I can just get the lightmap to darken the cubemap as well, I will be done.

The lightmap is in stage 0. The texture is stage 1. The cubemap is stage 2.

Here are the parameters I used:

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE)
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE)
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_PREVIOUS)
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR)
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR)
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA)

I suppose what I want is this:

texture_alpha * lightmap_color * texture_color + (1-texture_alpha) * lightmap_color * cubemap_color

Hmmm…here are the possible equations:

REPLACE Arg0
MODULATE Arg0 * Arg1
ADD Arg0 + Arg1
ADD_SIGNED_ARB Arg0 + Arg1 - 0.5
SUBTRACT_ARB Arg0 - Arg1
INTERPOLATE_ARB Arg0 * (Arg2) + Arg1 * (1-Arg2)

I can use GL_PREVIOUS to combine the texture+lightmap with the cubemap, but I need some way to get the lightmap in there on the cubemap, as well. Is it impossible to do this in a single pass?

texture_alpha * lightmap_color * texture_color + (1-texture_alpha) * lightmap_color * cubemap_color

simplifies to

(texture_alpha * texture_color + (1-texture_alpha) * cubemap_color) * lightmap_color

so it becomes

stage 0 : replace
stage 1 : interpolate
stage 2 : modulate

Thanks, that works well for my lightmapped surfaces. However, some of my surfaces use hardware (vertex) lights, not lightmaps. How can I get vertex colors to affect the combined cubemap?

The gascans in the above screenshot, for instance, are lit with hardware lights. If I try to combine a cubemap with their texture, the cubemap parts will be full-bright.

Originally posted by V-man:
Stage 2 contains the texture and alpha so I think I have it correct.
The math for INTERPOLATE is
Arg0  Arg2 + Arg1  (1 − Arg2)

Mate, I know how interpolate works. Perhaps we had different interpretations of what the op was trying to do? I would have assumed he wanted: lightdiffuse + specular_levelcubemap. The code you posted, with the stages in the order in which the op gave the textures, and with the change I suggested, would give: lightdiffusealpha + cubemap*(1-alpha), which seems is what he got. Apparently this met the OPs requirements as originally stated, though under-specified.

Now, if the cubemap is a reflection map, then my original assumption ought to be correct. Lightmaps are only suitable for diffuse lighting so at this point I have absolutely no idea what either of you are on about.

To Madoc,
I’m guessing that in the screen shot he had, the 2D texture was the brick wall and window frames. The cubemap is for reflection on the glass.
He is using the lightmap to make shadows on the 2D and the cubemap.

If you are using hw lights, then instead of the lightmap, you use GL_PRIMARY_COLOR where
GL_PRIMARY_COLOR = material * light

I don’t understand where to use GL_PRIMARY COLOR. For INTERPOLATE, the equation only has three variables:

Arg0 * (Arg2) + Arg1 * (1-Arg2)

Arg0 is the cubemap color, arg2 is the texture alpha, and arg1 is the result of the texture+lighting. There still won’t be any lighting on the cubemap.

No, it’s stage 2, modulate

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);

but you still need to bind some texture to stage 2, else the unit is in a invalid state.

Brilliant! So you just add a dummy texture, and give it combiner parameters that don’t even consider the dummy texture itself. I’ll try it out.

It works great. Now I can treat vertex-lit objects just like lightmapped objects. I can even use GL_RGB_SCALE to make the vertex lights “overbrightened”.

This is a good thread for anyone wishing to do the same thing. Thank you for your advice!