Reputation: 273
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.
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
Another clue: If I disable the vertexAttribArray after glDrawArrays at the end, my spheres/squares disappear!
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);
Upvotes: 1
Views: 926
Reputation: 54642
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()
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...)
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
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.
To use VAOs effectively your program structure would typically look like this:
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.
Upvotes: 7