无法使用 OpenGL 绘制多个对象

Trouble drawing multiple object with OpenGL

我正在尝试渲染多个对象,但只有指定的第一个对象正在渲染。我有一系列顶点数组,它们在单独的数组中有相应的索引。根据我读过的所有内容,我只是为每个正在绘制的对象分配 2 个 VBO——一个 VBO 用于顶点,一个用于索引。我生成缓冲区并将它们绑定到各自的 VAO。渲染时,我需要为每个对象进行单独的绘制调用。

这是我声明所需 VAO 和 VBO 的代码:

        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;

这是我生成和绑定相应 VAO 和 VBO 的代码:

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

我对正在渲染的每个对象也有单独的绘制调用:

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

但是渲染时,只绘制了第一个对象(纪念碑)。我哪里错了?在代码层面上,是否存在缺陷?

您不能一次绑定所有的顶点数组对象。您必须在绘制调用之前绑定正确的顶点数组对象。当前的 VAO 是一个全局状态。绑定 VAO 会破坏现有的顶点数组对象绑定。

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[4]);
glDrawElements(GL_TRIANGLES, gMesh.nPoolIndices, GL_UNSIGNED_SHORT, NULL);