PDA

View Full Version : point light with per pixel lighting



Undertaker
06-28-2004, 11:38 AM
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.

jabe
06-28-2004, 01:50 PM
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 :)

regards,
jan

Undertaker
06-28-2004, 02:14 PM
The intensity is (1-Attenuation)*Color
How do I set the color ?
And how do i multiply the attenuation by the color ?

jabe
06-28-2004, 03:00 PM
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 (http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_env_combine.txt) .

JanHH
06-28-2004, 07:31 PM
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 ;) . And both offer better ways to do this, on modern hardware, I would stick with vertex/fragment programs anyway.

heppe
06-28-2004, 11:46 PM
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

Ysaneya
06-28-2004, 11:53 PM
I wish people would read the original post instead of quickly posting the first link they know..

Y.

Undertaker
06-29-2004, 05:57 AM
JanHH I didn`t figure it out because i had the specification from the link posted by jabe and it doesn`t 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 light`s attenuation doesn`t work, it`s always the same size on all the walls ( the size changes as i change the brightness )

jabe
06-29-2004, 07:07 AM
for using GL_TEXTUREx_ARB you need the ARB_texture_env_crossbar (http://oss.sgi.com/projects/ogl-sample/registry/ARB/texture_env_crossbar.txt) 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

Undertaker
06-29-2004, 08:06 AM
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.

Undertaker
06-29-2004, 01:36 PM
I found out why the attenuation wasn`t working right. The GL_TEXTURE0_ARB and GL_TEXTURE1_ARB
really don`t 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 ?

jabe
06-29-2004, 01:50 PM
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:

Undertaker
06-29-2004, 02:02 PM
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.

jabe
06-29-2004, 02:54 PM
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.

Undertaker
06-29-2004, 03:38 PM
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<n>_ARB parameters aren`t supported by any of the NVidia`s chipsets.

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

JanHH
06-29-2004, 08:39 PM
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.

Tom Nuydens
06-29-2004, 11:44 PM
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

Undertaker
06-29-2004, 11:53 PM
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.

jabe
06-30-2004, 12:03 AM
@janhh: i think you are wrong. personally i use a geforce2mx for about 5 years now. i like my system :)
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;

ENDyou 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 :)


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_AR B, 0, localLightPos);
glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_AR B, 1, lightParams);
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vp);

RenderGeometry();greets,
jan

Undertaker
06-30-2004, 09:16 AM
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 ?

jabe
06-30-2004, 10:25 AM
they are listed:

SOURCE2_RGB_ARB 0x8582
SOURCE2_ALPHA_ARB 0x858A
OPERAND2_RGB_ARB 0x8592
OPERAND2_ALPHA_ARB 0x859A

operand2 is used for combiner mode GL_INTERPOLATE_ARB. as the name says, this mode interpolates between operand0 and operand1. operand2 is the weight.

you can use it as usual. an use would be reflection mapping with a per pixel reflection map. you can use the alpha of your diffuse map to say, how much the material is reflecting the environment at one point. use GL_INTERPOLATE_ARB to interpolate between the rgb values of the diffusemap (base texture) and the environment map. operand2 is set to the alpha value of the base texture.