c++ - 使用 OpenGL 绘制多个对象时遇到问题

标签 c++ opengl

我正在尝试渲染多个对象,但只有指定的第一个对象正在渲染。我有一系列顶点数组,它们相应的索引位于一个单独的数组中。根据我读到的所有内容,我只是为我正在绘制的每个对象分配 2 个 VBO——一个用于顶点,一个用于索引。我生成缓冲区并将它们绑定(bind)到各自的 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;

这是我用于生成和绑定(bind)相应 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);

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

最佳答案

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

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

关于c++ - 使用 OpenGL 绘制多个对象时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71102423/

相关文章:

c++ - 使用 cv::addWeighted 时出错

c++ - 无法编译旧的 WIN32 WINAPI 程序

opengl - 在 GLSL 中选择立方体贴图的面

OpenGL 着色语言不同类型的变量(限定符)

java - 在 Java 中渲染 "Slice"的球体 - 效率

c++ - 异步运行的函数的返回类型应该是什么

C++ 简单树遍历并将行存储在 vector 的行中。错误 : no matching function for call to 'std::vector<int>::push_back(std::vector<int>&)'

c++ - 使用字符串内存

c++ - 在其一侧显示 glutSolidCone

c# - GUI、跨平台、C# 和 OpenGL。是否可以?