Search code examples
c++openglvertex-buffer

Associating an attribute with multiple VBOs using glVertexAttribBinding/glVertexArrayAttribBinding


Suppose I have 2 meshes and I used one VBO for each mesh. The vertex attributes (position, normal, color) are contained in a struct:

struct Vertex {
   glm::vec3 position;
   glm::vec3 normal;
   glm::vec3 color;
}

and they are interleaved in the VBO; something like the third option from this link:

Yet another approach is to interleave the vertex attributes for each vertex in a batch, and then store each of these interleaved vertex blocks sequentially, again combining all the vertex attributes into a single buffer. As before, you'd pass byte offsets into the VBO to the glVertexAttribPointer ptr parameters, but you'd also use the stride parameter to ensure each vertex attribute array access only touched elements for that attribute array. Pictorially, this option is: (VNCVNCVNCVNC)

Then I use glVertexAttribFormat / glVertexArrayAttribFormat to specify the formatting properly (position as attribute 0, normal as attribute 1, color as attribute 2). Using glBindVertexBuffer / glVertexArrayVertexBuffer, attach the first VBO to binding index 0 and second VBO to binding index 1:

glVertexArrayVertexBuffer(vao, 0, vbo1, 0, sizeof(Vertex));
glVertexArrayVertexBuffer(vao, 1, vbo2, 0, sizeof(Vertex));

For each attribute, I then use glVertexAttribBinding/glVertexArrayAttribBinding to associate both VBOs:

// Position
glVertexArrayAttribBinding(vao, 0, 0);
glVertexArrayAttribBinding(vao, 0, 1);
// Normal
glVertexArrayAttribBinding(vao, 1, 0);
glVertexArrayAttribBinding(vao, 1, 1);
// Color
glVertexArrayAttribBinding(vao, 2, 0);
glVertexArrayAttribBinding(vao, 2, 1);

Would both VBOs be the data sources and the shaders would read from both of them or would the first VBO be replaced by the second VBO? If it is possible, how would the vertex ordering works in such situation (maybe ordered from first VBO and then second VBO)? Was thinking this would be a good way to implement batch rendering where I could just made a VBO for each mesh and "plug" the VBO to VAO when I want to batch-render multiple meshes.


Solution

  • Any form of "batch rendering" requires the vertices to be in the same buffer object.

    As to the specifics of your code:

    glVertexArrayAttribBinding(vao, 0, 0);
    glVertexArrayAttribBinding(vao, 0, 1);
    

    This is functionally equivalent to:

    i = 0;
    i = 1;
    

    A single vertex attribute comes from one buffer object. Multiple attributes can share the same buffer, but an attribute only gets sourced from a single buffer object. The buffer binding used will be the last one you set (for that attribute, in that VAO), much like i takes on the last value you set it to.