I am relatively familiar with instanced drawing and per instance data: I've implemented this in the past with success.
Now I am refactoring some old code, and I introduced a bug on how per instance data are supplied to shaders. The relevant bits are the following:
I have a vbo storing the world transforms of my objects. I used AMD's CodeXL to debug this: the buffer is correctly populated with data, and is bind when drawing a frame.
glBindBuffer(GL_ARRAY_BUFFER,batch.mTransformBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * OBJ_NUM, &xforms, GL_DYNAMIC_DRAW);
The shader specifies the input location explicitly:
#version 450
layout(location = 0) in vec3 vertexPos;
layout(location = 1) in vec4 vertexCol;
//...
layout(location = 6)uniform mat4 ViewProj;
layout(location = 10)uniform mat4 Model;
The ViewProj
matrix is equal for all instances and is set correctly using:
glUniformMatrix4fv(6, 1, GL_FALSE, &viewProjMat[0][0]);
Model
is per instance world matrix it's wrong: contains all zeros.
After binding the buffer and before drawing each frame, I am trying to setup the attribute pointers and divisors in such a way that every drawn instance will receive a different transform:
for (size_t i = 0; i < 4; ++i)
{
glEnableVertexAttribArray(10 + i);
glVertexAttribPointer(10 + i, 4, GL_FLOAT, GL_FALSE,
sizeof(GLfloat) * 16,
(const GLvoid*) (sizeof(GLfloat) * 4 * i));
glVertexAttribDivisor(10 + i, 1);
}
Now, I've looked and the code for a while and I really can't figure out what I am missing. CodeXL clearly show that Model (location 10) isn't correctly filled. No OpenGL error is generated.
My question is: does anyone know under which circumstances the setup of per instance data may fail silently? Or any suggestion on how to debug further this issue?
layout(location = 6)uniform mat4 ViewProj; layout(location = 10)uniform mat4 Model;
These are uniforms, not input values. They don't get fed by attributes; they get fed by glUniform*
calls. If you want Model
to be an input value, then qualify it with in
, not uniform
.
Equally importantly, inputs and uniforms do not get the same locations. What I mean is that uniform locations have a different space from input locations. An input can have the same location index as a uniform, and they won't refer to the same thing. Input locations only refer to attribute indices; uniform locations refer to uniform locations.
Lastly, uniform locations don't work like input locations. With attributes, each vec4
-equivalent uses a separate attribute index. With uniform locations, every basic type (anything that isn't a struct or an array) uses a single uniform location. So if ViewProj
is a uniform location, then it only takes up 1 location. But if Model
is an input, then it takes up 4 attribute indices.