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

时间:2020-04-04 07:26:23

标签: c++ opengl glm-math vbo vao

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

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

然后,我为两个形状创建顶点数组对象,并将其设置为各自的VertexAttribPointer。 (我认为问题出在这一步)

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

VBOindexing的代码:

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

1 个答案:

答案 0 :(得分:1)

您发布的代码没有错,因此很难确定问题出在哪里。但是,我最大的猜测是indexVBO(您未显示)将indexed_*数组中的绝对索引推送。结合偏移量glVertexAttribPointer的偏移量SphereVertexArrayID导致超出范围的读取。

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

glBindVertexArray(SphereVertexArrayID);

glBindVertexArray(CubeVertexArrayID);

绘制第二个组件时。然后,您可以完全摆脱SphereVertexArrayID