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
So you may ask : how ? Is there any trick needed ?
Yes, a "trick" is needed : crossbar. Cross-bar texture lookup allows to use a texel from another texture unit than the current texture unit.

Crossbar is available on cards that support ARB_texture_env_crossbar or NV_texture_env_combine4, that is the majority of ATi hardware (all Radeon) and nVidia hardware (all GeForce, all Quadro, all TNT).

Let's rewrite the texture environment functions you used with some other syntax :
reminder : it computes diffuse_intensity*decal*attn
TEXTURE UNIT 0 : REPLACE(TEXTURE) == L
TEXTURE UNIT 1 : DOT3(PREVIOUS,TEXTURE) == L dot N
TEXTURE UNIT 2 : MODULATE(TEXTURE,PREVIOUS) == decal*(L dot N)
TEXTURE UNIT 3 : MODULATE(TEXTURE,PREVIOUS) == attn*decal*(L dot N)

Now, to compute the new lighting equation that includes ambient, the goal is : ((diffuse_intensity*attn)+ambient)*decal
With texture environment crossbar it can be computed using the following configuration :
TEXTURE UNIT 0 : DOT3(TEXTURE,TEXTURE1) = L dot N
TEXTURE UNIT 1 : MODULATE(TEXTURE3,PREVIOUS) = attn*(L dot N)
TEXTURE UNIT 2 : ADD(CONSTANT,PREVIOUS) = ambient+attn*(L dot N)
TEXTURE UNIT 3 : MODULATE(TEXTURE2,PREVIOUS) = decal*(ambient+attn*(L dot N))

That works when attenuation is enabled, but since you have an option to disable attenuation, here's the setup for non-attenuated lighting with ambient. The goal is : (diffuse_intensity+ambient)*decal
TEXTURE UNIT 0 : DOT3(TEXTURE,TEXTURE1) = L dot N
TEXTURE UNIT 1 : ADD(CONSTANT,PREVIOUS) = ambient+(L dot N)
TEXTURE UNIT 2 : MODULATE(TEXTURE,PREVIOUS) = decal*(ambient+(L dot N))

Are you still ok ?

[Edited by - vincoof on June 26, 2004 9:45:20 PM]
Now, on to the code :)

I'm just rewriting things based on your code.
Old code :
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 0glActiveTextureARB(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)*colorglTexEnvi(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 1glActiveTextureARB(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) ;


New code :
GLfloat ambient_color[4] = { Ambient.red, Ambient.green, Ambient.blue, 1.f };glActiveTextureARB(GL_TEXTURE2_ARB);glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, m_textures[pFace->textureID]);if(g_Attenuation){glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD) ;glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT) ;glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS) ;glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, ambient_color);}else{glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);}if(g_Attenuation){GLfloat light_center[] = { LightPosition.x, LightPosition.y, LightPosition.z }; enableAttenuation3D(GL_TEXTURE3_ARB, tex3Dattn, light_radius, light_center);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_TEXTURE2_ARB) ;glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS) ;}//Bind normalisation cube map to texture unit 0glActiveTextureARB(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)*colorglTexEnvi(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_TEXTURE) ;glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1_ARB) ;//Bind normal map to texture unit 1glActiveTextureARB(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);if(g_Attenuation){glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE) ;glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE3_ARB) ;glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS) ;}else{glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD) ;glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT) ;glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS) ;glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, ambient_color);}


and please post screenshots when it's done ;)
Advertisement
after an entire night of constant attempts, i've made attenuation light work, see it here:
http://www.neoborn.com/users/b3rs3rk/attenuation.jpg

but i still cant combine ambient light with attenuation :/ what i have now is:
http://www.neoborn.com/users/b3rs3rk/amb_atten.jpg

i wanted something like this:
http://www.neoborn.com/users/b3rs3rk/ambient.jpg
(this is a screen made with the texture3d code with the broken ATI register combiners <--pratically useless, but gives the point :/)
Quote: Original post by b3rs3rk
i wanted something like this:
http://www.neoborn.com/users/b3rs3rk/ambient.jpg

In fact, this is not the result you *should* have. This is not real ambient lighting.

Quote: Original post by b3rs3rk
after an entire night of constant attempts, i've made attenuation light work, see it here:
http://www.neoborn.com/users/b3rs3rk/attenuation.jpg

Is this what you get with the code I've posted above ? Or did you change the texenv calls a bit ?
It looks like the following is computed : (diffuse_intensit+ambient)*attn*decal
instead of : ((diffuse_intensity*attn)+ambient)*decal

Just a quick test : setup ambient_color to {0,0,0,0} --> it should give the same result as if ambient was disabled. If results are different, the's definately a problem in the texenv calls.
infact, i've changed the code a bit... i simply compute diffuse_intensit*attn*decal.
how can i obtain the other effect (the one i should not have) ?
I'm not quite sure to understand. Why do you want to make the effect that "should" not be rendered ?

Anyway, this is done by : (diffuse_intensity*attn*decal)+ambient

But while it may look somehow good in your example, in most cases it will look crap. It tends to make scenes grey-ish (when using a grey ambient color, which is the case most of the time) and too bright.
Advertisement
maybe the screenshot is not so accurate. pratically i want a simple coloured light,nothing more..
if i use the attenuation code u gave me(again, thanks!!), i have a (for example) red light but the rest of the room is black.
all i need is a simple way to render a pointlight and manage its brightness and its color, with and/or without attenuation :D
With brightness and color, you have to setup this :
(diffuse_contribution*attn*light_diffuse_color+ambient_color)*decal

And the brightness is ruled by "ambient_color" and the color of the light is ruled bu "light_diffuse_color".

This can be done using the following scheme :
TEXTURE UNIT 0 : DOT3(TEXTURE,TEXTURE1) with TEXTURE=L and TEXTURE1=N
TEXTURE UNIT 1 : MODULATE(CONSTANT,PREVIOUS) with CONSTANT=light_diffuse_color
TEXTURE UNIT 2 : MAD(TEXTURE3,PREVIOUS,CONSTANT) with TEXTURE3=attn and CONSTANT=ambient_color
TEXTURE UNIT 3 : MODULATE(TEXTURE2,PREVIOUS) with TEXTURE2=decal

The only trick now is to setup the MAD function (MAD stands for "Multiply and ADd"). In fact : MAD(x,y,z) = x*y+z
(The MAD function is very popular in vertex and fragment programs).
This MAD operation can either be computed using the ATI_texture_env_combine3 extension or using the NV_texure_env_combine4 extension.

I won't write down the code for setting up glTexEnv calls, because I think you can do it yourself :)
And if you doubt about your code, feel free to post it when it's done so that we can validate it.

This topic is closed to new replies.

Advertisement