I spent some time integrating the triangulation algorithm into the renderer, finally making some use of it, to render the planet as a solid mass instead of line tracing its surface.
The planet
First thing I did was to swap the planet surface I had been using up to now, modeled after the first planet of the original game, for something more interesting. The first planet has a pretty boring topology, and doesn’t really stress the triangulation algorithm. So I reproduced the second planet from the original game, which I’ll refer to as ‘planet 1’ from now on (in typical CS nerd fashion, I start counting from 0 ;-). This is what planet 1 looks like in the original game:
Rendering planet 1
The polygon triangulation algorithm returns a set of vertex indices defined
on the vertices of the input polygon, which are perfectly suited for rendering
using vertex-, and index buffer objects using glDrawElements
. None
of this is rocket science, so I’ll keep it short.
The input polygon is created by connecting the left and right endpoints of
the planet surface (a line) using 3 new edges (left, bottom, right) to form
a counter-clockwise polygon. The vertex coordinates are stored in a vertex
buffer object (VBO), and the triangle indices in an index buffer object (IBO).
Rendering the VBO and IBO is just a matter of binding the buffers, enabling
the VBO as a vertex attribute array for the vertex position attribute using
glVertexAttribPointer
, then calling glDrawElements
to render the whole thing
using a single draw call.
For additional eye-candy, I quickly hacked together a texture to apply to
the surface polygon, by cropping a 32x32 pixel region from the planet image
above. Using the GLKit GLTextureLoader
class, loading and binding the texture
from a PNG file was a breeze, and applying the texture to the surface polygon
was just a matter of using the vertex x and y coordinates as texture coordinates
and enabling repeating the texture in both directions. The vertex and fragment
shaders are almost the equivalent of a ‘Hello World’ program for shaders, but
just for laughs I’ll quote them here:
Vertex shader
attribute vec4 a_position;
attribute vec2 a_texcoords;
uniform mat4 u_projection;
uniform mat4 u_model_view;
varying vec2 v_texcoords;
void main()
{
gl_Position = u_projection * u_model_view * a_position;
v_texcoords = vec2(a_position.x, a_position.y);
}
Fragment shader
varying lowp vec2 v_texcoords;
uniform lowp vec4 u_color;
uniform sampler2D u_texture;
void main()
{
lowp vec4 texel = texture2D(u_texture, v_texcoords);
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0) * texel;
}
Video
Next steps
I want to write some simple sprite-like interface that can be used to render
K14Entity
instances as textured quads instead of single-colored blocks. Initially,
I’ll stick with single, static textures, but eventually I want to add animation
capabilities using sprite frames, and textures that can be generated at run-time
using paths.
Development scoreboard
It only took me about 3 hours to hook the triangulation algorithm into the renderer, and modify it to render the planet surface using textured triangles. The total development time is now at about 91 hours. SLOC count is now 1267.