glVertexAttribPointer overwrite
glVertexAttribPointer overwrite
我对如何在不同的多个程序之间正确切换感到困惑。我将问题缩小到以下内容:如果我使用 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之后禁用顶点AttribArray,我的球体/正方形就会消失!
作为参考,以下是我在 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);
发布的代码表明可能存在对顶点数组对象(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,您的程序结构通常如下所示:
- 一旦,在设置过程中,您可以为每个对象创建一个 VAO。 例如,一个用于您的地球仪,一个用于四边形等。然后绑定每个 VAO,并从上面的列表中进行调用以设置对象的顶点状态。
- 在渲染过程中,对于每个对象,根据需要更改程序,绑定对象的 VAO,并进行绘制调用。您将不需要任何其他顶点状态调用,因为状态存储在每个对象的 VAO 中。
我认为您的代码中对此没有问题,而只是强调一个有时会引起混淆的相关项目:在调用glVertexAttribPointer()
时需要正确GL_ARRAY_BUFFER
绑定。无需为绘制调用建立GL_ARRAY_BUFFER
绑定。