Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Trouble drawing multiple object with OpenGL

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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?

>Solution :

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);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading