Multiple Lights

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;
}

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…

for (i=0;i<3;i++); ?

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.

Originally posted by s03:
for (i=0;i<3;i++); ?
That is what you get when a pascal programmer is forced to write c. :slight_smile:
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!?

You did not initialize the Color value to vec4(0.0, 0.0, 0.0, 0.0) - that could be the cause.

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.

Originally posted by satan:
[quote]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.
[/QUOTE]:wink:

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?

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.

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;
}

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.