1

I'm following basic tutorial on OpenGL 3.0. What is not clear to me why/if I have to bind, enable and unbind/disable all vertex buffers and textures each frame.

To me it seems too much gl**** calls which I guess have some overhead. For example here you see each frame several blocks like:

// do this for each mesh in scene
// vertexes
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glVertexAttribPointer(  0, 3, GL_FLOAT,GL_FALSE,0,(void*)0);
// normals
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, normal_buffer );
glVertexAttribPointer(  1, 3, GL_FLOAT,GL_FALSE,0,(void*)0);
// UVs
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, uv_buffer    );
glVertexAttribPointer(  2, 2, GL_FLOAT,GL_FALSE,0,(void*)0);

// ...
glDrawArrays(GL_TRIANGLES, 0, nVerts );
// ...
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);

imagine you have not just one but 100 different meshes each with it's own VBOs for vertexes,normas,UVs. Should I really do this procedure each frame for each of them? Sure I can encapsulate that complexity into some function/objects, but I worry about overheads of this gl**** function calls.

Is it not possible some part of this machinery to move from per frame loop into scene setup ?

Also I read that VAO is a way how to pack corresponding VBOs for one object together. And that binding VAO automatically binds corresponding VBOs. So I was thinking that maybe one VAO for each mesh (not instance) is how it should be done - but according to this answer it does not seems so?

Community
  • 1
  • 1
Prokop Hapala
  • 2,424
  • 2
  • 30
  • 59
  • A **first** step of optimizing that code is one set of buffers + one VAO per "object". A **second** step of optimizing that code is one set of buffers + one VAO per "group of objects that share the same vertex attribute formats" (by having bigger buffers, combining multiple objects in them). – peppe Nov 05 '16 at 13:48
  • If you only have a 100 objects, switching VAOs per object should not even be close to a performance bottleneck. – Reto Koradi Nov 05 '16 at 15:45

2 Answers2

2

First things first: Your concerns about GL call overhead have been addressed with the introduction of Vertex Array Objects (see @Criss answer). However the real problem with your train of thought is, that you equate VBOs with geometry meshes, i.e. give each geometry its own VBO.

That's not how you should see and use VBOs. VBOs are chunks of memory and you can put the data of several objects into a single VBO; you don't have to draw the whole thing, you can limit draw calls to subsets of a VBO. And you can coalesce geometries with similar or even identical drawing setup and draw them all at once with a single draw call. Either by having the right vertex index list, or by use of instancing.

When it comes to the binding state of textures… well, yeah, that's a bit more annoying. You really have to do the whole binding dance when switching textures. That's why in general you sort geometry by texture/shader before drawing, so that the amount of texture switches is minimized.

The last 3 or 4 generations of GPUs (as of late 2016) do support bindless textures though, where you can access textures through a 64 bit handle (effectively the address of the relevant data structure in some address space) in the shader. However bindless textures did not yet make it into the core OpenGL standard and you have to use vendor extensions to make use of it.

Another interesting approach (popularized by Id Tech 4) is virtual textures. You can allocate sparsely populated texture objects that are huge in their addressable size, but only part of them actually populated with data. During program execution you determine which areas of the texture are required and swap in the required data on demand.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
0

You should use vertex array object (generated by glGenVertexArrays). Thanks to it you don't have to perform those calls everytime. Vertex buffer object stores:

  • Calls to glEnableVertexAttribArray or glDisableVertexAttribArray.
  • Vertex attribute configurations via glVertexAttribPointer.
  • Vertex buffer objects associated with vertex attributes by calls to glVertexAttribPointer.

Maybe this will be better tutorial.

So that you can generate vao object, then bind it, perform the calls and unbind. Now in drawing loop you just have to bind vao.

Example:

  glUseProgram(shaderId);
  glBindVertexArray(vaoId);
  glDrawArrays(GL_TRIANGLES, 0, 3);
  glBindVertexArray(0);
  glUseProgram(0);
Community
  • 1
  • 1
Criss
  • 581
  • 5
  • 17