OpenGL - 错误地创建多个 VBO

Posted

技术标签:

【中文标题】OpenGL - 错误地创建多个 VBO【英文标题】:OpenGL - Creating multiple VBOs incorrectly 【发布时间】:2012-08-18 00:27:37 【问题描述】:

我遇到的问题是,一旦我为关卡中的主要几何图形创建了 VBO,当我为对象创建第二个 VBO 时,对象 VBO 不起作用。我假设我有一些不正确的缓冲区绑定,但我一辈子都找不到它。我先创建关卡 VBO,然后再创建对象 VBO,当我禁用关卡 VBO 的创建时,对象 VBO 会正确创建。

这是我的代码。

在 level.h 中:

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

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

创建区域(几何)VBO - 就像一个注释,创建在两个 VBO 中都能正常工作,所以数据移动不是问题,我认为这是一个绑定错误:

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;

还有对象——同样,对象几何体已完美加载,但前提是区域几何体尚未加载:

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

渲染这两个 VBO:

        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();

总而言之,我认为这是创建 VBO 的一个问题。我认为我做错了什么,并在应该绑定的时候保持绑定。

【问题讨论】:

尝试从渲染代码中删除 glBindBuffer。如果内存正常,您只需重新绑定顶点数组。 @iKlsR 当我这样做时,我得到一个 EXC_BAD_ACCESS 运行时错误。 【参考方案1】:
// Create the VAO
glGenVertexArraysAPPLE(1, &zoneVAO);
glBindVertexArrayAPPLE(zoneVAO);
glBindBuffer(GL_ARRAY_BUFFER, zoneVAO);  //<-------
glEnableVertexAttribArray(0);

在我突出显示的行中,这看起来应该是zoneVBO,而不是zoneVAO

您应该使用 glGetError 检查错误,它可能已经发现了这个错误。

在调用 renderObjects 之前不需要绑定缓冲区。如果您将顶点指针存储在 VAO 中,则无需绑定缓冲区,因为顶点指针已经指向正确的位置。

【讨论】:

以上是关于OpenGL - 错误地创建多个 VBO的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL几何着色器三角形不会没有错误地绘制

具有多个设备(监视器)的 OpenGL 上下文

OpenGL - 会使用多个 VBO 减慢渲染速度吗?

Opengl着色器:如果条件错误地评估为假

OpenGL中的多个渲染目标与Cg

在小 alpha 值上错误地在 OpenGL 中混合