In my ongoing attempt to convert to OpenGL ES 2.0 from ES 1.x I\'m currently converting some code to use Vertex Buffer Objects (\'VBOs\') rather than the existing unbuffered glD
I don't have any ES experience, but I think many things still apply
Partly, it doesn't force you to use one VBO per-body, but you have to do one glDrawArrays
per-body. These might still source their data from the same buffer, but it's still not advisable. Instead I would move away from complex primitives like triangle fans or strips and use indexed triangle lists, this way everything can be drawn in a single call. I doubt that ES supports the primitve_restart extension. With this you could specify a special vertex index that restarts the primitve.
If you got many other static attributes, it would be a good idea to seperate the vertex positions into their own buffer (that of course has GL_DYNAMIC_DRAW
or even GL_STREAM_DRAW
usage). But if you only got an additional 4ub color or something the like, then the extra copying cost might not be that bad and you might better profit from interleaving, needs to be tested.
If you update them all every frame, then a complete glBufferData
might be better than a glBufferSubData
. Or you can also call glBufferData(..., NULL)
and then glMapBuffer(..., GL_WRITE_ONLY)
if you don't want to hold a CPU array for your data. This tells the driver that you don't care for the previous data anymore. This way the driver can allocate a completely new buffer for you, while the previous data is still being used for rendering. So you can uplaod the new data while the old is still in use (The old buffer is freed by the driver when not used anymore).
place-holder
For colors GL_UNSIGNED_BYTE
might be even better, as these usually don't need that high a precision. This might also play well with alignment optimizations when you e.g. have 3 float coordinates and 4 byte color channels, which makes a vertex of 16 byte, which is very alignment friendly. In this case it might be advisable to keep vertices and colors in the same buffer.
EDIT: To clarify on point 3 a bit: If you have your data in a CPU array anyway, then you can just call glBufferData
with your data. If you want the driver to allocate that storage for you, you can use glMapBuffer
, which gives you a pointer to the buffer memory mapped into CPU address space (and of course you GL_WRITE_ONLY
as you don't care for the previous data). But in this case glBufferData
with a null pointer will allocate completely new storage for the buffer (without copying any data), which tells the driver, that we don't care for the previous contents (even they might currently still be used for rendering). The driver can optimize this case and allocate new storage under the hood, but still not free the previous storage, which is then freed when the previous data is finally not used anymore for rendering. But keep in mind that you don't create another buffer, it just goes on under the hood of the driver. So when you want to update the whole buffer, you can either do
updateData(dataArray);
glBufferData(GL_ARRAY_BUFFER, size, dataArray, usage);
if you got the data in your own CPU array anyway, or
glBufferData(GL_ARRAY_BUFFER, size, NULL, usage);
dataArray = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
updateData(dataArray);
glUnmapBuffer(GL_ARRAY_BUFFER);
If you don't need a CPU copy of your and want the driver to take care of. But if update the data step-wise during the whole application, then the first solution might be better, as you cannot use a buffer for rendering as long as its mapped, of course, and you should only map a buffer for a short time.