C ++ GLSL VAO中的多个IBO

时间:2014-08-05 09:37:02

标签: c++ glsl vbo vao

我正在开发一个小项目,我正在使用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);
}

1 个答案:

答案 0 :(得分: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。您必须具有创造性才能找到适合您使用的解决方案。祝你好运!