Vertex Buffer Objects in OpenGL ES#

Vertex Buffer Objects (VBOs) are the preferred way of storing vertex and index data. VBO storage is managed by the driver, so there is no need to copy an array from the client side at every draw call, and the driver is able to perform some transparent optimisations.

All the vertex attributes that are required for a mesh should be packed into the same VBO unless a mixture of static and dynamic attributes are being used. Do not create a VBO for every mesh, as it is a good idea to group meshes that are always rendered together to minimise buffer rebinding. This also has the benefit of improving batching.

The graphics chip tends to process multiple frames at a time, so the driver has to internally allocate multiple buffers for dynamic VBOs so that each frame has a unique dynamic buffer associated with it. Due to this driver behaviour, it is generally better for performance if dynamic vertex data (data that changes on a per-frame basis) is split from the static vertex data and placed into a separate VBO. This means only the dynamic VBOs need to be resubmitted per frame, rather than the entire vertex data set.

If there is a mesh where only some of the vertex data is dynamic, such as a skinned character in a game, then a VBO should be created that contains the static data. Use calls to glVertexAttribPointer to resubmit the dynamic vertex data.

A VBO that will never change should always set the STATIC_DRAW flag, while a VBO whose contents will change should never set it.

An alternative approach to dynamically updating vertex data involves creating a type of ring buffer. In this scenario, all the vertex data is stored in a single buffer, and the API function glMapBufferRange is used to map portions of the buffer for updating. This allows the application to update vertex data stored in one region of a vertex buffer while the graphics core is drawing from a separate region of the same vertex buffer.

Data should only be overwritten when it is no longer being used by the graphics core, meaning fences should be employed to determine when it is safe to update a region of buffer.