OpenGL 实例化:如何调试丢失的每个实例数据
OpenGL instancing : how to debug missing per instance data
我对实例化绘图和每个实例数据比较熟悉:我过去成功地实现了这一点。
现在我正在重构一些旧代码,并且我引入了一个关于如何将每个实例数据提供给着色器的错误。
相关位如下:
- 我有一个使用 glMultiDrawElementsIndirect 实现的工作渲染循环:如果我忽略每个实例数据,一切都会按预期绘制。
我有一个 vbo 存储我的对象的世界变换。我使用 AMD 的 CodeXL 进行调试:缓冲区已正确填充数据,并在绘制帧时绑定。
glBindBuffer(GL_ARRAY_BUFFER,batch.mTransformBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * OBJ_NUM, &xforms, GL_DYNAMIC_DRAW);
着色器明确指定输入位置:
#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]);
Model
是每个实例的世界矩阵这是错误的:包含所有零。
在绑定缓冲区之后和绘制每一帧之前,我尝试设置属性指针和除数,以便每个绘制的实例都将接收不同的转换:
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
作为输入值,则使用 in
限定它,而不是 uniform
.
同样重要的是,输入和制服的位置不同。我的意思是统一位置与输入位置有不同的 space。输入可以具有与制服相同的位置索引,并且它们不会指代同一事物。输入位置仅指属性索引; uniform locations指的是统一的位置。
最后,统一位置与输入位置不同。对于属性,每个 vec4
等价物使用一个单独的属性索引。有了统一的位置,每个基本类型(任何不是结构或数组的类型)都使用一个统一的位置。所以如果ViewProj
是一个统一的位置,那么它只占1个位置。但是如果Model
是一个输入,那么它就占用了4个属性索引。
我对实例化绘图和每个实例数据比较熟悉:我过去成功地实现了这一点。
现在我正在重构一些旧代码,并且我引入了一个关于如何将每个实例数据提供给着色器的错误。 相关位如下:
- 我有一个使用 glMultiDrawElementsIndirect 实现的工作渲染循环:如果我忽略每个实例数据,一切都会按预期绘制。
我有一个 vbo 存储我的对象的世界变换。我使用 AMD 的 CodeXL 进行调试:缓冲区已正确填充数据,并在绘制帧时绑定。
glBindBuffer(GL_ARRAY_BUFFER,batch.mTransformBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * OBJ_NUM, &xforms, GL_DYNAMIC_DRAW);
着色器明确指定输入位置:
#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]);
Model
是每个实例的世界矩阵这是错误的:包含所有零。
在绑定缓冲区之后和绘制每一帧之前,我尝试设置属性指针和除数,以便每个绘制的实例都将接收不同的转换:
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
作为输入值,则使用 in
限定它,而不是 uniform
.
同样重要的是,输入和制服的位置不同。我的意思是统一位置与输入位置有不同的 space。输入可以具有与制服相同的位置索引,并且它们不会指代同一事物。输入位置仅指属性索引; uniform locations指的是统一的位置。
最后,统一位置与输入位置不同。对于属性,每个 vec4
等价物使用一个单独的属性索引。有了统一的位置,每个基本类型(任何不是结构或数组的类型)都使用一个统一的位置。所以如果ViewProj
是一个统一的位置,那么它只占1个位置。但是如果Model
是一个输入,那么它就占用了4个属性索引。