Search code examples
c++openglopengl-3

Do I have to call glVertexAttribPointer() each frame, for each rendered mesh?


I have seen other people's code where they only called glVertexAttribPointer() when they initialized the vao. When I do that, only the first object in my scene gets rendered, but if I call it each frame * each object, everything renders fine... so does this mean I have to set glVertexAttribPointer() for each object before drawing? Or am I missing something?!

        glBindVertexArray(mesh->getVao());
        glBindBuffer(GL_ARRAY_BUFFER, mesh->getVbo());

        for(int i = 0; i < 5; i++)
            glEnableVertexAttribArray(i);

        // Vertex Positions
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
        offset++;
        // Vertex UVs
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
        offset++;
        // Vertex Normals
        glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
        offset++;
        // Vertex Tangents
        glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
        offset++;
        // Vertex Binormals
        glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);

        // Draw
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->getVbo());
        glDrawElements(GL_TRIANGLES, mesh->getNumberOfIndices(), GL_UNSIGNED_SHORT, (void*)0);

        for (int i = 0; i < 5; i++)
            glDisableVertexAttribArray(i);

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

This is 1 draw call per object. It works perfect, but do I really need to call glVertecAttribPointer() each frame for each object as such?


Solution

  • Vertex attribute pointers and index buffers are part of the VAO state, so they only have to be called once in the beginning.

    Init:

    glGenVertexArray(1, &vao);
    glBindVertexArray(vao);
    
    for(int i = 0; i < 5; i++)
        glEnableVertexAttribArray(i);
    
    // Vertex Positions
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
    offset++;
    // Vertex UVs
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
    offset++;
    // Vertex Normals
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
    offset++;
    // Vertex Tangents
    glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
    offset++;
    // Vertex Binormals
    glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 0, (void*)*offset);
    
    // Index Buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->getVbo());
    
    //Unbind VAO
    glBindVertexArray(0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //Unbind the index buffer AFTER the vao has been unbinded
    

    In each frame call

    glBindVertexArray(vao);
    glDrawElements(GL_TRIANGLES, mesh->getNumberOfIndices(), GL_UNSIGNED_SHORT, (void*)0);
    glBindVertexArray(0);