Opengl error 1282 (invalid operation) when using texture()

fragment-shaderglslopengl

I have the following fragment shader:

#version 330 core

layout (location = 0) out vec4 color;

uniform vec4 colour;
uniform vec2 light_pos;

in DATA
{
    vec4 position;
    vec2 texCoord;
    float tid;
    vec4 color;
} fs_in;

uniform sampler2D textures[32];

void main()
{
    float intensity = 1.0 / length(fs_in.position.xy - light_pos);

    vec4 texColor = fs_in.color;
    if (fs_in.tid > 0.0)
    {
        int tid = int(fs_in.tid + 0.5);
        texColor = texture(textures[tid], fs_in.texCoord);
    }

    color = texColor * intensity;
}

If I run my program, I get opengl error 1282, which is invalid operation. If I don't use the texture(), so I write texCoord = vec4(…) it works perfectly. I'm always passing in tid (texture ID) as 0 (no texture) so that part shouldn't even run. I've set the textures uniform to some placeholder, but as far as I know this shouldn't even matter. What could cause the invalid operation then?

Best Answer

Your shader compilation has most likely failed. Make sure that you always check the compile status after trying to compile the shader, using:

GLint val = GL_FALSE;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &val);
if (val != GL_TRUE)
{
    // compilation failed
}

In your case, the shader is illegal because you're trying to access an array of samplers with a variable index:

texColor = texture(textures[tid], fs_in.texCoord);

This is not supported in GLSL 3.30. From the spec (emphasis added):

Samplers aggregated into arrays within a shader (using square brackets [ ]) can only be indexed with integral constant expressions (see section 4.3.3 “Constant Expressions”).

This restriction is relaxed in later OpenGL versions. For example, from the GLSL 4.50 spec:

When aggregated into arrays within a shader, samplers can only be indexed with a dynamically uniform integral expression, otherwise results are undefined.

This change was introduced in GLSL 4.00. But it would still not be sufficient for your case, since you're trying to use an in variable as the index, which is not dynamically uniform.

If your textures are all the same size, you may want to consider using an array texture instead. That will allow you to sample one of the layers in the array texture based on a dynamically calculated index.

Related Topic