Jul 062013

Recently, I've been bitten by OpenGL ES missing VAO support. For a few days now, I'm playing with another peculiarity:

glDrawElements index type support is limited to be GL_UNSIGNED_SHORT at most. What is the problem here? Let's assume, you have a large vertex buffer (turns out, yet moderate-sized ones). In this case, the elements in your index buffer are not longer able to discriminate between all these vertices. To be clear, your index buffer can still be large – but every single element value has to be smaller than 65536.

For some problems, a large vertex buffer can still be useful. As long, as you can process vertices in a more or less 'use and forget' manner, glVertexPointer can be used to slide along the vertex buffer and your indices – being only an offset counter to  the element defined by glVertexPointer's last argument – can remain small enough.

Unfortunately, this is not true for most real-world cases. In general, primitives have not this nice kind of locality for vertices in a linear buffer. Consider a mesh: 

meshOne naïve approach in drawing a function plot on top of this mesh would be to chain the column vectors of vertices and setting up an index buffer (including degenerate triangles, in order to connect vector ends) and draw the whole thing as a triangle strip.

This won't work of course, if for example n=70000. Even the first triangle requires two vertices from different columns. The 'distance' (inside the vertex buffer) of these vertices would be larger than 65535, but the pointer at the vertex buffers origin has still to maintain access to the element in (0,0). So, no surfing on a single vertex buffer.

At least not in a trivial way. Looking for rearrangements of the vertices, you will become quickly aware of a special kind of debt. Some of the vertices have to be duplicated inside the vertex buffer. Otherwise, their original indices would hinder the vertex pointers movement. The amount of such vertices seems to be proportional to 2n (simplifying for the moment the problem to m=n). At this moment, I'm not aware of any optimal algorithm in the sense of minimizing duplications. There are other implications to consider for the index buffer and also for the structure of the users vertex input data (at least for dynamic scenes). For now, I'm using multiple buffers in a simple tiling scheme (256×256) for larger meshes with the single exception, that the complete mesh has no more than 65536 vertexes.

Good news is, index buffers with unsigned int elements and even VAO's made it into the OpenGL ES 3 standard. And of course, there is always glDrawArrays.

Update (2013/07/25): Android 4.3 added OpenGL ES 3.0 support.