I'm making some tests with OpenGL ES 2 and got some questions, my current program is like that:

-> create index buffer
-> fill index buffer glBufferData …
-> create vertex buffer
-> fill vertex buffer glBufferData …

 1. Apply vertex buffer

    -> Bind VAO
       -> bind vertex buffer
          - enable attributs (glVertexPointer, …)
       -> unbind vertex buffer
    -> Unbind VAO
    -> Bind VAO

 3. Apply index buffer
 4. Draw

The problem

The given code crash, after some researches, I've understood why: I need to unbind my index buffer in init part (after "fill index buffer glBufferData") or unbind it before the first "Bind VAO"

My questions are:

  • Can I put my index buffer in VAO (VAO stock index buffer?)?
  • Did I have to unbind buffers after each update (glBufferData)?

In my application I've got some buffers who are updated on each frame (Exemple: Particles) so I've got an OpenGL stack like that:

-> bind buffer 1
-> update buffer 1
-> close buffer 1
-> bind buffer 1
-> draw

First 3 lines update the Vertex buffer, the two last draw object, that should be something like that:

-> bind buffer 1
-> update buffer 1
-> draw



1 Answer 1


You seem to be doing a lot on unnecessary binding/unbinding. If you are using a VAO, then you should only bind the VAO when you set it up and when drawing the geometry. You only bind the VBO/IBO again when you need to update them.

After drawing or updating a buffer, you don't necessarily have to unbind it, though it might be a good idea to do so to avoid accidental writes to buffers that were left bound.

Now taking your fist sequence of operations, this is the overall order I would expect to see:

On init:

  1. Create & bind a VAO. Any VBO and IBO that you bind in the sequence will be associated with the current VAO (this one).

  2. Create & bind index buffer.

    • Fill index buffer with glBufferData/glMapBuffer.
  3. Create & bind vertex buffer.

    • Fill vertex buffer glBufferData/glMapBuffer.
  4. Set up vertex attributes with glEnableVertexAttribArray/glVertexAttribPointer, etc.

  5. Optionally unbind everything to avoid accidental modification of the buffers and VAO. Remember to unbind the VAO first. E.g.: glBindVertexArray(0);

On draw:

  1. If only drawing the buffers:

    • Bind the VAO;
    • Perform the draw call(s).
  2. If updating and drawing:

    • Bind the VAO, VBO, IBO;
    • Update the buffers (updating vertex atributes is only necessary if the vertex format has changed);
    • Perform the draw call(s).
  3. Optionally unbind to avoid accidental modification of the buffers and VAO.

That's as simple as that. This order of operations should function without problems.

  • 2
    \$\begingroup\$ I'd like to add that in my experiments (2014) with real-life cases (but simple shaders as to not bottleneck at the GPU) I found the performance improvements using VAO to be insignificant (<2% CPU savings) after proper ordering of render calls was implemented to completely skip VBO setup when using the same VBO on consecutive render calls (10 to 33% CPU savings), and I hit some drivers bugs with VAO so I ended up turning them off by default. It was even less significant when using complex shaders, MSAA, etc, which bottleneck at the GPU leaving the CPU idly waiting anyway even on mobile. \$\endgroup\$ Commented Dec 30, 2014 at 23:11
  • 2
    \$\begingroup\$ Note that misaligning vertex data in a way that's not supported by the hardware will force the GPU drivers to reorder VBO data on each setup while drivers can reorder it once with VAO so long as nothing is changed so YMMV. Best to align & pad vertex data anyway. \$\endgroup\$ Commented Dec 30, 2014 at 23:25
  • 1
    \$\begingroup\$ Why must the VAO be unbinded before everything else? \$\endgroup\$ Commented Aug 19, 2015 at 16:58
  • 2
    \$\begingroup\$ "Optionally unbind to avoid accidental modification of the buffers and VAO." Err, no, you setup the correct state before doing it. You don't just allocate 3GB buffer then assume that you have enough memory allocated, you need 4MiB, you allocate 4MiB on the spot, and if not that, you have allocator that preallocates bigger chunks then gives them out/allocates more when you need them. This statement alone would warrant writing this answer off as completely wrong. Stop misleading people. I can't even find out what exactly I need/needn't to unbind because of trash information like this. \$\endgroup\$
    – Sahsahae
    Commented Dec 27, 2019 at 10:13
  • 1
    \$\begingroup\$ Furthermore: "You only bind the VBO/IBO again when you need to update them" is wrong. They are bound to tell the shader pipeline where to stream its data from, updates can be but aren't necessarily involved. "Optionally unbind everything to avoid accidental modification" is nonsense. Binding doesn't modify. Remains to say that OpenGL 4.5/.6 offer direct state access with pretty elegant possibilities for everything. The Red Book has details. \$\endgroup\$
    – user144188
    Commented Jan 30, 2021 at 14:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .