1
votes

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?

2

2 Answers

3
votes

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.

1
votes

I know this solution is late, but if it helps anybody..

As per Cherno's video, this should work. He however uses the attribute 'fs_in.tid' as a 'GL_BYTE' in the gl_VertexAttribPointer fo the texture index, for some reason regarding casting 1.0f always got converted to 0.0f and hence did not work. Changing GL_BYTE to GL_FLOAT resolved this issue for me.

Regarding the 'opengl error 1282', its a very common mistake I faced. I used to forget to call glUseProgram(ShaderID) before setting any of the uniforms. Because of this the uniforms even though not being used/set at the time can cause an error, namely '1282'. This could be one of the solutions, this solved it for me.