point light with per pixel lighting

There are alot of tutorials that do difuse lighting but none that do point light lighting (or spot light for that matter )with per pixel lighting using ARB_texture_env_combine extension and NOT NVidia`s register combiners.
From a tutorial by Ronald Frazier i found that the ecuation for point light is :
Intensity = 1 - (x2 + y2 + z2)/R2
and by storing the value (x/R)2 + (y/R)2 in texture unit 0 and the value (z/R)2 in texture unit one the ecuation becomes :
Intensity = 1 - Texture0 - Texture 1

He implements this using register combiners .
They may be easier to understant and implement but there are more then 1 video chipset manufacturers.

So anyone who knows how to implement this using
the ARB_texture_env_combine extension pls reply.
Thanx.

the loading of the texture coords, ok, nothing special about it. the combiner stages could be replaced by the arb combiner in the following way:

glActiveTextureARB(GL_TEXTURE0_ARB);   
glEnable(GL_TEXTURE_2D);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
    
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE1_ARB);  
  
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_1D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
    
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);	
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_ONE_MINUS_SRC_COLOR); 

but its only the attenuation. nothing more :slight_smile:

regards,
jan

The intensity is (1-Attenuation)*Color
How do I set the color ?
And how do i multiply the attenuation by the color ?

instead of

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_ONE_MINUS_SRC_COLOR);

use

lTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);

glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);

glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_ONE_MINUS_SRC_COLOR); 
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); 

you did not write anything about a color. mostly per pixel attenuation will be used with normal mapping and a diffuse map, so you would have an additional pass where you could modulate the light color.

in the above example jsut set the color with glColor. instead of modulating with the primary color you can use the texture environment color (GL_CONSTANT_ARB for combiner input) via glTexEnv.

hope this helps.
for further information about arb texture combiners read here .

If you understand how it works with NV register combiners in theory, you should be able to implement it with ARB_texture_env_combine as well. But why do you want to do so? The ARB extension needs more rendering passes, and chipsets that do ONLY have that one are slower than others anyway, so it will get even more slow… and as you said, there is more than one gfx chipsets manufacturer, in fact, there are two :wink: . And both offer better ways to do this, on modern hardware, I would stick with vertex/fragment programs anyway.

http://www.ronfrazier.net/apparition/index.asp?appmain=research/advanced_per_pixel_lighting.html

http://www.ronfrazier.net/apparition/index.asp?appmain=research/per_pixel_lighting.html

I wish people would read the original post instead of quickly posting the first link they know…

Y.

JanHH I didnt figure it out because i had the specification from the link posted by jabe and it doesnt say anywhere about the
GL_TEXTURE0_ARB and GL_TEXTURE1_ARB parameters used in
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE1_ARB);
so i didn` t know how to do the addition.

I got it working but it doesn`t display the correct color of the textures .
Here is the code :

float color = {1,1,1,1};
float pointLightBrightness = 100;

glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture2D);

glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_1D);
glBindTexture(GL_TEXTURE_1D, texture1D);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE1_ARB);

glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvfv(GL_TEXTURE_ENV, GL_PRIMARY_COLOR_ARB, color);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_ONE_MINUS_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);

glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);

glBegin(GL_POLYGON);
for i = all the vertices
{
Vector3 texCoords = ( ( v(i).coord - pointLightPos ) / ( pointLightBrightness * 2.0f ) ) + 0.5f;
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, texCoords.x, texCoords.y);
glMultiTexCoord1fARB(GL_TEXTURE1_ARB, texCoords.z);
glVertex3f(v(i).coord.x, v(i).coord.y, v(i).coord.z);
}
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);

and the second pass:

glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_BLEND);
glBlendFunc(GL_DST_COLOR, GL_ZERO);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_POLYGON);

for i = all the vertices
{
glMultiTexCoord2fARB(GL_TEXTURE0_ARB, v(i).texcoord.x, v(i).texcoord.y);
glVertex3f(v(i).coord.x, v(i).coord.y, v(i).coord.z);
}
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);

Another problem is that the lights attenuation doesnt work, it`s always the same size on all the walls ( the size changes as i change the brightness )

for using GL_TEXTUREx_ARB you need the ARB_texture_env_crossbar extension. on my geforce2 it is not listed in the supported extensions but its working, nevertheless.

in your first pass, you should call glDisable(GL_TEXTURE_1D) because unit 1 is still active. in your second pass, you have to set the texture environment function to modulate or replace in your case.

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

thats what i meant. you have a second pass, so you can modulate the lightcolor here. btw, you forgot to set the color.

second pass:

glActiveTextureARB(GL_TEXTURE0_ARB);
glColor4f(color);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBlendFunc(...);
...

your mistake is, you did not reset the texture environment to fit your needs. you want to modulate the attenuation with a diffusemap, but you use the combiner setup from the first pass to calculate distance attenuation.

maybe reading the red book would help to clear up some opengl basics.

good luck,
jan

