OpenGL: Passing a point light in a fragment shader

I don't know if there are any OpenGL gurus here, but I'm stumped. I'm trying to pass a point light to a CalcPoint function in my fragment shader. Here's the relevant code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#define TOTAL_LIGHTS 2
struct PLight
{
    vec4 pos;

    vec4 diff;
    vec4 spec;
    vec4 amb;

    float con;
    float lin;
    float quad;
};

layout(std140) uniform Light
{
    PLight pLights[TOTAL_LIGHTS];
}light;

vec3 CalcPoint(in PLight p) 
{
    ...
}


When I pass in the point light from main using hard coded values everything works fine.

1
2
3
4
5
6
7
void main()
{
    ...
    pointLight += CalcPoint(light.pLights[0]);
    pointLight += CalcPoint(light.pLights[1]);
    ...
}


But, when I try to use a loop, the second light is not calculated correctly.

1
2
for(int i = 0; i < TOTAL_LIGHTS; i++)
    pointLight += CalcPoint(light.pLights[i]);


Any thoughts as to why the loop is not working?
Thanks
Last edited on
Hi, I was also curious as to why that didn't work.
I found this: http://stackoverflow.com/questions/16039515/glsl-for-loop-array-index
The answer seems to be that older drivers require array indices to be constants, so having a for loop of ints like that won't work.

It might be helpful (for others, I personally don't know) to say what shader version you're using and what opengl version you have. I think the SO's OP was using opengl 4 with shader version 330.

So try to update your drivers, I assume they're Intel? Never really liked Intel support, they always seem to be lagging behind nvidia or amd.

If this helped be sure to update your OpenGL forum post too ;)
Last edited on
Thanks for the reply. I hacked at this most the this morning and I'm no closer to a resolution. I've tried it on three different computers. My old laptop running Win 7 and almost GL 3.1, another laptop with Win 8 and GL 4.1 and a desktop with Win 10 and GL4.5. Each is a little different. The second laptop just renders everything black after adding the second light no matter if I use hard coded values, constants, or anything else.

The other two computers seem to render fine when using constants and hacks similar to what was done in the SO link above.

I've tried all different shader versions, but started with 330 and went up from there. Also, my drivers are as up to date as they're going to get. I don't expect anything new for my old laptop.

What I really don't understand is that I'm doing the exact same thing with a regular old uniform and it works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
struct PointLight
{
	vec3 position;
	
	vec3 diffuse;
	vec3 specular;
	vec3 ambient;
	
	float constant;
	float linear;
	float quadratic;
};
#define TOTAL_LIGHTS 2
uniform PointLight pointLight[TOTAL_LIGHTS];

vec3 CalculatePoint(PointLight p)
{
...
}

void main()
{
...
vec3 point = vec3(0.0);
	for(int i = 0; i < TOTAL_LIGHTS; i++)
		point += CalculatePoint(pointLight[i]);
...
}


The above code works just fine in the same shader. I can use this method but I wanted to change over to a uniform buffer object so I could access the data easier from multiple shaders. I don't understand why it works one way and not another!

Anyway, I'm going to hack at it a little longer and if it I can't get it to work, I'll revert back to the regular old uniform. Thanks again for your thoughts.
Topic archived. No new replies allowed.