4
votes

i'm trying to learn the basics of OpenGL, but i have a Problem with setting up the transformation matrices. I made the model, view and projection matrices, but i have a problem sending them to my vertex shader.

Here is the code:

//Set up MVP
glm::mat4 model = glm::mat4();
GLint uniModel = glGetUniformLocation(program, "model");
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));

glm::mat4 view = glm::lookAt(
    glm::vec3(2.5f, 2.5f, 2.0f),
    glm::vec3(0.0f, 0.0f, 0.0f),
    glm::vec3(0.0f, 0.0f, 1.0f));
GLint uniView = glGetUniformLocation(program, "view");
glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view));

glm::mat4 proj = glm::perspective(45.0f, 800.0f / 600.0f, 1.0f, 10.0f);
GLint uniProj = glGetUniformLocation(program, "proj");
glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj));

and the shader:

layout (location = 0) in vec3 position;

uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;

void main() {
    gl_Position = proj * view * model * vec4(position, 1.0);
}

I think i did something wrong with setting up the uniforms, because it doesn't draw anything, even if i set model, view and proj to the identity. Could be i just mistyped something, but i really can't find the problem.

Edit: Solved it, the problem was that i forgot to use glUseProgram() first.

1
The first thing to do is check all possible return codes, verify your shader program has compiled and linked correctly, and make sure your uniforms are valid. This should pretty quickly narrow down where the problem is; and after that, all bets are off. A binary search with glGetError() can also be very useful in these instances.gavinb
@gavinb : How can i make sure, that my uniforms are valid? I'm pretty sure that is the problem, because the shaders compile and are linked, and i don't get any errors or something. If i do: gl_Position = vec4(position, 1.0) in the shader everything works fine. I think the shader thinks all matrices are 0 and projects everything to 0.0x40_hues
Uniforms must be >= 0 to be valid. Make sure you check glGetProgram(GL_LINK_STATUS,...). Don't forget to glUseProgram() too.gavinb
@gavinb : Thank you, it was the glUseProgram() thing.0x40_hues
You should pre-calculate proj * view * model, whenever it's possible and then send it to the Shader as mvp, instead of all the 3 separately and then calculating it in the Shader.vallentin

1 Answers

2
votes

The first thing to do is check all possible return codes, verify your shader program has compiled and linked correctly, and make sure your uniforms are valid, which means the location value is >= 0.

A binary search with glGetError() can also be very useful in these instances when you don't know where it's going wrong.

After compiling the shaders, make sure you check glGetProgram(GL_LINK_STATUS,...). And finally, you must call glUseProgram() to activate the shader.

As @Vallentin suggests, it is much more efficient to pass in your precalculated MVP matrix, since it will not change between the app and the shader. This simplifies your code somewhat, to something like this for your application code:

// Set up MVP matrices

glm::mat4 model = glm::mat4();

glm::mat4 view = glm::lookAt(
    glm::vec3(2.5f, 2.5f, 2.0f),
    glm::vec3(0.0f, 0.0f, 0.0f),
    glm::vec3(0.0f, 0.0f, 1.0f));

glm::mat4 proj = glm::perspective(45.0f, 800.0f / 600.0f, 1.0f, 10.0f);

glm::mat4 mvp = proj * view * model;

glUseProgram(prog);

GLint uniMvp = glGetUniformLocation(program, "mvp");
glUniformMatrix4fv(uniMvp, 1, GL_FALSE, glm::value_ptr(mvp));

and then the GLSL:

// Shader code

layout (location = 0) in vec3 position;
uniform mat4 mvp;

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

Also, you could cache the uniform locations, since they won't change once compiled. This will save a small amount per frame, rather than querying them for every redraw.