Experiences with OpenGL ES 2.0: Part I
During the development of Sprinkfield I hardly used OpenGL since Cocos2D matched our needs perfectly. However, our new game under development calls for more than “putting together” a few sprites so I had to familiarize myself with the tips & tricks of Open GL to a greater extent. In terms of syntax, there was nothing extra in it, but learning the pipeline programming, understanding the relationship between matrices, vertices, textures, shaders and buffer objects took more than a couple of hours, rather a couple of weeks. I daresay that many things have become clear for me on the other hand, it would be rather pompous to think of myself as an OpenGL guru.
It follows that I constantly run into problems that must have been discussed already somewhere in the lengthy OpenGL documentation or have already been solved by others.
Triangles and textures
In our new game, a very long landscape strip with repeating textures has to be displayed. One solution for this in OpenGL (now I omit the details and just focus on the problem) is to cover a strip of triangles (GL_TRIANGLE_STRIP) with a repeated picture (by setting the value of GL_TEXTURE_WRAP_S and/or GL_TEXTURE_WRAP_T to GL_REPEAT).
With these setting, OpenGL draws the triangles in this order: (1, 2, 3), (2, 3, 4), (3, 4, 5)…
The method worked fine in the iOS Simulator. And because that was only a simulator, it implemented OpenGL purely through software code, leaving out the graphics card. However, when I tested it on an actual device, I found that the texture strip started to fall apart after repetition #127.
I did not test that what if increased the size of the picture on which the texture is based because it would only postpone the texture disintegration problem to a later point. I surfed the net and found the most useful help here: http://stackoverflow.com/q/8787483/89364
In short, the rounding errors of the GPU will become visible in the app above a certain graphics size.
The texture is placed on more shorter triangle strips: on the picture above section 1-14 is divided into 2 shorter sections, 1-8 and 7-14, each made up of 6 triangles. The size of the texture tile exactly matches the size of these shorter sections, and each section uses the full texture tile. The advantage of this method is that we can display the same picture at the cost of a relatively small redundancy (the vertex coordinates of 7 and 8 must be used twice). In effect, there is still only one triangle strip drawn.
In this case, the process of drawing goes as follows: …(6, 7, 8), (7, 8, 9), (8, 9, 10), (9, 10, 11)… Now, the question is: what will happen to the two middle “triangles”? These are degenerate triangles, existing only in the software and the hardware smartly neglects them.
The benefit of this solution (besides the fact that the long picture will not fall apart) is that it required minimal modifications in the program code. That is we had to insert two additional vertices after every 16th vertex and then, during the drawing phase, we had to pass these two extra vertices to the OpenGL. The number of triangles increased by roughly 10%, but because we are talking about a total of few hundred triangles only, it will not impose a significant extra load on the graphics card.