我的 OpenGL 3.2 代码遇到了一个奇怪的现象。我正在绘制一系列对象,每个对象都有一个 2D(颜色)纹理和一些相当标准的 Material 设置(漫反射/镜面反射颜色等)分配给它,我想将 Material 设置发送到我的片段通过统一缓冲区的着色器。各个统一 block 的 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) 使用此着色器的所有对象共享相同的 Material 设置,或 c) 其他对象使用不同的着色器,这一切都可以正常工作。
一旦两个对象使用相同的着色器,但具有不同的 Material 设置(例如,一个具有蓝色,一个具有绿色漫反射颜色),并且都在框架中,它们就会开始疯狂闪烁 - 每个都在切换在它自己的 Material 设置和其他对象的 Material 设置之间似乎是随机的。显然,某些绘图发生时,先前调用的 Material 值仍在统一缓冲区中,但为什么呢?我错过了关于统一缓冲区的重要内容吗?对 glDraw* 的调用是否会以某种方式与我将数据写入缓冲区重叠,或者缓冲区的内容是否会影响调用 glDraw* 后屏幕上的内容?
郑重声明,我是在 GeForce GT650M 上的 OS X 10.7.5 上开发的。
最佳答案
好吧,我很确定这有什么问题:
layout(std140) uniform MaterialBlock {
vec4 diffuseColor, specularColor;
float shininess, ambient, emission;
} material
我非常确定 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]);
这里非常明显的问题是您将尝试将 4 个元素数组发送到着色器中的 float 变量...希望这有帮助
关于c++ - 通过统一缓冲区对象发送到 GLSL 的数据泄漏到其他绘制调用中 (OpenGL 3.2),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19779649/