11
\$\begingroup\$

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

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

Draw
-------
 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

Thanks

\$\endgroup\$
11
\$\begingroup\$

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.

\$\endgroup\$
  • 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\$ – Stephane Hockenhull Dec 30 '14 at 23:11
  • 1
    \$\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\$ – Stephane Hockenhull Dec 30 '14 at 23:25
  • \$\begingroup\$ Why must the VAO be unbinded before everything else? \$\endgroup\$ – Daniel Safari Aug 19 '15 at 16:58
  • \$\begingroup\$ @DanielSafari, you mean after the setup? If you'd unbind a buffer first (binding buffer 0/null), it would clear that binding point in the current VAO. That's why the null VAO should be set first. \$\endgroup\$ – glampert Aug 19 '15 at 17:25
  • \$\begingroup\$ @glampert - no, that's not how bindings work; the buffer binding is used when glVertexAttribPointer is called, and not otherwise (exception: GL_ELEMENT_ARRAY_BUFFER). Changing the buffer binding after your glVertexAttribPointer call has no effect. \$\endgroup\$ – Maximus Minimus Jun 27 '17 at 14:00

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.