GLSL How to access UNIFORM array?

Turns out you cannot access UNIFORM array, which hasn’t been created with certain size, with integers that are created within the void main() method/function
If you want to access UNIFORM array that hasn’t been created with specified size, you will have to type in a “static” number.
This code will work nicely.

	uniform float[] myArray = float[](0, 10, 20);
	
	void main() {
		float x = myArray[0];
	}

This code won’t compile.

	uniform float[] myArray = float[](0, 10, 20);
	
	void main() {
		int index = 0;
		float x = myArray[index];
	}

If you want to access your UNIFORM array with “index”, you will need to do this.

	uniform float[3] myArray = float[3](0, 10, 20);
	
	void main() {
		int index = 0;
		float x = myArray[index];
	}

I have found that this kind of thing is somewhat dependent on the particular compiler your vendor has used. Some are more lenient with what will compile, some are very strict. It’s extremely annoying but very few compilers actually break the rules (ie don’t follow the specification) so you can’t really call them on it. The more recent drivers tend to be fine however.

Did you have an actual question?

In general AMD is strict to the rules and Nvidia takes pretty much any code you throw at it (i.e. you can use HLSL or CG functions).
On the other hand you can use [icode]#pragma optionNV(strict on)[/icode] to force Nvidia to be strict.

Some more tips for cross-platform uniform access:

  1. Initializing uniforms (and arrays) with default values was only added in GLSL 120 +. Make sure you add [icode]#version 120[/icode] to the top of your shader.

  2. It’s usually good practice to specify a length:

float a[5] = float[5](3.4, 4.2, 5.0, 5.2, 1.1);
  1. Certain drivers will not support dynamic indexing. For example, if you’re using GL ES (WebGL, iOS, etc) then don’t expect dynamic indexing of uniforms to work across all platforms. In your case the index won’t be dynamic, but it’s best just to stick to “static” indices where possible.

  2. Initializing arrays in the shader doesn’t work at all in Mac OSX <= 1.7. I haven’t tested later versions of OSX.

  3. You can access certain elements of an array by including the index in the name when using glGetUniformLocation:

 glGetUniformLocation( program, "LightPos[0]" ) 

Oddly, in WebGL, I found this was the only way I could update an entire array of values with glUniform4fv.