I am passing an uniform array to geometry shader and want to index into it using a variable. I can use variable length array & index with fixed number (numeric constant) OR I can define a fixed length array & index using varible. However I can't index into variable length array using a variable.
Below is pseudo code for geometry shader with cases that work & case that doesn't work
This works:
uniform vec2 dimensions[2];
// some code which computes index which is an int
float dimX = dimensions[index].x;
This works:
uniform vec2 dimensions[];
// some code which computes index which is an int
float dimX = dimensions[0].x;
This doesn't work:
uniform vec2 dimensions[];
// some code which computes index which is an int
float dimX = dimensions[index].x;
Is it possible to do something like this?
Sadly, no this is not possible. You did not include the GLSL version you are targeting but did mention geometry shaders, so I have included the relevant part of the GLSL 1.5 spec. below:
Variables of the same type can be aggregated into arrays by declaring a name followed by brackets ( [ ] ) enclosing an optional size. When an array size is specified in a declaration, it must be an integral constant expression (see Section 4.3.3 “Constant Expressions” ) greater than zero. If an array is indexed with an expression that is not an integral constant expression, or if an array is passed as an argument to a function, then its size must be declared before any such use.
While desktop GLSL is much more forgiving when it comes to indexing arrays with non-const expressions than GLSL ES, you still have to work within some limitations. The same way that texture lookups are often used to overcome non-const array indexing in OpenGL ES, you may be able to work around this by using a 1D texture lookup in your geometry shader. I have to wonder if you really need this functionality that badly though?
It is a good idea to define an upper limit to your uniform array anyway, because the GLSL spec. only requires an implementation provide 1024 uniform components (e.g. 1024 float
, 256 vec4
, 64 mat4
or some combination of each) in the geometry shader stage. If your array has a known maximum size at compile time you can avoid trouble later down the road associated with unknowingly exceeding this limitation.
Since you mentioned GLSL 4.x, I would like to point out a newer feature in OpenGL known as Shader Storage Buffer Objects. Using SSBOs, it may be possible to use an array with dynamic length at run-time for your purposes. You can query the length of an SSBO using .length ()
in the shader, and handle range validation yourself. However, I think this is probably overkill but worth mentioning nevertheless.