Search code examples
openglvertex-array-objectvertex-buffer-objects

how does a VBO get attached to a VAO


VAO being Vertex Array Object and VBO being Vertex Buffer Object. The calls for creating and binding/unbinding VAOs and VBOs have a general format as given below:

GLuint VAO, VBO;
glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

        glGenBuffers(1, &VBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
            glBufferData(GL_ARRAY_BUFFER, 
                            sizeof(GLfloat)* 9,
                            vertices,
                            GL_STATIC_DRAW);
            glVertexAttribPointer(0,
                    3, GL_FLOAT, GL_FALSE,
                    0, 0);
            glEnableVertexAttribArray(0);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);    

I've followed some tutorials on the internet, and they say that the VBO is bound to the VAO, but in the above code, I don't get how the "connection" or "binding" is established between the VBO and the VAO? I mean how do we know which VBO is bound to which VAO and what if a VBO is to be bound to multiple VAOs?

So, the basic question is: what does VBO is bound to VAO mean, how do we know which VBO is bound to which VAO and how is this binding established?


Solution

  • how does a VBO get attached to a VAO

    It is attached when glVertexAttribPointer is called.

    Each attribute which is stated in the Vertex Array Objects state vector may refer to a different Vertex Buffer Object. This reference is stored when glVertexAttribPointer is called. Then the buffer which is currently bound to the target ARRAY_BUFFER is associated to the attribute and the name (value) of the object is stored in the state vector of the VAO. The ARRAY_BUFFER binding is a global state.

    This behaves different to the Index Buffer (ELEMENT_ARRAY_BUFFER). The index buffer binding is stated within the Vertex Array Object. When a buffer is bound to the target ELEMENT_ARRAY_BUFFER, then this buffer is associated to the vertex array object which is currently bound.


    That means when you call glBindBuffer(GL_ARRAY_BUFFER, VBO);, then a global state is set that stores VBO. glVertexAttribPointer retrieves VBO from the global state and assoicates it to VAO. When glBindBuffer(GL_ARRAY_BUFFER, ...) is called again, then the previous binding is lost, but of course it does not change any state of the VAO.

    glBindVertexArray(VAO);              # bind VAO (global state)
    
    glBindBuffer(GL_ARRAY_BUFFER, VBO1); # bind VBO1 (global state)
    glVertexAttribPointer(0, ...);       # associate VBO1 to attribute 0 in VAO
    
    glBindBuffer(GL_ARRAY_BUFFER, VBO2); # bind VBO2 (change global state, VBO1 binding is lost)
    glVertexAttribPointer(1, ...);       # associate VBO2 to attribute 1 in VAO