我正在开发一个小项目,使用的是VBO,IBO和VAO,我有一个顶点数组,以及它们各自的数组索引,因此我对材质进行了相同的处理(因为同一顶点可以在另一侧使用不同的材质),但在VAO中的此链接相同,不会显示任何内容。每个VAO都必须有一个IBO吗?

附件是我的代码,分别向gpu和render发送数据!

谢谢您的帮助,问候:)

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

最佳答案

每个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。您必须具有创造力才能找到适合您使用的解决方案。祝好运!

关于c++ - VAO中的C++ GLSL多个IBO,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25135574/

10-08 20:40