I'm trying to render multiple objects, but only the first object specified is rendering. I have a series of vertices arrays with their corresponding indices in a separate array. According to everything I've read, I simply allot 2 VBOs per object I'm drawing -- one VBO for vertices, one for indices. I generate the buffers and bind them to their respective VAO. When rendering, I then need to have individual draw calls for each object.
This is my code for declaring the needed VAOs and VBOs:
GLuint VAO[5]; // Handle for the vertex array object
GLuint VBO[10]; // Handle for the vertex buffer object
GLuint nMonumentIndices; // Number of indices of the mesh
GLuint nPlaneIndices;
GLuint nBuildingIndices;
GLuint nColumnIndices;
GLuint nPoolIndices;
And this is my code for generating and binding the respective VAOs and VBOs:
const GLuint floatsPerVertex = 3; // Number of coordinates per vertex
const GLuint floatsPerColor = 4; // (r, g, b, a)
// Strides between vertex coordinates is 6 (x, y, r, g, b, a). A tightly packed stride is 0.
GLint stride = sizeof(float) * (floatsPerVertex floatsPerColor);// The number of floats before each
glGenVertexArrays(5, mesh.VAO); //generates 1 vertex array
glGenBuffers(10, mesh.VBO); // generates two VBOs
glBindVertexArray(mesh.VAO[0]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[0]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(monumentVerts), monumentVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nMonumentIndices = sizeof(monumentIndices) / sizeof(monumentIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[1]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(monumentIndices), monumentIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float) * floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindVertexArray(mesh.VAO[1]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[2]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVerts), planeVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nPlaneIndices = sizeof(planeIndices) / sizeof(planeIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[3]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(planeIndices), planeIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindVertexArray(mesh.VAO[2]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[4]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(monumentVerts), monumentVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nBuildingIndices = sizeof(buildingIndices) / sizeof(buildingIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[5]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(buildingIndices), buildingIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindVertexArray(mesh.VAO[3]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[6]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(columnVerts), columnVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nBuildingIndices = sizeof(columnIndices) / sizeof(columnIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[7]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(columnIndices), columnIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
glBindVertexArray(mesh.VAO[4]); //binds our VAO
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO[8]); //binds our first VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(poolVerts), poolVerts, GL_STATIC_DRAW); //sends the vertices to the buffer
mesh.nBuildingIndices = sizeof(poolIndices) / sizeof(poolIndices[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.VBO[9]); //binds second VBO
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(poolIndices), poolIndices, GL_STATIC_DRAW); //sends the indices to the buffer
// Creates the Vertex Attribute Pointer
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, floatsPerColor, GL_FLOAT, GL_FALSE, stride, (char*)(sizeof(float)* floatsPerVertex));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
I also have separate draw calls for each object that I'm rendering:
// Activate the VBOs contained within the mesh's VAO
glBindVertexArray(gMesh.VAO[0]);
glDrawElements(GL_TRIANGLES, gMesh.nMonumentIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
glBindVertexArray(gMesh.VAO[1]);
glDrawElements(GL_TRIANGLES, gMesh.nPlaneIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
glBindVertexArray(gMesh.VAO[2]);
glDrawElements(GL_TRIANGLES, gMesh.nBuildingIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
glBindVertexArray(gMesh.VAO[3]);
glDrawElements(GL_TRIANGLES, gMesh.nColumnIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
glBindVertexArray(gMesh.VAO[4]);
glDrawElements(GL_TRIANGLES, gMesh.nPoolIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(0);
However, when rendering, only the first object (the monument) is drawn. Where am I going wrong? On a code level, are there any flaws?
CodePudding user response:
You cannot bind all the Vertex Array Objects at once. You have to bind the correct Vertex Array Object before the draw call. The current VAO is a global state. Binding a VAO breaks the existing vertex array object binding.
glBindVertexArray(mesh.VAO[0]);
glDrawElements(GL_TRIANGLES, gMesh.nMonumentIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(mesh.VAO[1]);
glDrawElements(GL_TRIANGLES, gMesh.nPlaneIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(mesh.VAO[2]);
glDrawElements(GL_TRIANGLES, gMesh.nBuildingIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(mesh.VAO[3]);
glDrawElements(GL_TRIANGLES, gMesh.nColumnIndices, GL_UNSIGNED_SHORT, NULL);
glBindVertexArray(mesh.VAO[5]);
glDrawElements(GL_TRIANGLES, gMesh.nPoolIndices, GL_UNSIGNED_SHORT, NULL);