Advertisement

Per pixel light attenuation and bump mapping

Started by June 21, 2004 05:48 PM
36 comments, last by vincoof 20 years, 5 months ago
Yes it can be done using another texture unit, but most of the time it can also be done without :)
Can you post the texture environment functions you are using ? (I mean each call to glActiveTexture followed by calls to glTexEnv, from GL_TEXTURE0_ARB to GL_TEXTURE3_ARB)
glActiveTextureARB(GL_TEXTURE2_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textures[pFace->textureID]);

if(g_Attenuation){
GLfloat light_center[] = { LightPosition.x, LightPosition.y, LightPosition.z };
enableAttenuation3D(GL_TEXTURE3_ARB, tex3Dattn, light_radius, light_center);
}

//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) ;


then i draw with glDrawRangeElements and disable textures :)
Advertisement
I think the best way is computing ambient during attenuation, thanks to ATI_texture_env_combine3 or NV_texture_env_combine4.
Replace the function enableAttenuation3D with :
void enableAttenuation3D(GLenum texturestage, GLuint textureid, GLfloat radius, GLfloat center[3], GLfloat ambient[4]){  GLfloat eqS[4] = { 0, 0, 0, 0 };  GLfloat eqT[4] = { 0, 0, 0, 0 };  GLfloat eqR[4] = { 0, 0, 0, 0 };  glActiveTextureARB(texturestage);  glBindTexture(GL_TEXTURE_3D_EXT, textureid);  glEnable(GL_TEXTURE_3D_EXT);  glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, ambient);  if (NV_texture_env_combine4_supported)  {    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV); // mandatory    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD); // mandatory    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); // optional    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); // optional    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); // optional    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); // optional    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB); // optional    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR); // mandatory    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_ZERO); // optional    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_ONE_MINUS_SRC_COLOR); // optional  }  else if (ATI_texture_env_combine3_supported)  {    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); // mandatory    glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE_ADD_ATI); // mandatory    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); // optional    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); // optional    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); // optional    glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_CONSTANT_ARB); // optional    glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR); // mandatory  }  eqS[0] = 0.5f/radius;  eqS[3] = 0.5f-0.5f*center[0]/radius;  eqT[1] = 0.5f/radius;  eqT[3] = 0.5f-0.5f*center[1]/radius;  eqR[2] = 0.5f/radius;  eqR[3] = 0.5f-0.5f*center[2]/radius;  glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);  glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);  glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);  glTexGenfv(GL_S, GL_EYE_PLANE, eqS);  glTexGenfv(GL_T, GL_EYE_PLANE, eqT);  glTexGenfv(GL_R, GL_EYE_PLANE, eqR);  glEnable(GL_TEXTURE_GEN_S);  glEnable(GL_TEXTURE_GEN_T);  glEnable(GL_TEXTURE_GEN_R);}


and then call it using something like :
if(g_Attenuation){GLfloat light_center[] = { LightPosition.x, LightPosition.y, LightPosition.z };GLfloat ambient_color[] = { Ambient.red, Ambient.green, Ambient.blue, 1.f };enableAttenuation3D(GL_TEXTURE3_ARB, tex3Dattn, light_radius, light_center, ambient_color);}


The problem with this method is that ambient lighting will be activated only when attenuation is activated too.

in this case, you can just copy / paste the glTexEnv calls (the ones I've just posted) for GL_TEXTURE2_ARB.

[edit] this ambient step is the easiest to do, but not the best. To get advantage of real ambient lighting, you have to break all your texenv calls. May I post how to do ?
@vincoof: thank you :D now i can combine these methods and obtain more kinds of effects ^___^
@vincoof: last question: if i try my demo on a gefo3 and activate the ambient/attenuation light, EVERYTHING appears coloured, even if i change the light radius. instead, on my ati, only the light is coloured :/
Could you be more precise please ? I don't really imagine what's happening. If you could post screenshots that'd be great.
Advertisement
this is on my GeForce 3 Ti200, everything is red:
http://www.neoborn.com/users/b3rs3rk/screen-gefo1.JPG

and this is on my Ati 9000, only the light is red:
http://www.neoborn.com/users/b3rs3rk/Screen5.JPG
You use a red ambient light, right ?
In that case, the GeForce behaviour is the correct one.
Maybe I did a mistake in the ATi code, or maybe the driver has an issue.

Anyway, I think it's time to setup real ambient lighting, don't you think ?

Are you ready ? ^_^
Quote: Original post by vincoof
this ambient step is the easiest to do, but not the best. To get advantage of real ambient lighting, you have to break all your texenv calls. May I post how to do ?


yeah, post it :D
First things first, let's write down what happens from what you've posted a bit before :

TEXTURE0 : pass the normalized light vector, sampled from texture unit 0. The result is L

TEXTURE1 : compute dot product with the texel sampled from texture unit 1 (the normal map), and with the light vector (which is actually in PREVIOUS). The result is (N dot L), aka the diffuse contribution

TEXTURE2 : modulate the result from previous texture unit (diffuse contribution) with the texel sampled from texture unit 2 (decal map). The result is diffuse_intensity*decal

TEXTURE3 (if enabled) : modulate the result from previous texture unit (diffuse_intensity*decal) with the texel sampled from texture unit 3 (attenuation map). The result is diffuse_intensity*decal*attn

(note : I don't take into account the ambient term in TEXTURE3 because I'm killing it to set it somewhere else)

Is that ok for now ?

So, with the current scheme, the result is :
diffuse_intensity*decal*attn

And with the slight change I proposed a bit sooner, ambient like it was computed in TEXTURE3 means the result was :
(diffuse_intensity*decal*attn)+ambient

But in fact, real ambient lighting should be computed as :
((diffuse_intensity*attn)+ambient)*decal

For this to work, texture environment functions must be changed.

This topic is closed to new replies.

Advertisement