【问题标题】:Problem displaying multiple objects in modern OpenGL [closed]在现代 OpenGL 中显示多个对象的问题 [关闭]
【发布时间】:2020-07-16 09:31:27
【问题描述】:

我正在尝试在 OpenGL 中显示两个形状。 首先,我从 obj 文件和纹理形式 DDS 中获取顶点、UV、法线、索引,并将它们存储在 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])));

【问题讨论】:

  • 问题是什么?你说有问题,但是什么不行?
  • @Rabbid76 当我调用 glDrawElement 时,只显示一个形状。我会在几秒钟内更新问题。
  • @curs0r:indexVBO 推送到indices 的索引是什么?
  • @ybungalobill 它推送要打印的索引,如果有两个不同的索引打印相同的顶点,它将用单个索引替换它们。
  • @curs0r:这不是我问题的本质。由于我在下面的回答对您有用,这意味着 indexVBO 计算的索引不正确。这就是为什么您应该提供该函数的代码。

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


【解决方案1】:

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

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

glBindVertexArray(SphereVertexArrayID);

glBindVertexArray(CubeVertexArrayID);

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

【讨论】:

  • 我确实做到了这一点,并且成功了。我打算添加多个对象,所以我使用了不同的缓冲区。将其更改为单个缓冲区有效。谢谢@ybungalobill
  • @curs0r:最好尽可能使用单个 VAO,即使是多个对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多