Reputation: 55
I am rendering two different objects to the screen using two rendering programs. Each program has it's own vertex and fragment shader associated with it.
In the following code I am creating the first rendering program and using a GL_ARRAY_BUFFER to load the vertices into the shader:
boardRenderingProgram = compileBoardShaders();
vector<GLfloat> boardVertices = board.getBorderVertices();
GLfloat* borderVertices = &boardVertices[0];
GLuint numberOfVerts = boardVertices.size();
GLuint anotherVBO;
GLuint anotherBuffer;
glGenVertexArrays(1, &anotherVBO);
glBindVertexArray(anotherVBO);
glGenBuffers(1, &anotherBuffer);
glBindBuffer(GL_ARRAY_BUFFER, anotherBuffer);
glBufferData(GL_ARRAY_BUFFER, numberOfVerts*3*sizeof(GLfloat), NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, numberOfVerts*3*sizeof(GLfloat), borderVertices);
vert = glGetAttribLocation(boardRenderingProgram, "vBoardPosition");
glVertexAttribPointer(vert, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(vert);
Vertex shader for first program:
#version 330 core
layout(location = 0) in vec4 vBoardPosition;
void main() {
gl_Position = vBoardPosition;
}
I then do exactly the same thing for the second rendering program, I am also setting a rotation and translation matrix in the second program:
renderingProgram = compileShaders();
moveMatrix = glm::make_mat4(moveArray);
currentBlockVertices = generator.getRandomBlock(blockNumber).getVertices();
numberOfVertices = 8;
GLfloat* vertices = ¤tBlockVertices[0];
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, numberOfVertices*7*sizeof(GLfloat), NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, numberOfVertices*3*sizeof(GLfloat), vertices);
vpos = glGetAttribLocation(renderingProgram, "vPosition");
glVertexAttribPointer(vpos, 3, GL_FLOAT, GL_FALSE, 0, 0);
mpos = glGetUniformLocation(renderingProgram, "mMove");
rpos = glGetUniformLocation(renderingProgram, "mRotate");
glProgramUniformMatrix4fv(renderingProgram, mpos, 1, GL_FALSE, glm::value_ptr(moveMatrix));
glProgramUniformMatrix4fv(renderingProgram, rpos, 1, GL_FALSE, glm::value_ptr(rotateMatrix));
glEnableVertexAttribArray(vpos);
Vertex shader for second program:
#version 330 core
layout(location = 0) in vec4 vPosition;
layout(location = 1) uniform mat4 mMove;
layout(location = 2) uniform mat4 mRotate;
void main() {
gl_Position = mMove * mRotate * vPosition;
}
Once these programs are created I use the following code in my render function to draw them to the screen:
glUseProgram(boardRenderingProgram);
glDrawArrays(GL_POINTS, 0, 8);
glUseProgram(renderingProgram);
glDrawArrays(GL_LINE_LOOP, 0, 8);
SwapBuffers(hDC_);
However, despite specifying different vertices to load into each rendering program, both rendering programs draw the same vertices to the screen. It also seems that the rendering program that is created second determines which vertices are used.
I have tried adding additional glUseProgram() calls before and after the vertex and matrix attributes are set but this doesn't seem to help.
Why are the two programs drawing the same vertices when I have loaded different vertices into each one?
Upvotes: 2
Views: 1002
Reputation: 55
Ok so after further investigation I found that the line that cleared the vertices when loading the second shader was glBindVertexArray().
Following advice from here: https://gamedev.stackexchange.com/questions/49749/why-doesnt-glbindvertexarray-work-in-this-case I changed my rendering code to add a glBindVertexArray() before each draw call:
glBindVertexArray(boardVertexArrayObject);
glUseProgram(boardRenderingProgram);
glDrawArrays(GL_LINES, 0, 6);
glBindVertexArray(pieceVertexArrayObject);
glUseProgram(renderingProgram);
glDrawArrays(GL_LINE_LOOP, 0, 8);
SwapBuffers(hDC_);
Apparently glBindVertexArray() should be called before modifying the VBO and before drawing. Code now works correctly!
Upvotes: 0
Reputation: 52082
#version 330 core
...
layout(location = 1) uniform mat4 mMove;
layout(location = 2) uniform mat4 mRotate;
^^^^^^^^^^^^^^^^^^^^
Explicit uniform locations have only been core since OpenGL 4.3. You need to check for GL_ARB_explicit_uniform_location
before using them on prior versions.
I suspect your second shader failed to compile. Make sure you check for shader compilation and program link success via GL_COMPILE_STATUS
/GL_LINK_STATUS
before calling glUseProgram()
.
Upvotes: 2