Multiple VAO share a VBO Let's say I have a have 10 different terrains. Each terrain have the same x and z coordinates, but they have different y coordinate, normals and colors. The indices used for element rendering is also the same.

The data looks like this:

std::vector&lt;GLfloat&gt; xzCoords;
std::vector&lt;GLuint&gt; indices;

std::vector&lt;GLfloat&gt; yCoords[10];
std::vector&lt;GLfloat&gt; normals[10];
std::vector&lt;GLfloat&gt; colors[10];


And the VBO and VAO IDs:

GLuint VAO_IDs[10];
GLuint VBO_xzCoord_IDs[10];
GLuint VBO_yCoord_IDs[10];
GLuint VBO_indices_IDs[10];
GLuint VBO_normals_IDs[10];
GLuint VBO_colors_IDs[10];


If I want one VAO for each of the terrain deffinitions, how would that look if the VBO for xz coordinates and indices are the same for each?

What I am doing now looks like this:

Setting up the buffers:

for (size_t i = 0; i &lt; 10; i++){
        //VAO
        glGenVertexArrays(1, &amp;VAO_IDs[i]);
        glBindVertexArray(VAO_IDs[i]);

        //VBO
        glGenBuffers(1, &amp;VBO_xzCoord_IDs[i]);
        glGenBuffers(1, &amp;VBO_yCoord_IDs[i]);
        glGenBuffers(1, &amp;VBO_indices_IDs[i]);
        glGenBuffers(1, &amp;VBO_normals_IDs[i]);
        glGenBuffers(1, &amp;VBO_colors_IDs[i]);

        //xz coords
        glBindBuffer(GL_ARRAY_BUFFER, VBO_xzCoord_IDs[i]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*xzCoords.size(), &amp;xzCoords[0], GL_STATIC_DRAW);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
        glEnableVertexAttribArray(0);
        //y coords
        glBindBuffer(GL_ARRAY_BUFFER, VBO_yCoord_IDs[i]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*yCoords[i].size(), &amp;yCoords[i][0], GL_STREAM_DRAW);
        glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, (void*)0);
        glEnableVertexAttribArray(1);
        //normals
        glBindBuffer(GL_ARRAY_BUFFER, VBO_normals_IDs[i]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*VBO_normals_IDs[i].size(), &amp;VBO_normals_IDs[i][0], GL_STREAM_DRAW);
        glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 0, (void*)0);
        glEnableVertexAttribArray(2);
        //colors
        glBindBuffer(GL_ARRAY_BUFFER, VBO_colors_IDs[i]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*VBO_colors_IDs[i].size(), &amp;VBO_colors_IDs[i][0], GL_STREAM_DRAW);
        glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, (void*)0);
        glEnableVertexAttribArray(3);

//indices
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO_indices_IDs[i]);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*indices.size(), &amp;indices[0], GL_STATIC_DRAW);
    }


Rendering function:

for (size_t i = 0; i &lt; 10; i++)
    {
        glBindVertexArray(VAO_IDs[i]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO_indices_IDs[i]);
        glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void*)0);

    }


So as you can see, I create a new xz-coordinates and indices buffer for each VAO. I doubt this is the most effective way to do it. How should I do this?
VAO can share VBO's because they do not store vertex data itself but references to Vertex Buffer Objects. 

So you can first generate your buffers and upload your buffer data (vertex data and index data) to currently bound buffers.

glGenBuffers(1, &amp;VBO_xzCoord_IDs[i]);
glGenBuffers(1, &amp;VBO_yCoord_IDs[i]);
glGenBuffers(1, &amp;VBO_indices_IDs[i]);
glGenBuffers(1, &amp;VBO_normals_IDs[i]);
glGenBuffers(1, &amp;VBO_colors_IDs[i]);

//xz coords
glBindBuffer(GL_ARRAY_BUFFER, VBO_xzCoord_IDs[i]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*xzCoords.size(), &amp;xzCoords[0], GL_STATIC_DRAW);

...

//indices
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO_indices_IDs[i]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*indices.size(), &amp;indices[0], GL_STATIC_DRAW);


And then generate your VAO's and connect vertex array object data index you provide in glVertexAttribPointer call with currently bound GL_ARRAY_BUFFER.

The GL_ELEMENT_ARRAY_BUFFER can be a little confusing because it doesn't require glVertexAttribPointer call. So how it is connected with VAO? It seems that binding the buffer ties it to the currently bound VAO.

//VAO
glGenVertexArrays(1, &amp;VAO_IDs[i]);
glBindVertexArray(VAO_IDs[i]);

//xz coords
glBindBuffer(GL_ARRAY_BUFFER, VBO_xzCoord_IDs[i]);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

...

//indices
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO_indices_IDs[i]);

glBindVertexArray(0);


And in your rendering call you don't need to bind GL_ELEMENT_ARRAY_BUFFER because it was already connected with VAO.