0

我正在开发一个小项目,我正在使用 VBO、IBO 和 VAO,我有一个顶点数组及其各自的数组索引,我对材料做同样的事情(因为相同的顶点可以在另一侧有不同的材料) 但 VAO 中的此链接不显示任何内容。每个 VAO 都必须是 IBO?

附件是我的代码,其中分别将数据发送到 gpu 和渲染!

我会很感激你的帮助,问候:)

void Upload(){
    GLuint ibo[2], vbo[3];

    glGenBuffers(3, vbo);
    glGenBuffers(2, ibo);
    glGenVertexArrays(1, vao);

    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); //Vertices
    glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(vec3), vertices.data(), GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); //Normales
    glBufferData(GL_ARRAY_BUFFER, vertex_normal.size()*sizeof(vec3), vertex_normal.data(), GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, v_indices.size()*sizeof(GLuint), v_indices.data(), GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glBindBuffer(GL_ARRAY_BUFFER, vbo[2]); //Material
    glBufferData(GL_ARRAY_BUFFER, materials.size()*sizeof(Material), materials.data(), GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.size()*sizeof(GLuint), m_indices.data(), GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glBindVertexArray(vao[0]);
    //Vertices:
    glEnableVertexAttribArray(attrib_vertex);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glVertexAttribPointer(attrib_vertex, 3, GL_FLOAT, GL_FALSE, 0, 0);
    //Normales:
    glEnableVertexAttribArray(attrib_normal);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    glVertexAttribPointer(attrib_normal, 3, GL_FLOAT, GL_FALSE, 0, 0);
    //IBO:
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[0]);

    //Materiales:
    for(int i=0; i<5; ++i)
        glEnableVertexAttribArray(attrib_material+i);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
    glVertexAttribPointer(attrib_material, 4, GL_FLOAT, GL_FALSE, sizeof(Material), NULL);
    glVertexAttribPointer(attrib_material+1, 4, GL_FLOAT, GL_FALSE, sizeof(Material), (void*)offsetof(Material, diffuse));
    glVertexAttribPointer(attrib_material+2, 4, GL_FLOAT, GL_FALSE, sizeof(Material), (void*)offsetof(Material, specular));
    glVertexAttribPointer(attrib_material+3, 4, GL_FLOAT, GL_FALSE, sizeof(Material), (void*)offsetof(Material, emission));
    glVertexAttribPointer(attrib_material+4, 1, GL_FLOAT, GL_FALSE, sizeof(Material), (void*)offsetof(Material, shininess));

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[1]);

    //Desactivando todo:
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDisableVertexAttribArray(attrib_vertex);
    glDisableVertexAttribArray(attrib_normal);
    for(int i=0; i<5; ++i)
        glDisableVertexAttribArray(attrib_material+i);
}
void Draw(){
    glBindVertexArray(vao[0]);
    glDrawElements(GL_TRIANGLES, v_indices.size(), GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
}
4

1 回答 1

1

每个 VAO 存储当前的值GL_ELEMENT_ARRAY_BUFFER_BINDING

该存储值在您调用glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[0])和时设置glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[1])

您的代码的问题是您的第二次调用glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,...)是覆盖第一次调用存储的值。发生这种情况是因为每个 VAO 只能为GL_ELEMENT_ARRAY_BUFFER_BINDING. 也就是说,每个 VAO 只允许 1 个 IBO。

我提出的一些解决方案:

  • 您可以以不同方式存储材质数据,使其与网格中的索引相匹配。这可能意味着您需要复制材料数据。
  • 您可以将材质数据存储在统一缓冲区中,然后将材质数据的索引存储在统一缓冲区中作为每个顶点的顶点属性。
  • 您的材质似乎定义了照明信息。也许您可以将渲染拆分为多个通道。(即环境通道、漫反射通道、镜面反射通道......) 像延迟光照这样的渲染方法将使其成为非问题。
  • 您可以将顶点和材质的索引组合成一个大 IBO。(可能与我提到的其他方法结合使用。)
  • glVertexAttribDivisor如果您的数据符合模式,您也许可以使用。

无论哪种方式,核心问题是每个 VAO 只能有 1 个 IBO。您必须具有创造性才能找到适合您使用的解决方案。祝你好运!

于 2014-08-05T09:54:52.107 回答