OpenGL ES 2.0 : Seeking VBO Performance/Optimisation Tips For Many Moving Vertices

杀马特。学长 韩版系。学妹 提交于 2019-12-03 07:24:06

I don't have any ES experience, but I think many things still apply

  1. 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.

  2. 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.

  3. 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).

  4. place-holder

  5. 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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!