1

我对实例绘图和每个实例数据比较熟悉:我过去成功地实现了这一点。

现在我正在重构一些旧代码,并且我引入了一个关于如何将每个实例数据提供给着色器的错误。相关位如下:

  1. 我有一个使用glMultiDrawElementsIndirect实现的工作渲染循环:如果我忽略每个实例数据,一切都会按预期绘制。
  2. 我有一个 vbo 存储我的对象的世界变换。我使用 AMD 的CodeXL进行调试:缓冲区正确填充了数据,并且在绘制框架时被绑定。

    glBindBuffer(GL_ARRAY_BUFFER,batch.mTransformBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * OBJ_NUM, &xforms, GL_DYNAMIC_DRAW);

  3. 着色器明确指定输入位置:

    #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 错误。

我的问题是:有谁知道在哪种情况下每个实例数据的设置可能会静默失败?或有关如何进一步调试此问题的任何建议?

4

1 回答 1

2
layout(location = 6)uniform mat4 ViewProj;
layout(location = 10)uniform mat4 Model;

这些是制服,而不是输入值。他们不会被属性喂养;他们被glUniform*电话喂饱了。如果你想Model成为一个输入值,那么用 来限定它in,而不是uniform

同样重要的是,输入和制服不会获得相同的位置。我的意思是统一位置与输入位置具有不同的空间。输入可以具有与制服相同的位置索引,并且它们不会引用相同的东西。输入位置仅指属性索引;统一位置是指统一位置。

最后,统一位置不像输入位置那样工作。对于属性,每个vec4等效项使用单独的属性索引。使用统一位置,每个基本类型(不是结构或数组的任何东西)都使用一个统一的位置。所以如果ViewProj是一个统一的位置,那么它只占用1个位置。但如果Model是输入,则它占用 4 个属性索引。

于 2016-07-04T22:53:00.907 回答