2
$\begingroup$

If no, Should I create a new VAO for every VBO that has its own vertex attribute configurations?

Could you please give me a snippet code example that shows how to use one VAO for multiple VBOs? All examples I find on the internet call to glVertexAttribPointer before drawing a buffer, but if you have to call that method everytime you want to draw a buffer, then VAOs doesn't make sense.

PS: The tutorial I'm following uses Opengl 3.3

$\endgroup$
2
$\begingroup$

Yes, VAO state includes vertex attribute specification for multiple attributes. Each attribute has its own format information and can come from a distinct buffer object. That's part of why you can only bind one VAO at a time.

// two VBOs but one VAO
GLuint points_vbo = 0;
glGenBuffers(1, &points_vbo);
glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);

GLuint colours_vbo = 0;
glGenBuffers(1, &colours_vbo);
glBindBuffer(GL_ARRAY_BUFFER, colours_vbo);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), colours, GL_STATIC_DRAW);

GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);


rendering-loop
{
    glBindVertexArray(vao);

    glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glBindBuffer(GL_ARRAY_BUFFER, colours_vbo);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);

    glDrawArrays(GL_TRIANGLES, 0, 3);
}

PS: you will need to be careful about the location of the vertex attribute. Those used in the rendering loop need to match those in the vertex shader.

$\endgroup$
  • $\begingroup$ Could you please give me a snippet code example that shows how to use one VAO for multiple VBOs? All examples I find on the internet call to glVertexAttribPointer before drawing a buffer, but if you have to call that method everytime you want to draw a buffer, then VAOs doesn't make sense. $\endgroup$ – 4dr14n31t0r Th3 G4m3r Jan 31 '17 at 7:36
  • $\begingroup$ I added some code per OP's request. Hope it's ok. It will need to be approve by Nicol to show up $\endgroup$ – user18490 Jan 31 '17 at 16:46
  • 1
    $\begingroup$ @4dr14n31t0r Th3 G4m3r Note that in the code below you will need to make the call all these functions each time in the rendering loop if you render more than 1 object. Also please accept an answer if acceptable. $\endgroup$ – user18490 Feb 1 '17 at 7:24
4
$\begingroup$

In version 4.3+ the vao layout can be set independently from the VBO buffer which allows you to rebind the vbo without having to call vertexAttribPointer every time:

//in init
glBindVertexArray(vao);

glVertexAttribFormat(posAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, pos));
// set the details of a single attribute
glVertexAttribBinding(posAttrLoc, 0);
// which buffer binding point it is attached to
glEnableVertexAttribArray(posAttrLoc);

glVertexAttribFormat(normalAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, normal));
glVertexAttribBinding(normalAttrLoc, 0);
glEnableVertexAttribArray(normalAttrLoc);

glVertexAttribFormat(texAttrLoc, 2, GL_FLOAT, false, offsetof(Texture, tex));
glVertexAttribBinding(texAttrLoc, 1);
glEnableVertexAttribArray(texAttrLoc);

Note that there is no mention of any VBO during init, just the binding points. That binding point is then used during draw to specify which vbo to pull the vertex data from:

//draw

glBindVertexArray(vao);
foreach(mesh in meshes){
    glBindVertexBuffer(0, mesh.vbo, mesh.vboOffset, sizeof(Vertex));
    glBindVertexBuffer(1, mesh.texVbo, mesh.texVboOffset, sizeof(Texture));
    // bind the buffer to the binding point
    glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);
    //draw
}

In pre 4.3 you would create a VAO per mesh and per mesh call glVertexAttribPointer for each attribute:

glBindVertexArray(mesh.vao);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo);

glVertexAttribPointer (posAttrLoc, 3, GL_FLOAT, false, sizeof(Vertex), mesh.vboOffset + offsetof(Vertex, pos));
glEnableVertexAttribArray(posAttrLoc);
//...

Then during draw bind the per mesh vao before drawing it:

foreach(mesh in meshes){        
    glBindVertexArray(mesh.vao);
    glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount);
}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.