Home > Blockchain >  Trouble drawing multiple object with OpenGL
Trouble drawing multiple object with OpenGL

Time:02-14

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);
  • Related