【问题标题】:glVertexAttribPointer overwriteglVertexAttribPointer 覆盖
【发布时间】:2014-10-07 04:21:14
【问题描述】:

我对如何在不同的多个程序之间正确切换感到困惑。我已将问题缩小到以下几点:如果我使用 NO_HDR 运行,它可以正常工作;我得到了一些线条、一艘太空船和一些球体,按此顺序渲染。如果我使用 HDR 运行,我得到的结果基本相同,但我得到的是 2d 正方形而不是球体。

我认为 hdr 部分的四边形顶点属性覆盖了 forwardRender() 部分中要渲染的最后内容。如果我在 forwardRender() 中更改顺序,那么在 forwardRender() 中最后渲染的任何内容都会以某种方式被弄乱。我错过了什么允许四边形顶点覆盖我的其他对象?

#if NO_HDR
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
forwardRender();

#else

//set to render to custom frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, rt.FramebufferName);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
forwardRender();

//now switch to render to screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, rt.renderedTexture);

glUseProgram(hdr.shaderProgram);
glUniform1i(texID, 0);

glBindBuffer(GL_ARRAY_BUFFER, hdr.quad_vertexbuffer);
glEnableVertexAttribArray(hdr.quad_vertexPosition_modelspace);
glVertexAttribPointer(
                      hdr.quad_vertexPosition_modelspace, // attribute
                      3,                              // size
                      GL_FLOAT,                       // type
                      GL_FALSE,                       // normalized?
                      0,                              // stride
                      (void*)0                        // array buffer offset
                      );
// Draw the triangles !
glBindVertexArray(hdr.vao);
glDrawArrays(GL_TRIANGLES, 0, 6); // 2*3 indices starting at 0 -> 2 triangles

#endif

另一个线索:如果我在最后 glDrawArrays 之后禁用 vertexAttribArray,我的球体/正方形就会消失!

作为参考,这是我在 forwardRender() 中渲染球体的方式:

glUseProgram(globe.shaderProgram);
glm::mat4 mvp = camera * world * position * size * orientation;
GLint uTransform = glGetUniformLocation(shaderProgram, "transform");
glUniformMatrix4fv(uTransform, 1, GL_FALSE, glm::value_ptr(mvp));
glBindVertexArray(globe.vao);
glDrawArrays(drawType, 0, globe.drawCount);

【问题讨论】:

    标签: c++ opengl


    【解决方案1】:

    发布的代码表明可能对顶点数组对象 (VAO) 的工作方式存在误解。 VAO 是状态的集合。它包含具有以下调用的状态集:

    • glVertexAttribPointer(...)
    • glEnableVertexAttribArray(...), glDisableVertexAttribArray()
    • glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...)

    每当您进行这些调用之一时,相应的状态都会保存在当前绑定的 VAO 中。当你稍后再次绑定 VAO 时,状态会恢复。

    例如,在发布代码的这个序列中:

    glEnableVertexAttribArray(hdr.quad_vertexPosition_modelspace);
    glVertexAttribPointer(hdr.quad_vertexPosition_modelspace, ...);
    // Draw the triangles !
    glBindVertexArray(hdr.vao);
    glDrawArrays(GL_TRIANGLES, 0, 6); // 2*3 indices starting at 0 -> 2 triangles
    

    glDrawArrays() 调用将使用您在序列中的前两个调用中设置的状态。该状态将应用于当时绑定的任何 VAO。然后,glBindVertexArray(hdr.vao) 调用恢复存储在hdr.vao 中的状态,这是先前绑定该 VAO 时设置的最新状态。

    还要注意,这与切换程序无关。顶点状态不是程序状态的一部分。

    要有效地使用 VAO,您的程序结构通常如下所示:

    1. 有一次,在设置过程中,您为每个对象创建了一个 VAO。例如。一个用于地球,一个用于四边形等。然后绑定每个 VAO,并从上面的列表中调用以设置对象的顶点状态。
    2. 在渲染过程中,对于每个对象,根据需要更改程序,绑定对象的 VAO,并进行绘图调用。您不需要任何其他顶点状态调用,因为状态存储在每个对象的 VAO 中。

    我认为您的代码中没有这个问题,只是为了强调一个有时会引起混淆的相关项目:在调用 glVertexAttribPointer() 时需要正确的 GL_ARRAY_BUFFER 绑定。无需为绘图调用建立GL_ARRAY_BUFFER 绑定。

    【讨论】:

    • 澄清一下,保存到当前绑定的 VAO 的唯一绑定是绑定到 GL_ELEMENT_ARRAY_BUFFER?
    • 是的。 GL_ARRAY_BUFFER 绑定需要在调用glVertexAttribPointer() 时就位,然后缓冲区引用将成为该属性状态的一部分。 GL_ARRAY_BUFFER 绑定本身不是 VAO 状态的一部分,也会影响绘图调用。
    猜你喜欢
    • 2011-06-11
    • 2012-01-28
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    相关资源
    最近更新 更多