通过Uniform Buffer Objects发送到GLSL的数据泄漏到其他绘制调用中(OpenGL 3.2)

时间:2013-11-05 00:05:03

标签: c++ opengl glsl

我的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上进行开发。

1 个答案:

答案 0 :(得分:1)

好吧我很确定这有什么不妥之处:

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

我非常确定材料的环境和发射本身就是颜色也应该被声明为vec4数组,我怀疑你的绘图代码中你有类似的东西

//this is just an example and assumption
float material_ambient[4];
float material_emmission[4];
//to setup material ambient and emmissive colour
material_ambient = {1.0, 1.0, 1.0, 1.0};
material_emmision = {1.0, 1.0, 1.0, 1.0};

glUniform4f(material_ambient_id, material_ambient[0], material_ambient[1], material_ambient[2], material_ambient[3]);
glUniform4f(material_emissive_id, material_emissive[0], material_emissive[1], material_emissive[2], material_emissive[3]);

这里非常明显的问题是你要尝试将四个元素数组发送到着色器中的浮点变量...希望这有帮助