PDA

View Full Version : Multiple Lights



satan
06-15-2006, 07:39 PM
Hi everyone,

I am just starting with GLSL and wrote a simple vertex lighting shader that works with one light source. Now I tried to make it work with multiple lights but I only get the result that my scene is lit by only one light namely the last light in the for-loop.

Thanks for any help and here is the code.

Vertex shader:

vec3 Position;
vec3 Light;
vec3 Normal;
vec4 Ambient;
vec4 Diffuse;
float fDiffuse;
vec4 Color;
int i;

void main(void)
{
// transform vertex to eye-space
gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
Position = vec3(gl_ModelViewMatrix * gl_Vertex);
// transform normal
Normal = normalize(gl_NormalMatrix * gl_Normal);
for (i=0;i<3;i++);
{
// calculate light to vertex vector
Light = vec3(normalize(vec3(gl_LightSource[i].position) - Position));
// calculate ambient term
Ambient = gl_FrontMaterial.ambient * gl_LightSource[i].ambient;
// calculate diffuse term
fDiffuse = clamp(dot(Normal, Light), 0.0, 1.0);
Diffuse = fDiffuse*(gl_LightSource[i].diffuse * gl_FrontMaterial.diffuse);
// add diffuse and ambient
Color += Diffuse + Ambient;
}
gl_FrontColor = Color;
}Fragment shader:

void main(void)
{
gl_FragColor = gl_Color;
}

Mars_999
06-15-2006, 08:12 PM
What hardware are you using? IIRC loops aren't available on some older hardware... Try unrolling the loop and see what happens... For now that is my best guess. BTW did you setup your light parameters for lights 1 and 2. LIGHT0 isn't the same as 1-7...

Flavious
06-15-2006, 08:23 PM
for (i=0;i<3;i++); ?

Mars_999
06-15-2006, 08:33 PM
Originally posted by s03:
for (i=0;i<3;i++); ? Nice catch. I really hate the small font that the code blocks uses. Hard to pick up on those errors.

satan
06-15-2006, 11:51 PM
Originally posted by s03:
for (i=0;i<3;i++); ? That is what you get when a pascal programmer is forced to write c. :)
Well spotted.
But now I have another problem. It only works for up to 3 light sources. I have 4 lights in my test scene. Letting i run from 0 to 3 I see light one to three, letting it run from 1 to 4 I get light two to four. Letting it run from 0 to 4 gives me light one and four!?

k_szczech
06-16-2006, 11:26 AM
You did not initialize the Color value to vec4(0.0, 0.0, 0.0, 0.0) - that could be the cause.

satan
06-16-2006, 12:08 PM
Originally posted by k_szczech:
You did not initialize the Color value to vec4(0.0, 0.0, 0.0, 0.0) - that could be the cause. That is not the problem, but thanks anyway.
I unrolled the loop and it works as it should.
This is on a Geforce 6600 GT, driver version 87.62 on Ubuntu Linux.

Mars_999
06-16-2006, 01:48 PM
Originally posted by satan:

Originally posted by k_szczech:
You did not initialize the Color value to vec4(0.0, 0.0, 0.0, 0.0) - that could be the cause. That is not the problem, but thanks anyway.
I unrolled the loop and it works as it should.
This is on a Geforce 6600 GT, driver version 87.62 on Ubuntu Linux. ;)

satan
06-16-2006, 03:56 PM
I just checked it also works if I use two for-loops. One from 0 to 2 the other from 2 to 4. To me it looks like there is something horribly wrong.
Can anyone explain what is happening?

Overmind
06-17-2006, 05:58 AM
Is there any particular reason why all your variables are global? Have you tried making them local to your main function?

It shouldn't be the cause of the error, but you never know...

If it really works with two loops and identical code inside the loops, then it's most likely a driver bug, and it may be possible that making your variables global triggers the bug.

satan
06-17-2006, 06:58 AM
It works if I make the variables local. But it does not work if I pass the number of lights as a uniform variable.
But if I use some 'tricks' I get it to work with the dynamic loop.
Here is the non working shader:

uniform int Lights;

void main(void)
{
vec3 Position;
vec3 Light;
vec3 Normal;
vec4 Ambient;
vec4 Diffuse;
float fDiffuse;
vec4 Color;
int i;

Color = vec4(0.0, 0.0, 0.0, 0.0);
// transform vertex to eye-space
gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
Position = vec3(gl_ModelViewMatrix * gl_Vertex);
// transform normal
Normal = normalize(gl_NormalMatrix * gl_Normal);
for (i=0;i<Lights;i++)
{
// calculate light to vertex vector
Light = vec3(normalize(vec3(gl_LightSource[i].position) - Position));
// calculate ambient term
Ambient = gl_FrontMaterial.ambient * gl_LightSource[i].ambient;
// calculate diffuse term
fDiffuse = clamp(dot(Normal, Light), 0.0, 1.0);
Diffuse = fDiffuse*(gl_LightSource[i].diffuse * gl_FrontMaterial.diffuse);
// add diffuse and ambient
Color += Diffuse + Ambient;
}
gl_FrontColor = Color;
}And here is the working version:

uniform int Lights;

void main(void)
{
vec3 Position;
vec3 Light;
vec3 Normal;
vec4 Ambient;
vec4 Diffuse;
float fDiffuse;
vec4 Color;
int i;

Color = vec4(0.0, 0.0, 0.0, 0.0);
// transform vertex to eye-space
gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
Position = vec3(gl_ModelViewMatrix * gl_Vertex);
// transform normal
Normal = normalize(gl_NormalMatrix * gl_Normal);
if (Lights<4)
{
for (i=0;i<Lights;i++)
{
// calculate light to vertex vector
Light = vec3(normalize(vec3(gl_LightSource[i].position) - Position));
// calculate ambient term
Ambient = gl_FrontMaterial.ambient * gl_LightSource[i].ambient;
// calculate diffuse term
fDiffuse = clamp(dot(Normal, Light), 0.0, 1.0);
Diffuse = fDiffuse*(gl_LightSource[i].diffuse * gl_FrontMaterial.diffuse);
// add diffuse and ambient
Color += Diffuse + Ambient;
}
}
else
{
for (i=0;i<4;i++)
{
// calculate light to vertex vector
Light = vec3(normalize(vec3(gl_LightSource[i].position) - Position));
// calculate ambient term
Ambient = gl_FrontMaterial.ambient * gl_LightSource[i].ambient;
// calculate diffuse term
fDiffuse = clamp(dot(Normal, Light), 0.0, 1.0);
Diffuse = fDiffuse*(gl_LightSource[i].diffuse * gl_FrontMaterial.diffuse);
// add diffuse and ambient
Color += Diffuse + Ambient;
}
}
gl_FrontColor = Color;
}