Android OpenGL ES glDrawArrays or glDrawElements?

For both, you pass OpenGL some buffers containing vertex data.

glDrawArrays is basically "draw this contiguous range of vertices, using the data I gave you earlier". Good:

  • You don't need to build an index buffer

Bad:

  • If you organise your data into GL_TRIANGLES, you will have duplicate vertex data for adjacent triangles. This is obviously wasteful.
  • If you use GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN to try and avoid duplicating data: it isn't terribly effective and you'd have to make a rendering call for each strip and fan. OpenGL calls are expensive and should be avoided where possible

With glDrawElements, you pass in buffer containing the indices of the vertices you want to draw.

Good

  • No duplicate vertex data - you just index the same data for different triangles
  • You can just use GL_TRIANGLES and rely on the vertex cache to avoid processing the same data twice - no need to re-organise your geometry data or split rendering over multiple calls

Bad

  • Memory overhead of index buffer

My recommendation is to use glDrawElements


The performance implications are probably similar on the iphone, the OpenGL ES Programming Guide for iOS recommends using triangle strips and joining multiple strips through degenerate triangles.

The link has a nice illustration of the concept. This way you could reuse some vertices and still do all the drawing in one step.

For best performance, your models should be submitted as a single unindexed triangle strip using glDrawArrays with as few duplicated vertices as possible. If your models require many vertices to be duplicated (because many vertices are shared by triangles that do not appear sequentially in the triangle strip or because your application merged many smaller triangle strips), you may obtain better performance using a separate index buffer and calling glDrawElements instead. There is a trade off: an unindexed triangle strip must periodically duplicate entire vertices, while an indexed triangle list requires additional memory for the indices and adds overhead to look up vertices. For best results, test your models using both indexed and unindexed triangle strips, and use the one that performs the fastest.

Where possible, sort vertex and index data so that that triangles that share common vertices are drawn reasonably close to each other in the triangle strip. Graphics hardware often caches recent vertex calculations, so locality of reference may allow the hardware to avoid calculating a vertex multiple times.

The downside is that you probably need a preprocessing step that sorts your mesh in order to obtain long enough strips. I could not come up with a nice algorithm for this yet, so I can not give any performance or space numbers compared to GL_TRIANGLES. Of course this is also highly dependent on the meshes you want to draw.