Search code examples
c++openglvertex-buffervertex-array-object

OpenGL Draw Multiple Vertex Arrays


I want to draw multiple vertex arrays. This is the initialization:

unsigned int va1;
unsigned int vb1;

void init_va1() {
    glGenVertexArrays(1, &va1);
    glBindVertexArray(va1);
    glGenBuffers(1, &vb1);
    glBindBuffer(GL_ARRAY_BUFFER, vb1);
    glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(vec2), nullptr, GL_DYNAMIC_DRAW);
    glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(vec2), nullptr);
    glEnableVertexAttribArray(0);
}

unsigned int va2;
unsigned int vb2;

void init_va2() {
    glGenVertexArrays(1, &va2);
    glBindVertexArray(va2);
    glGenBuffers(1, &vb2);
    glBindBuffer(GL_ARRAY_BUFFER, vb2);
    glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(vec2), nullptr, GL_DYNAMIC_DRAW);
    glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(vec2), nullptr);
    glEnableVertexAttribArray(0);
}

At initialization:

init_va1();
init_va2();

At draw:

glBindVertexArray(va1);
vec2 a1[] = {
    vec2(0.0, 0.0),
    vec2(0.1, 0.0),
    vec2(0.1, 0.1),
    vec2(0.0, 0.1),
};
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(a1), a1);
glUniform3f(polygon_color_loc, 0, 1, 0);
glDrawArrays(GL_LINE_LOOP, 0, 4);

glBindVertexArray(va2);
vec2 a2[] = {
    vec2(0.0, 0.0),
    vec2(-0.1, 0.0),
    vec2(-0.1, -0.1),
    vec2(0.0, -0.1),
};
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(a2), a2);
glUniform3f(polygon_color_loc, 1, 0, 0);
glDrawArrays(GL_LINE_LOOP, 0, 4);

Whichever vertex array I initialize last will be drawn properly, and the other one will not be drawn. For example, if I call init_va1() and then init_va2(), the drawing using va2 will be shown, and the drawing using va1 will not. If I reorder the calls, then the drawing using va1 will be shown, and the drawing using va2 will not. How do I draw both vertex arrays?


Solution

  • glBufferSubData changes the data of the buffer that is currently bound to the specified target. The current ARRAY_BUFFER is a globale state. you need to bind the proper buffer object when you want to update the data store of the buffer:

    glBindBuffer(GL_ARRAY_BUFFER, vb1);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(a1), a1);
    
    glBindVertexArray(va1);
    glDrawArrays(GL_LINE_LOOP, 0, 4);
    
    glBindBuffer(GL_ARRAY_BUFFER, vb2);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(a2), a2);
    
    glBindVertexArray(va2);
    glDrawArrays(GL_LINE_LOOP, 0, 4);
    

    In contrast to the ARRAY_BUFFER, the Index buffers (ELEMENT_ARRAY_BUFFER) is stated in the Vertex Array Object. If you want to change the contents of an index buffer, it is also possible just to bind the the VAO in which the index buffer is stated.