Constant vec3 array - no go

So I want to do something like this:


const vec3 COLOR_MASKS[ 8 ] = { vec3( 0.0, 0.0, 0.0 ),
                                vec3( 0.5, 0.5, 0.5 ),
                                vec3( 1.0, 0.5, 0.5 ),
                                vec3( 0.5, 1.0, 0.5 ),
                                vec3( 0.5, 0.5, 1.0 ),
                                vec3( 0.5, 1.0, 1.0 ),
                                vec3( 1.0, 0.5, 1.0 ),
                                vec3( 1.0, 1.0, 0.5 ) };

color = COLOR_MASKS[index];

for a shader debugging tool (not for performance) – index being an int computed in the shader.

But the compiler says no way:

frag.glsl: error C7516: OpenGL does not allow constant arrays
frag.glsl: error C7549: OpenGL does not allow C style initializers

So what’s the GLSL paradigm for this? I’d rather not have to do the silly/verbose/less readable:


if val == 0 then
  val2 = 123
else if val == 1 then
  val2 = 456
...

approach.

Thanks.

This compiles/works, but is crazy-verbose and the compiler won’t let me make the array constant:

  vec3 COLOR_MASKS[8];
  COLOR_MASKS[0] = vec3( 0.0, 0.0, 0.0 );
  COLOR_MASKS[1] = vec3( 0.5, 0.5, 0.5 );
  COLOR_MASKS[2] = vec3( 1.0, 0.5, 0.5 );
  COLOR_MASKS[3] = vec3( 0.5, 1.0, 0.5 );
  COLOR_MASKS[4] = vec3( 0.5, 0.5, 1.0 );
  COLOR_MASKS[5] = vec3( 0.5, 1.0, 1.0 );
  COLOR_MASKS[6] = vec3( 1.0, 0.5, 1.0 );
  COLOR_MASKS[7] = vec3( 1.0, 1.0, 0.5 );

color = COLOR_MASKS[index];

Is there no better way?

Array constructors in GLSL look like this:


float a[5] = float[](3.4, 4.2, 5.0, 5.2, 1.1);

Why would you want to make it constant, it seems like overkill in a shader.

I usually mark the array as an uniform:


uniform vec3 COLOR_MASKS[ 8 ] = { vec3( 0.0, 0.0, 0.0 ),
                                vec3( 0.5, 0.5, 0.5 ),
                                vec3( 1.0, 0.5, 0.5 ),
                                vec3( 0.5, 1.0, 0.5 ),
                                vec3( 0.5, 0.5, 1.0 ),
                                vec3( 0.5, 1.0, 1.0 ),
                                vec3( 1.0, 0.5, 1.0 ),
                                vec3( 1.0, 1.0, 0.5 ) };


I am unsure if this is a bad practice, or sub-performant.

I am unsure if this is a bad practice, or sub-performant.

It’s more like contrary to the spec. Array initialization isn’t supposed to work that way in GLSL; you’re supposed to use constructor syntax.

Thanks for the correction; I looked closer at the spec for this, and found the solution:


const vec3 MyArray[4]=vec3[4](
	vec3(1.5,34.4,3.2),
	vec3(1.6,34.1,1.2),
	vec3(18.981777,6.258294,-27.141813),
	vec3(1.0,3.0,1.0)
);

No curly brackets.

Edit:
And OUCH. Replacing one of my uniform-arrays with such a const vec4[] dropped framerate from 93fps to 2fps :S.
Removing the “const” makes it run at 8fps.
Replacing the “const” with “uniform” (again, no curly brackets) restores it to 93fps.

GTX275, 196.34 (beta), winxp.

Thanks, all!

@Alfonse, this works - thanks:


  vec3 COLOR_MASKS[8] = vec3[]( vec3( 0.0, 0.0, 0.0 ),
                                vec3( 0.5, 0.5, 0.5 ),
                                ... 
                              );

@zeoverlord:

I try to make whatever is constant const, so the compiler will fold it into the code when possible (even if it’s lame at dead code elimination). For instance, if I use a constant index to look into the above array, which I would make const, then only a stupid compiler isn’t going to generate the maximally efficient code there and just pretend that was a reference to that color specifically in-line in the code.

But alas, like switch statements originally, seems GLSL doesn’t believe in const arrays yet…

@Ilian:

Yeah, that works, but there are two disadvantages:
[ol][li] uniforms have to be at global scope (so you can’t define these convenience lookups inside the only function that uses them), and [*] because they’re uniform (i.e. parameters), then compiler cannot fold the array completely out of the code in the case of indexing with a constant[/ol][/li]And I too can confirm that unlike non-uniform arrays, seems the C array initializer syntax “can” be used for uniform arrays defined at the global scope (on NVidia at least). This is a bug I gather.

No dice here. That won’t compile, either in a function or at the global scope. The error is:

error C7516: OpenGL does not allow constant arrays

Wow. Weird. And on NVidia too, with recent GPU/drivers. Let me try some tests…

Ok, here on NVidia GTX285 / 190.32 (Linux), neither the GLSL array initializer or C initializer cases dropped my perf, but using the uniform forms seemed not to honor the initializers. Always got black.

error C7516: OpenGL does not allow constant arrays

IIRC, you need “#version 120” or higher for constant arrays. Try adding that to the top of your shader.

Thanks, but it’s there. Very first line.

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