Indeed the wrong texture color was because i didn`t disable the 1D texture, thanx.

Now it all works , including light color, but the attenuation still doesn`t work.
The light is always the same size no matter how far I set the light.

I found out why the attenuation wasnt working right. The GL_TEXTURE0_ARB and GL_TEXTURE1_ARB really dont work on geforce 2 so I tried to do the calculations some other way , here it is :

glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex2D);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_ONE_MINUS_SRC_COLOR);

glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_1D);
glBindTexture(GL_TEXTURE_1D, tex1D);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_SUBTRACT_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);

This works just right , the only problem is that now I can`t set the color .
Can the combiners do more than 1 ecuation per texture unit at once ?

no, they can’t.
but you can modulate the light color in the next pass along with your texture.
my geforce2 doesn’t show up the crossbar extension but it works. even ogl does not generate any error :confused:

If i modulate it in the second pass than all the enviroment turns red or whatever color i have.
I only want the corona from the point light to be that color.

second pass:

glColor4fv(lightColor);
glBindTexture(GL_TEXTURE_2D, diffuseMap);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE);
glEnable(GL_BLEND);
glBlendFunc(GL_DST_COLOR, GL_ZERO);
RenderGeometry();

the texture will be modulated by the lightcolor and blended (modulated again) by the color in the framebuffer, which are only greyscale values from pass one.

btw, the texturecoord generation could be done in a vertex program. i implemented exactly this stuff for the ARB combiners some time ago. so i can post the vp if you are interested. normalmapping fits very nicely into this approach, but needs one pass more for the diffuse part.

But by modulating the color with the texture all texture`s surface turns into that color.
With GL_REPLACE only the part lit by the point light would remain the color specified.

I just read somewhere that the GL_TEXTURE_ARB parameters arent supported by any of the NVidias chipsets.

And yes I would be interested in the vp for automatic texture gen if u could.

I once decided to forget everything about ARB_texture_env_combine and NV_register_combiners and switched to ARB_vertex_program and ARB_fragment_program and found live to be much easier. Why do you stick with these really old and deprecated ARB extensions? Even if it is for something commercial, most people will have a gf fx or something like that soon, and I think one could really start ignoring the gf 4s that are still there… but maybe, I am wrong.

The NV_texture_env_combine4 extension is what allows you to use GL_TEXTURE[i]_ARB on NVidia cards. The same functionality is now also part of the core (not sure which version, 1.4 I think), so it should be fairly safe to rely on it.

– Tom

Please stay on topic and reply to my question.
Instead of telling me what i should use and that i should buy a newer video card to support some extension u can help me to solve my problem using what I have.

JanHH this is the first time I am using texture combiners so it seems logic to take it one at a time.
The vertex and fragment programs are more advanced and not too well documented so i first wanna learn how to use the old and deprecated ARB_texture_env.

@janhh: i think you are wrong. personally i use a geforce2mx for about 5 years now. i like my system :slight_smile:
yes, arb_fp makes life much easier, but when developing commercial application, not games, you have to fit your product into the consumer market. it’s amazing, what hardware are people still using.

@undertaker: GL_MODULATE modulates the texture completely with the primary color, right. but the blending into the framebuffer modulates it again with the pointlight intensity values. thats why you need two passes.

the vertex program comes here:

!!ARBvp1.0
OPTION ARB_position_invariant;

//per-vertex inputs
ATTRIB inPos    = vertex.position;
ATTRIB inCol    = vertex.color;

//light params
PARAM lightPos     = program.env[0];
PARAM lightParams  = program.env[1];

PARAM constVec = {0.5,0.5,0.5,1};

TEMP vec0;
ALIAS eyePos   = vec0;
ALIAS lightVec = vec0;
ALIAS texVec   = vec0;

//per-vertex outputs
OUTPUT outCol  = result.color;
OUTPUT outTex1 = result.texcoord[0];
OUTPUT outTex2 = result.texcoord[1];

//calculate light direction and normalize
SUB lightVec, lightPos, inPos;
MAD texVec, lightParams.y, lightVec, constVec;
MOV outTex1.x, texVec.x;
MOV outTex1.y, texVec.y;
MOV outTex2.x, texVec.z;
MOV outCol, inCol;

END

you have to pass to local vp parameters into this program.
param 1 - lightposition in object space
param 2 - lightparameters {radius, 1/(2*radius)}

of course, you can do the radius divide in the vp, too. but i wanted so save some instructions :slight_smile:

float lightParams[4] = {0,0,0,0};
float localLightPos[4];

lightParams[0] = lightRadius;
lightParams[1] = 1.0f / (lightParams[0]*2);

transformInverse(localLightPos, lightPos, objectMatrix);

glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 0, localLightPos);
glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, 1, lightParams); 
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vp);

RenderGeometry();

greets,
jan

Thanx alot.

One more question , what is the deal with the
GL_SOURCE2_RGB_ARB and GL_OPERAND2_RGB_ARB parameters , they aren`t listed in the ARB_texture_env specification.
What cards support them and how can i use them ?