2014-10-07 47 views
0

我很困惑如何正确切换不同的多个程序。我将问题缩小到以下范围:如果我使用NO_HDR运行,它可以正常工作;我得到了一些线条,一艘太空飞船和一些球体,按照这个顺序渲染。如果我使用HDR运行,我会得到大致相同的结果,但是我不是使用球体而是使用2d的方格。glVertexAttribPointer覆盖

我认为hdr部分的quad vertex属性覆盖了在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); 

回答

6

张贴的代码表明如何顶点数组对象(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之前绑定的最近状态集。

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

要使用VAOs有效的程序结构通常是这样的:

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

我不认为你在你的代码有这个问题,但只是为了强调一个相关项目有时会导致混乱:正确GL_ARRAY_BUFFER的结合需要到位的时候glVertexAttribPointer()被调用。不需要为绘制调用建立GL_ARRAY_BUFFER绑定。

+0

为了澄清,保存到当前绑定VAO的唯一绑定是绑定到GL_ELEMENT_ARRAY_BUFFER? – Francis 2014-12-22 07:55:44

+1

是的。当调用'glVertexAttribPointer()'时,'GL_ARRAY_BUFFER'绑定需要到位,然后缓冲区引用成为该属性状态的一部分。 GL_ARRAY_BUFFER绑定本身不是VAO状态的一部分,并且对绘制调用也有影响。 – 2014-12-22 16:21:18