Advertisement

Per pixel colored light

Started by July 13, 2004 01:22 PM
9 comments, last by Lutz 20 years, 4 months ago
i have this situation: GL_TEXTURE0 is my cube map GL_TEXTURE1 is my normal map GL_TEXTURE2 is my decal texture i have set up combiners and now i've got a nice bump mapping effect with per pixel lighting. But the light is WHITE (pratically it's a white SPOTLIGHT..is a simple source of white diffuse light with no attenuation,it's not ambient light). How can i create a colored light?
Multiply resulting color with light color. Something like:
Final_color = ambient_color + light_color * (L dot N) * diffuse_texture.

Full equation is a "bit" longer but you'll get the idea.
You should never let your fears become the boundaries of your dreams.
Advertisement
Which texenv's are configured to TEXTURE0, TEXTURE1 and TEXTURE2 ?
//Bind normalisation cube map to texture unit 0
glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, m_normcubemap[pFace->textureID]);
glEnable(GL_TEXTURE_CUBE_MAP);

//Set up texture environment to do (tex0 dot tex1)*color
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE) ;
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE) ;

//Bind normal map to texture unit 1
glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, m_normalmap[pFace->textureID]);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB_ARB) ;
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS) ;
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE) ;

glActiveTextureARB(GL_TEXTURE2_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textures[pFace->textureID]);
Ok, this is what you can do :

texenv of TEXTURE0 : DOT3(TEXTURE0,TEXTURE1)
texenv of TEXTURE1 : MODULATE(PREVIOUS,TEXTURE2)
texenv of TEXTURE3 : MODULATE(PREVIOUS,PRIMARY_COLOR) or MODULATE(PREVIOUS,CONSTANT) as you wish... (I prefer the former)

this, of course, assumes you can use GL_ARB_texture_env_crossbar or GL_NV_texture_env_combine4 in order to use the crossbar functionality.

And if you can use the NV_texture_env_combine4 functionality or the ATI_texture_env_combine3 functionality, you can use the texenv of TEXTURE3 to compute ambient on top of diffuse, something like :
texenv of TEXTURE3 : MAD(PREVIOUS,PRIMARY_COLOR,CONSTANT)
with PRIMARY_COLOR being the diffuse color and CONSTANT being the ambient color.
2 remarks:

1) If I read your source correctly, you do (tex0) dot (tex1), where tex0 is the normalization cubemap and tex1 is the normal map. This does not make sense. tex0 should be the light in tangent/object space (whatever you've chosen), oh, well, unless you've chosen the cubemap 3D texture coordinates to be the light vector. Hmmm, probably you did that...

2) You're wasting one texture unit:
Texture unit 0 just loads a texture, texture unit 1 does the dot product. This can be done using only one texture unit. I'll try to remember how it works, it might be incorrect. Can anyone correct plz.?

// Bind all textures
glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, m_normcubemap[pFace->textureID]);
glEnable(GL_TEXTURE_CUBE_MAP);

glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, m_normalmap[pFace->textureID]);
glEnable(GL_TEXTURE_2D);

glActiveTextureARB(GL_TEXTURE2_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textures[pFace->textureID]);

// Texture unit 0: (tex0 dot tex1)*color
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB_ARB) ;
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE0);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1);

// Texture unit 1: (Result of unit 0) * decal
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE2);

Lutz
Advertisement
1) of course he sends the light vector as texture coordinates :) And of course this vector is computed in tangent space too.

2) You're talking about crossbar, and while it's true it would work, it's not "saving" any texture unit because with texture combiners you have to use all texture stages (unless you need some extra processing like I proposed).

And as a last note, this code is wrong :
// Texture unit 1: (Result of unit 0) * decalglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE2);

it should be :
// Texture unit 1: (Result of unit 0) * decalglTexEnvi(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_TEXTURE2);

Cheers
probably i'm doing some mistakes, because if i use that code i have no bump mapping, only the decal texture with some colors on (light green, magenta etc... basically the colors of the normal map)
Sure because you have to call glActiveTextureARB(GL_TEXTURE0_ARB) before the first texenv set and call glActiveTextureARB(GL_TEXTURE1_ARB) before the second texenv set.
And at last, call this :
glActiveTextureARB(GL_TEXTURE2_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);

this stage is where I recommend you to compute diffuse colouring (and ambient lighting, optionally) but, obviously, actually it's not computing anything. It's just passing the colour from the previous stage to the next one.
sometimes i feel so stupid... :P

This topic is closed to new replies.

Advertisement