我的 OpenGL 3.2 代码遇到了一个奇怪的现象。我正在绘制一系列对象,每个对象都有一个 2D(颜色)纹理和一些相当标准的材质设置(漫反射/镜面反射颜色等)分配给它,我想将材质设置发送到我的片段着色器通过统一缓冲区。相应统一块的 GLSL 声明如下所示:
layout(std140) uniform MaterialBlock {
vec4 diffuseColor, specularColor;
float shininess, ambient, emission;
} material;
这就是我的渲染周期在伪代码中的样子:
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);
}
只要 a) 只有一个对象在屏幕上,或 b) 使用此着色器的所有对象共享相同的材质设置,或 c) 其他对象使用不同的着色器,这一切就足够了。
一旦两个对象使用相同的着色器,但具有不同的材质设置(例如,一个具有蓝色,一个具有绿色漫反射颜色),并且两者都在帧中,它们就会开始疯狂地闪烁——每个对象在自己的之间切换材料设置和其他对象的设置似乎是随机的。很明显,有些绘制发生时之前调用的材质值仍在统一缓冲区中,但为什么呢?我是否错过了关于统一缓冲区的一些重要内容?对 glDraw* 的调用能否以某种方式将我的写入数据重叠到缓冲区,或者缓冲区的内容是否会影响调用 glDraw* 后屏幕上的内容?
作为记录,我在 GeForce GT650M 上的 OS X 10.7.5 上开发这个。