PDA

View Full Version : Data sent to GLSL via Uniform Buffer Objects influences other draw calls



iguana
11-05-2013, 08:03 AM
Hey! I've been running into a weird phenomenon with my OpenGL 3.2 code. I'm drawing a series of objects, each of which has a 2D (color) texture and some fairly standard material settings (diffuse/specular color etc.) assigned to it, and I'd like to send the material settings to my fragment shader(s) via a uniform buffer. The GLSL declaration of the respective uniform block looks like this:


layout(std140) uniform MaterialBlock {
vec4 diffuseColor, specularColor;
float shininess, ambient, emission;
} material;

And this is what my render cycle looks like in pseudocode:


glUseProgram(objectShaderId);

for each object {

// Set material
glBindBuffer(GL_UNIFORM_BUFFER, materialBufferId);
MaterialBlockPtr = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY);
<set object's material values via MaterialBlockPtr>
glUnmapBuffer(GL_UNIFORM_BUFFER);

// Set texture
glBindTexture(GL_TEXTURE_2D, textureId);

// Draw
glBindVertexArray(object.vertexArrayId);
glDrawElements(GL_TRIANGLES, object.faceCount, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);

}

This all works well enough as long as a) only a single object is on screen, or b) all objects using this shader share the same material settings, or c) the other objects use a different shader.

As soon as two objects use the same shader, but have different material settings (e.g. one has a blue, one has a green diffuse color), and both are in the frame, they start to flicker like crazy each one switching between its own material settings and those of the other object seemingly at random. Obviously, some of the drawing happens with the material values of the previous call still in the uniform buffer, but why? Have I missed something essential about uniform buffers? Can calls to glDraw* somehow overlap my writing data to the buffer, or can the contents of the buffer influence what's on screen after the call to glDraw* took place?

I'm a bit of a noob when it comes to GL>=1 and GLSL, so I'm grateful for any pointers. For the record, I'm developing this on OS X 10.7.5 on a GeForce GT650M.

iguana
11-05-2013, 08:50 AM
Well this is embarrassing. I think I found the solution 20 minutes after posting. If I replace the glMapBuffer call with an equivalent glMapBufferRange call, it all works fine. According to the docs, glMapBufferRange will flush the modified buffer if called without the GL_MAP_FLUSH_EXPLICIT_BIT, perhaps glMapBuffer doesn't? Anyway, I can't claim to understand it entirely, but for the time being, my problem seems to be solved…