Search code examples
copenglopengl-4

glUniformMatrix4fv - INVALID OPERATION


Context:

  • OpenGL C API 4.1 ("modern" opengl)

Issue:

I am encoutering an INVALID OPERATION binding uniforms the wrong way with multiple shaders :

// Getting ids for each uniform
GLuint uniform1 = glGetUniformLocation(shader1_program.id, "mvp");
GLuint uniform2 = glGetUniformLocation(shader2_program.id, "mvp");

loop {
    // Print mesh 1 shader 1
    glUseProgram(shader1_program.id);
    glUniformMatrix4fv(uniform1 , 1, GL_FALSE, mvp1);
    check_gl_error(); // =============================> this one provides the error
    glBindVertexArray(vao1);
    glDrawArrays(GL_TRIANGLES, 0, vertex_number1);

    // Print mesh 2 with shader2
    glUseProgram(shader2_program.id);
    glUniformMatrix4fv(uniform2 , 1, GL_FALSE, mvp2);
    check_gl_error();
    glBindVertexArray(vao2);
    glDrawArrays(GL_TRIANGLES, 0, vertex_number2);
}

Here is the check_gl_error() function that get error code from glGetError and print signification:

typedef struct glmaperror_s {
                            GLenum err;
                            char *string_error;
}                            glmaperror_t;

static const glmaperror_t glmaperror[] = {
    { GL_INVALID_OPERATION, "GL_INVALID_OPERATION", },
    { GL_INVALID_ENUM, "GL_INVALID_ENUM", },
    { GL_INVALID_VALUE, "GL_INVALID_VALUE", },
    { GL_OUT_OF_MEMORY, "GL_OUT_OF_MEMORY", },
    { GL_INVALID_FRAMEBUFFER_OPERATION, "GL_INVALID_FRAMEBUFFER_OPERATION", },
};

int check_gl_error(void)
{
    GLenum  err;
    char    *error;

    error = 0;
    while ((err = glGetError()) != GL_NO_ERROR) {
        error = "Unhandled GL error";
        for (size_t i = 0; i * sizeof(glmaperror_t) < sizeof(glmaperror); i++) {
            if (glmaperror[i].err == err) {
                error = glmaperror[i].string_error;
            }
        }
        fprintf(stderr, "[GL Error]: %s\n", error);
        return (-1);
    }
    return (0);
}

Here are the two shaders :

shader1 :

#version 410
in vec3 position;
in vec3 color;

out vec4 _color;

uniform mat4 mvp;

void main() {
  gl_Position = mvp * vec4(position, 1.0);
  _color = vec4(color, 255.0);
}

shader2

#version 410
in vec3 position;

uniform mat4 mvp;

void main() {
  gl_Position = mvp * vec4(position, 1.0);
}

Actually, only mesh 2 is rendered.

I have printed shader1_program.id and shader2_program.id, they are valid and have different values which is ok.

I have printed uniform1 and uniform2, they have the same numerical value.


Is it the right order to declare and bind uniform ?


Solution

  • shader1_program.id is the result of the compiled shader1 code from the glCompileShader function. shader2_program.id is the result of the compiled shader2 code from the glCompileShader function.
    – Alrick 12 hours ago

    So that's the problem then. glUseProgram expects a program object, not a shader object.

    You create program objects by a call to glCreateProgram, followed by attaching your compiled shader stages with glAttachShader, and then calling glLinkProgram afterwards. You cannot call glUseProgram on a shader directly.