在现代 OpenGL 中显示多个对象时出现问题

Problem displaying multiple objects in modern OpenGL

我试图在 OpenGL 中显示两个形状。 首先,我从 obj 文件和纹理形式的 DDS 中获取顶点、uvs、法线、索引,并将它们存储在 struct Shape 数组中。

然后我索引了 4 个相应数组中所有形状的顶点、uvs、法线和索引,还在另一个向量中存储了顶点、uvs、法线和索引的总数。 然后我初始化了VBO。

然后我为两个形状创建顶点数组对象并设置它们以提供相应的 VertexAttribPointer。 (我觉得问题出在这一步)

最后我绑定了各自的 VAO 并显示它们,但只显示了一个形状。 我到底哪里错了。

VBO 索引代码:

std::vector<glm::vec4> elecount;
long long int endind = 0,endver=0,enduv=0,endnr=0;

std::vector<unsigned short> indices;
std::vector<glm::vec3> indexed_vertices;
std::vector<glm::vec2> indexed_uvs;
std::vector<glm::vec3> indexed_normals;
for (int i = 0;i < componentcount ;i++)
{
    endver = endind = enduv = endnr = 0;
    indexVBO(component[i].vertices, component[i].uvs, component[i].normals, indices, indexed_vertices, indexed_uvs, indexed_normals);
    endind = indices.size();
    endver = indexed_vertices.size();
    enduv = indexed_uvs.size();
    endnr = indexed_normals.size();
    elecount.push_back(glm::vec4(endver, enduv, endnr, endind));
}

VBO 代码:

GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(glm::vec3), &indexed_vertices[0], GL_STATIC_DRAW);

GLuint uvbuffer;
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_uvs.size() * sizeof(glm::vec2), &indexed_uvs[0], GL_STATIC_DRAW);

GLuint normalbuffer;
glGenBuffers(1, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(glm::vec3), &indexed_normals[0], GL_STATIC_DRAW);

GLuint elementbuffer;
glGenBuffers(1, &elementbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0], GL_STATIC_DRAW);

VAO 代码:

    GLuint CubeVertexArrayID, SphereVertexArrayID;
glGenVertexArrays(1, &CubeVertexArrayID);
glGenVertexArrays(1, &SphereVertexArrayID);

glBindVertexArray(CubeVertexArrayID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);

glBindVertexArray(SphereVertexArrayID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)(sizeof(glm::vec3) * ((int)elecount[0][0])));
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(glm::vec2) * ((int)elecount[0][1])));
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(glm::vec3) * ((int)elecount[0][2])));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);

显示代码:

    glBindVertexArray(CubeVertexArrayID);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, component[0].Texture);
    glUniform1i(TextureID, 0);
    glDrawElements(GL_TRIANGLES,(int)elecount[0][3],GL_UNSIGNED_SHORT,(void*)0);

    glm::mat4 ModelMatrix2 = glm::mat4(1.0);
    ModelMatrix2 = glm::translate(ModelMatrix2, glm::vec3(2.0f, 0.0f, 0.0f));
    glm::mat4 MVP2 = ProjectionMatrix * ViewMatrix * ModelMatrix2;
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP2[0][0]);
    glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix2[0][0]);
    glUseProgram(shaderProg);

    glBindVertexArray(SphereVertexArrayID);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, component[1].Texture);
    glUniform1i(TextureID, 0);
    glDrawElements(GL_TRIANGLES, (int)(elecount[1][3]-elecount[0][3]), GL_UNSIGNED_SHORT,(void*)(sizeof(unsigned short) * ((int)elecount[0][3])));

您发布的代码没有任何问题,因此很难确定问题出在哪里。但是,我最好的猜测是 indexVBO (您没有显示)将绝对索引推入 indexed_* 数组。结合 SphereVertexArrayID 的偏移量 glVertexAttribPointer 这会导致越界读取。

您可以修复您的 indexVBO 代码。然而,由于两个 VAO 引用相同的缓冲区,最简单的解决方案(我会说,正确的解决方案)是为两个组件使用单个 VAO。如果我的假设是正确的,那么只要改变

glBindVertexArray(SphereVertexArrayID);

glBindVertexArray(CubeVertexArrayID);

当您绘制第二个组件时。那么你就可以彻底摆脱SphereVertexArrayID