GLSL and struct arrays

Hello,

I want to compute multiple lights in my fragment shader. I pass the light data to the vertex shader via a uniform struct[] and then I want to do something like that:

struct Global_lights {
  ...
};

uniform ...
uniform Global_lights[] lights;

out ...
out Global_lights[] frag_lights;

void pass_lights() {
	frag_lights = lights;
}

The fragment shader:

struct Global_lights {
  ...
};

in ...
in Global_lights[] frag_lights;

If I try to compile this I get two errors:
Error compiling Shader
Vertex shader failed to compile with the following errors:
ERROR: 0:27: error(#282) Implicitly sized arrays can not be assigned to
ERROR: 0:27: error(#160) Cannot convert from: “uniform array of structure” to: “default out array of structure”
ERROR: error(#273) 2 compilation errors. No code generated

I somewhat understand the error message but I’d like some kind of source to read what is allowed and what not. Can someone offer a soluting? The exact amount of lights has to variable.
Thanks!

when u want to use a uniform in the fragment-shader, you don’t have to pass it through the vertex-shader.
just declare the uniform array in the fragment shader.

When you want to use a uniform in multiple shader stages(vertex, fragment …) just declare it with the same name and type in all stages were you want to use it.

Wow thanks, I didn’t konw that.
If I declare a uniform in the fragment shader because I only need it in the fragment shader, do I still have to declare it in vertex shader as well? My test suggests that but it doesn’t really makes sense.
vertex shader

#version 140

in vec4 vertex_position;
in vec4 vertex_color;

uniform vec2 camera_offset;
uniform mat4 mvp_matrix;
// if I remove this the color uniform the uniform in the frag shader is not what it should be
uniform vec4 color;

out vec4 frag_position;
out vec4 frag_colorcode;

void main() {
	frag_position = vec4(vertex_position.xy - camera_offset.xy, vertex_position.zw) * mvp_matrix;
	frag_colorcode = vertex_color;
	gl_Position = frag_position;
}

fragment shader

 #version 140
 
//@insert global_lights.struct
 
in vec4 frag_position;
in vec4 frag_colorcode;

uniform vec4 color;
uniform Global_lights[] frag_lights;
 
 void main() {
 	gl_FragColor = (color + frag_colorcode);
}

Thanks!

If you only use a uniform in the frag shader, you don’t need to declare it in the vertex shader, and vice versa.

Okay I found the problem! Thank you.
One followup question: Is there a way to determine the length of an implicit declared (uniform) array? .length() doesn’t work. Is there some other way to iterate over the array?

There are no implicitly declared arrays in GLSL. You can pass a uniform variable for the length and only compute lighting for the relevant lights, but you need an explicit size on the uniform struct array.

Hm I see … arg why is everything so uncomfortable …

Another followup question:
Lets say I have 32 fixed lights. All have a specific position in model space. I have to transform these light coords with the mvpMatrix to get my light calaulations right. It makes absolutly no sense to perform this calculation for every fragment so I wanted to do it once in the vertex shader and then pass it via the positions via an out variable to my fragment shader. Problem is: The amount of “in”-variables in the fragment shader is limited. Much more limited then the amount of uniforms.

Is there a solution to this problem?

Do it on the CPU once for each light.