Satchmo Brown
Satchmo Brown

Reputation: 1437

OpenGL - Creating multiple VBOs incorrectly

The problem I am having is that once I create a VBO for the main geometry in a level, when I create a second for the objects, the object VBO does not work. I am assuming I have some buffer bound incorrectly but I can't for the life of me find it. I create the level VBO first and then the object VBO and again, when I disable the creation of the level VBO, the object VBO creates correctly.

Here is my code.

in level.h:

// Zone VBO
GLuint zoneVBO;
GLuint zoneVAO;
GLuint zoneIBO;

// Object VBO
GLuint objVBO;
GLuint objVAO;
GLuint objIBO;

Creation of zone (geometry) VBO - just as a note, the creation works correctly in both VBOs so the data moving around isn't the issue, it is I think, a binding error:

void WLD::createZoneVBO()
{
    // Get the size for our VBO
    int numVert = 0;
    int numPoly = 0;
    int VBOsize = 0;
    int IBOsize = 0;

    // Get the count of vertices and polygons
    for(int i = 0; i < zoneFragMap[0x36]; i++)
    {
        numVert += zmeshes[i].numVert;
        numPoly += zmeshes[i].numPoly;
        VBOsize += zmeshes[i].numVert * sizeof(Vertex);
        IBOsize += zmeshes[i].numPoly * 3 * sizeof(GLuint);
    }

    // Create the IBO and VBO data
    GLuint* iboData = new GLuint[zonePolyProcessed * 3];
    Vertex* vboData = new Vertex[zoneVertProcessed];

    int iboPos = 0;
    int vboPos = 0;

    // Create the VBO and IBO
    for(int i = 0; i < zoneFragMap[0x36]; i++)
    {
        // Copy the data to the IBO
        memcpy(&iboData[iboPos], zmeshes[i].indices, zmeshes[i].numPoly * 3 * sizeof(GLuint));//sizeof(*zmeshes[i].indices));

        // Advance the position
        iboPos += zmeshes[i].numPoly * 3;

        // Copy the data to the VBO
        memcpy(&vboData[vboPos], zmeshes[i].vertices, zmeshes[i].numVert * sizeof(Vertex));//sizeof(*zmeshes[i].vertices));

        // Advance the position
        vboPos += zmeshes[i].numVert;
    }

    //Create VBO for the triangle
    glGenBuffers(1, &zoneVBO);
    glBindBuffer(GL_ARRAY_BUFFER, zoneVBO);
    glBufferData(GL_ARRAY_BUFFER, zoneVertProcessed * sizeof(Vertex), vboData, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    //Create the IBO for the triangle
    //16 bit indices
    //We could have actually made one big IBO for both the quad and triangle.
    glGenBuffers(1, &zoneIBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, zoneIBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, zonePolyProcessed * 3 * sizeof(GLuint), iboData, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    // Create the VAO
    glGenVertexArraysAPPLE(1, &zoneVAO);
    glBindVertexArrayAPPLE(zoneVAO);
    glBindBuffer(GL_ARRAY_BUFFER, zoneVAO);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);
    glEnableVertexAttribArray(3);
    glVertexAttribPointer(opaque["position"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
    glVertexAttribPointer(opaque["normal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 3));
    glVertexAttribPointer(opaque["texcoord"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 6));
    glVertexAttribPointer(opaque["color"], 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 8));
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArrayAPPLE(0);

    delete[] iboData;
    delete[] vboData;
}

And the objects - again, the object geometry is loaded perfectly, but only if the zone geometry hasn't been loaded yet:

void WLD::createObjectVBO()
{
    // Get the size for our VBO
    int numVert = 0;
    int numPoly = 0;
    int VBOsize = 0;
    int IBOsize = 0;

    // Get the count of vertices and polygons
    for(int i = 0; i < objFragMap[0x36]; i++)
    {
        numVert += objMeshes[i].numVert;
        numPoly += objMeshes[i].numPoly;
        VBOsize += objMeshes[i].numVert * sizeof(Vertex);
        IBOsize += objMeshes[i].numPoly * 3 * sizeof(GLuint);
    }

    // Create the IBO and VBO data
    GLuint* iboData = new GLuint[objPolyProcessed * 3];
    Vertex* vboData = new Vertex[objVertProcessed];

    int iboPos = 0;
    int vboPos = 0;

    // Create the VBO and IBO
    for(int i = 0; i < objFragMap[0x36]; i++)
    {
        // Copy the data to the IBO
        memcpy(&iboData[iboPos], objMeshes[i].indices, objMeshes[i].numPoly * 3 * sizeof(GLuint));//sizeof(*zmeshes[i].indices));

        // Advance the position
        iboPos += objMeshes[i].numPoly * 3;

        // Copy the data to the VBO
        memcpy(&vboData[vboPos], objMeshes[i].vertices, objMeshes[i].numVert * sizeof(Vertex));//sizeof(*zmeshes[i].vertices));

        // Advance the position
        vboPos += objMeshes[i].numVert;
    }

    //Create VBO for the triangle
    glGenBuffers(1, &objVBO);
    glBindBuffer(GL_ARRAY_BUFFER, objVBO);
    glBufferData(GL_ARRAY_BUFFER, objVertProcessed * sizeof(Vertex), vboData, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    //Create the IBO for the triangle
    //16 bit indices
    //We could have actually made one big IBO for both the quad and triangle.
    glGenBuffers(1, &objIBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, objIBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, objPolyProcessed * 3 * sizeof(GLuint), iboData, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // Create the VAO
    glGenVertexArraysAPPLE(1, &objVAO);
    glBindVertexArrayAPPLE(objVAO);
    glBindBuffer(GL_ARRAY_BUFFER, objVAO);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);
    glEnableVertexAttribArray(3);
    glVertexAttribPointer(opaque["position"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
    glVertexAttribPointer(opaque["normal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 3));
    glVertexAttribPointer(opaque["texcoord"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 6));
    glVertexAttribPointer(opaque["color"], 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(sizeof(float) * 8));
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArrayAPPLE(0);
}

Rendering these two VBOs:

        opaque.Use();
        glBindVertexArrayAPPLE(getVAO(2));
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, zoneIBO);
        glBindBuffer(GL_ARRAY_BUFFER, zoneVBO);
        glUniformMatrix4fv(opaque("camera"), 1, GL_FALSE, glm::value_ptr(cameraMat));
        renderGeometry(&cameraMat, 0, curRegion);
        glBindVertexArrayAPPLE(0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glBindVertexArrayAPPLE(objVAO);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, objIBO);
        glBindBuffer(GL_ARRAY_BUFFER, objVBO);
        glUniformMatrix4fv(opaque("camera"), 1, GL_FALSE, glm::value_ptr(cameraMat));
        renderObjects(&cameraMat);
        glBindVertexArrayAPPLE(0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        opaque.UnUse();

To summarize, I think it's an issue in the creation of the VBOs. I think I am doing something wrong and keeping something bound when it should be bound.

Upvotes: 1

Views: 701

Answers (1)

Tim
Tim

Reputation: 35943

// Create the VAO
glGenVertexArraysAPPLE(1, &zoneVAO);
glBindVertexArrayAPPLE(zoneVAO);
glBindBuffer(GL_ARRAY_BUFFER, zoneVAO);  //<-------
glEnableVertexAttribArray(0);

In the line I have highlighted, this looks like it should be zoneVBO, not zoneVAO.

You should be checking for errors with glGetError, it might have spotted this mistake.

Also it's not required to bind the buffers before calling renderObjects. If you have the vertex pointer stored in the VAO, then you do not need to bind the buffer, as the vertex pointers already point to the correct location.

Upvotes: 2

Related Questions