我对实例绘图和每实例数据相对熟悉:我在过去成功地实现了这一点。
现在我正在重构一些旧代码,并介绍了一个关于每个实例数据如何提供给着色器的bug。
>
我有一个vbo存储我对象的世界变换。我使用AMD的CodeXL进行调试:缓冲区正确填充了数据,并且在绘制帧时被绑定。
GL_ARRAY_BUFFER; glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4)*OBJ_NUM,
着色器显式指定输入位置:
#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;
ViewProj
矩阵对于所有实例都是相等的,并使用以下方法正确设置:
glUniformMatrix4fv(6, 1, GL_FALSE, &viewProjMat[0][0]);
模型
是每个实例的世界矩阵,这是错误的:包含所有零。
绑定缓冲区后,在绘制每个帧之前,我尝试设置属性指针和除数,以便每个绘制的实例都会收到不同的转换:
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);
}
现在,我已经查看了一段时间的代码,我真的无法弄清楚我错过了什么。CodeXL 清楚地表明模型(位置 10)未正确填充。不会生成 OpenGL 错误。
我的问题是:有谁知道在什么情况下每个实例数据的设置可能会静默失败?或者关于如何进一步调试此问题的任何建议?
layout(location = 6)uniform mat4 ViewProj;
layout(location = 10)uniform mat4 Model;
这些是制服,而不是输入值。他们不受属性的影响;他们被glUniform*
调用喂养。如果您希望Model
作为输入值,那么在中使用来限定它,而不是
uniform
。
同样重要的是,输入和制服不会得到相同的位置。我的意思是统一位置与输入位置有不同的空间。输入可以具有与制服相同的位置索引,它们不会引用相同的东西。输入位置仅指属性索引;统一位置指统一位置。
最后,统一位置与输入位置不同。对于属性,每个vec4
-等效项使用单独的属性索引。对于统一的位置,每个基本类型(不是结构或数组的任何类型)都使用一个统一的位置。因此,如果ViewProj
是一个统一的位置,那么它只占用1个位置。但如果Model
是一个输入,那么它将占用4个属性索引。