版本 4.3

Version >= 4.3

OpenGL 4.3(或 ARB_separate_attrib_format)新增了一種指定頂點資料的替代方法,它在屬性繫結的資料格式和提供資料的緩衝區物件源之間建立了分隔。因此,不是每個網格都有 VAO,而是每個頂點格式都有一個 VAO。

每個屬性都與頂點格式和繫結點相關聯。頂點格式由型別,元件計數,是否規範化以及從資料起點到該特定頂點的相對偏移量組成。繫結點指定屬性從哪個緩衝區獲取其資料。通過分離兩者,你可以繫結緩衝區而無需重新指定任何頂點格式。你還可以使用單個繫結呼叫將用於提供資料的緩衝區更改為多個屬性。

//accessible constant declarations
constexpr int vertexBindingPoint = 0;
constexpr int texBindingPoint = 1;// free to choose, must be less than the GL_MAX_VERTEX_ATTRIB_BINDINGS limit

//during initialization
glBindVertexArray(vao);

glVertexAttribFormat(posAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, pos));
// set the details of a single attribute
glVertexAttribBinding(posAttrLoc, vertexBindingPoint);
// which buffer binding point it is attached to
glEnableVertexAttribArray(posAttrLoc);

glVertexAttribFormat(normalAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, normal));
glVertexAttribBinding(normalAttrLoc, vertexBindingPoint);
glEnableVertexAttribArray(normalAttrLoc);

glVertexAttribFormat(texAttrLoc, 2, GL_FLOAT, false, offsetof(Texture, tex));
glVertexAttribBinding(texAttrLoc, texBindingPoint);
glEnableVertexAttribArray(texAttrLoc);

然後在繪製期間保持 vao 繫結並僅更改緩衝區繫結。

void drawMesh(Mesh[] mesh){
    glBindVertexArray(vao);

    foreach(mesh in meshes){
        glBindVertexBuffer(vertexBindingPoint, mesh.vbo, mesh.vboOffset, sizeof(Vertex));
        glBindVertexBuffer(texBindingPoint, mesh.texVbo, mesh.texVboOffset, sizeof(Texture));
        // bind the buffers to the binding point

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ebo);

        glDrawElements(GL_TRIANGLES, mesh.vertexCount, GL_UNSIGNED_INT, mesh.indexOffset);
        //draw
    }
}