Search code examples
c++openglsdlvao

VBO must be bound after VAO


Code:

void render()
{
    glClear(GL_COLOR_BUFFER_BIT);

    GLfloat vertices[6][4] = {
        { 1.0f, 1.0f, 1.0f, 1.0f },
        { 1.0f, 1.0f, 1.0f, 1.0f },
        { 1.0f, 1.0f, 1.0f, 1.0f },

        { 1.0f, 1.0f, 1.0f, 1.0f },
        { 1.0f, 1.0f, 1.0f, 1.0f },
        { 1.0f, 1.0f, 1.0f, 1.0f }
    };

    glUseProgram(shadptr->progGraphics);
    glBindVertexArray(vao_g);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_g);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, vertices, GL_DYNAMIC_DRAW);
    glDrawArrays(GL_TRIANGLES, 0, 6);

    glUseProgram(shadptr->progText);
    glBindVertexArray(vao_t);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_t);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, vertices, GL_DYNAMIC_DRAW);
    glDrawArrays(GL_TRIANGLES, 0, 6);

    SDL_GL_SwapWindow(winptr->window);
}

void set_buffers()
{
    glGenVertexArrays(1, &vao_g);
    glBindVertexArray(vao_g);

    glGenBuffers(1, &vbo_g);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_g);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr);

    glGenVertexArrays(1, &vao_t);
    glBindVertexArray(vao_t);

    glGenBuffers(1, &vbo_t);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_t);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr);
}

I have a problem. I don't know why I have to bind vbo after binding vao in render function. When I don't bind vbo, in RenderDoc I have an error "glDrawArrays has generated an error (GL_OUT_OF_MEMORY)" and in mesh output, in VS input I see wrong values or --- value.


Solution

  • I don't know why I have to bind vbo after binding vao in render function"

    Because you try to create and initialize the buffer object 's data store by glBufferData and for this the buffer has to be bound.

    I recommend to move the code, which creates and initializes the buffer to set_buffers. Then it will be sufficient to bind the vertex array object only, in the function render:

    void render()
    {
        glClear(GL_COLOR_BUFFER_BIT);
    
        glUseProgram(shadptr->progGraphics);
        glBindVertexArray(vao_g);
        glDrawArrays(GL_TRIANGLES, 0, 6);
    
        glUseProgram(shadptr->progText);
        glBindVertexArray(vao_t);
        glDrawArrays(GL_TRIANGLES, 0, 6);
    
        SDL_GL_SwapWindow(winptr->window);
    }
    

    void set_buffers()
    {
        ....
    
        GLfloat vertices[6][4] = {
            { 1.0f, 1.0f, 1.0f, 1.0f },
            { 1.0f, 1.0f, 1.0f, 1.0f },
            { 1.0f, 1.0f, 1.0f, 1.0f },
    
            { 1.0f, 1.0f, 1.0f, 1.0f },
            { 1.0f, 1.0f, 1.0f, 1.0f },
            { 1.0f, 1.0f, 1.0f, 1.0f }
        };
    
        glBindBuffer(GL_ARRAY_BUFFER, vbo_g);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, vertices, GL_DYNAMIC_DRAW);
    
        glBindBuffer(GL_ARRAY_BUFFER, vbo_t);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, vertices, GL_DYNAMIC_DRAW);
    
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    

    I recommend to use glBufferSubData, to change the content of a buffer. This will update the buffer, but doesn't creates and initializes a completely new data store and thus would be much more efficient.