问题描述
我对如何在不同的多个程序之间正确切换感到困惑。我已经将问题缩小到以下:如果我运行与NO_HDR,它工作正常;我得到一些线,一艘太空船和一些球,按顺序呈现。如果我使用HDR,我得到的大部分是相同的东西,但而不是球体我得到2d正方形。
I am confused as to how to properly switch between different multiple programs. I've narrowed the problem down to the following: if I run with NO_HDR, it works fine; I get some lines, a space ship, and some spheres, rendered in that order. If I run with HDR, I get mostly the same thing, but instead of spheres I get 2d squares.
我认为来自hdr部分的quad顶点属性会覆盖在forwardRender()部分中渲染的最后一些东西。如果我改变了forwardRender()中的顺序,在forwardRender()中最后渲染的任何东西都会以某种方式被弄乱。我缺少的是允许四顶点覆盖其他对象?
I think the quad vertex attribute from the hdr portion is overwriting the last things to render in the forwardRender() section. If I change the order in forwardRender(), whatever is rendered last in forwardRender() will be messed up in some way. What am I missing that is allowing the quad vertices to overwrite my other objects?
#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
另一个线索:如果我禁用了vertexAttribArray glDrawArrays在结尾,我的球体/方块消失!
Another clue: If I disable the vertexAttribArray after glDrawArrays at the end, my spheres/squares disappear!
为了参考,这里是如何渲染球体在forwardRender():
For reference, here is how I render the spheres in 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是状态的集合。它包含以下调用的状态集:
The posted code suggests a possible misunderstanding of how Vertex Array Objects (VAO) work. A VAO is a collection of state. It contains the state set with the following calls:
-
glVertexAttribPointer(...)
-
glEnableVertexAttribArray(...)
,glDisableVertexAttribArray()
li>
-
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,...)
glVertexAttribPointer(...)
glEnableVertexAttribArray(...)
,glDisableVertexAttribArray()
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...)
每当您进行其中一个调用时,相应的状态将保存在当前绑定的VAO中。
Whenever you make one of these calls, the corresponding state is saved in the currently bound VAO. And when you later bind the VAO again, the state is restored.
例如,按照发布的代码中的顺序:
For example, in this sequence from the posted code:
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
中的状态,
the glDrawArrays()
call will not use the state you set up with the first two calls in the sequence. That state will be applied to whatever VAO is bound at the time. Then, the glBindVertexArray(hdr.vao)
call restores the state stored in hdr.vao
, which is the most recent state set when that VAO was previously bound.
此外,请注意,这与切换程序无关。顶点状态不是程序状态的一部分。
Also note that this has nothing to do with switching programs. Vertex state is not part of the program state.
要有效地使用VAO,您的程序结构通常如下所示:
To use VAOs effectively your program structure would typically look like this:
- 一旦,在设置过程中,您将为每个对象创建一个VAO。例如。一个用于地球,一个用于四边形等。然后绑定每个VAO,并从上面的列表中调用以设置对象的顶点状态。
- 在渲染期间,每个对象,如果需要,改变程序,绑定对象的VAO,并进行绘制调用。您不需要任何其他顶点状态调用,因为状态存储在每个对象的VAO中。
我不认为你的代码中有这个问题,但只是强调一个相关的项目,有时会导致混乱:正确的 GL_ARRAY_BUFFER
绑定需要到位的时候 glVertexAttribPointer()
被调用。没有必要为绘图调用建立 GL_ARRAY_BUFFER
绑定。
I don't think you have a problem with this in your code, but just to emphasize one related item that sometimes causes confusion: The correct GL_ARRAY_BUFFER
binding needs to be in place at the time glVertexAttribPointer()
is called. There is no need to establish GL_ARRAY_BUFFER
bindings for the draw calls.
这篇关于glVertexAttribPointer覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!