Search code examples
c++openglvertex-array-object

Call to glBindVertexArray(vao): what does it do if 'vao' is already bound, and how to design shape classes accordingly?


I am trying out OpenGL again and I'm wondering how to design the classes that are rendered later on. Right now, there's is only one type of shapes, and so I created a class Shape with a static VAO member that glGenVertexArrays(1, &vao) is called on when the first instance of Shape is created. Now there's a method void Shape::render():

void Shape::render()
{
  glBindVertexArray(vao);
  glDrawArrays(GL_TRIANGLES, foo, bar);
}

Is this a good way to go? I mean, when all the instances of Shape are drawn in the actual program, there is the recurring call to bind Shape::vao, but my guess would be that it doesn't actually do anything if vao is already bound currently. Is that guess correct?

Also, I saw a tutorial some time ago that used to call glBindVertexArray(0) at the end of render(). Wouldn't that be a potential performance loss when there are many shapes?


Solution

  • but my guess would be that it doesn't actually do anything if vao is already bound currently. Is that guess correct?

    Yes. As far as correctness is concerned, re-binding something that already is bound is not a problem.

    It might add a small performance penalty, though. A reasonable GL implementation would probably not do much in this case, but you still have a call into the GL lib, and it has to find the current context of the thread before it has a chance to do nothing. So it might be possible that you are still better off if you cache the currently VAO on your side and only call into the GL if it actually changes. But that is something that only profiling/benchmarking can tell you. If you have many thousands or even millions of instances, that might become a real problem - OTOH, you are screwed than anyway if you have a separate draw call per instance - you should look into instanced rendering in that case.

    Also, I saw a tutorial some time ago that used to call glBindVertexArray(0) at the end of render(). Wouldn't that be a potential performance loss when there are many shapes?

    Yes. Most of the tutorials do this for some "cleanness", but it is really a waste of time in most situations. Unbinding some GL object is only a useful operation if you can (and actually intent to) do something in the "unbound" state - like FBO 0 which is just the default framebuffer. For VAOs, in the core profile, VAO 0 is utterly useless, and you have to bind one in any case before you can draw - so you win nothing by unbinding any other inbetween.