iPhone 3D Programming : Blending and Augmented Reality - Rendering Anti-Aliased Lines with Textures

2/27/2011 10:40:52 AM
Sometimes full-screen anti-aliasing is more than you really need and can cause too much of a performance hit. You may find that you need anti-aliasing only on your line primitives rather than the entire scene. Normally this would be achieved in OpenGL ES like so:

Alas, none of the iPhone models supports this at the time of this writing. However, the simulator does support line smoothing; watch out for inconsistencies like this!

A clever trick to work around this limitation is filling an alpha texture with a circle and then tessellating the lines into short triangle strips (Figure 1). Texture coordinates are chosen such that the circle is stretched in the right places. That has the added benefit of allowing round end-cap styles and wide lines.

Figure 1. Line anti-aliasing with textured triangle strips

Using a 16×16 circle for the texture works well for thick lines (see the left circle in Figure 1 and left panel in Figure 2). For thinner lines, I find that a highly blurred 16x16 texture produces good results (see the right circle in Figure 6-9 and right panel in Figure 2).

Figure 2. Antialiased lines

Let’s walk through the process of converting a line list into a textured triangle list. Each source vertex needs to be extruded into four new vertices. It helps to give each extrusion vector a name using cardinal directions, as shown in Figure 3.

Figure 3. Line extrusion

Before going over the extrusion algorithm, let’s set up an example scenario. Say we’re rendering an animated stick figure similar to Figure 6-10. Note that some vertices are shared by multiple lines, so it makes sense to use an index buffer. Suppose the application can render the stick figure using either line primitives or textured triangles. Let’s define a StickFigure structure that stores the vertex and index data for either the non-AA variant or the AA variant; see Example 1. The non-AA variant doesn’t need texture coordinates, but we’re including them for simplicity’s sake.

Example 1. Structures for the extrusion algorithm
struct Vertex {
vec3 Position;
vec2 TexCoord;

typedef std::vector<Vertex> VertexList;
typedef std::vector<GLushort> IndexList;

struct StickFigure {
IndexList Indices;
VertexList Vertices;

The function prototype for the extrusion method needs three arguments: the source StickFigure (lines), the destination StickFigure (triangles), and the desired line width. See Example 2 and refer back to Figure 6-11 to visualize the six extrusion vectors (N, S, NE, NW, SW, SE).

Example 2. Line extrusion algorithm
void ExtrudeLines(const StickFigure& lines, StickFigure& triangles, float width)
IndexList::iterator sourceIndex = lines.Indices.begin();
VertexList::iterator destVertex = triangles.Vertices.begin();
while (sourceIndex != lines.Indices.end()) {

vec3 a = lines.Vertices[lines.Indices[*sourceIndex++]].Position;
vec3 b = lines.Vertices[lines.Indices[*sourceIndex++]].Position;
vec3 e = (b - a).Normalized() * width;

vec3 N = vec3(-e.y, e.x, 0);
vec3 S = -N;
vec3 NE = N + e;
vec3 NW = N - e;
vec3 SW = -NE;
vec3 SE = -NW;

destVertex++->Position = a + SW;
destVertex++->Position = a + NW;
destVertex++->Position = a + S;
destVertex++->Position = a + N;
destVertex++->Position = b + S;
destVertex++->Position = b + N;
destVertex++->Position = b + SE;
destVertex++->Position = b + NE;

At this point, we’ve computed the positions of the extruded triangles, but we still haven’t provided texture coordinates for the triangles, nor the contents of the index buffer. Note that the animated figure can change its vertex positions at every frame, but the number of lines stays the same. This means we can generate the index list only once; there’s no need to recompute it at every frame. The same goes for the texture coordinates. Let’s declare a couple functions for these start-of-day tasks:

void GenerateTriangleIndices(size_t lineCount, IndexList& triangles);
void GenerateTriangleTexCoords(size_t lineCount, VertexList& triangles);

Flip back to Figure 1, and note the number of triangles and vertices. Every line primitive extrudes into six triangles composed from eight vertices. Since every triangle requires three indices, the number of indices in the new index buffer is lineCount*18. This is different from the number of vertices, which is only lineCount*8. See Example 3.

Example 3. Line extrusion initialization methods
void GenerateTriangleIndices(size_t lineCount, IndexList& triangles)
triangles.resize(lineCount * 18);
IndexList::iterator index = triangles.begin();
for (GLushort v = 0; index != triangles.end(); v += 8) {
*index++ = 0 + v; *index++ = 1 + v; *index++ = 2 + v;
*index++ = 2 + v; *index++ = 1 + v; *index++ = 3 + v;
*index++ = 2 + v; *index++ = 3 + v; *index++ = 4 + v;
*index++ = 4 + v; *index++ = 3 + v; *index++ = 5 + v;
*index++ = 4 + v; *index++ = 5 + v; *index++ = 6 + v;
*index++ = 6 + v; *index++ = 5 + v; *index++ = 7 + v;

void GenerateTriangleTexCoords(size_t lineCount, VertexList& triangles)
triangles.resize(lineCount * 8);
VertexList::iterator vertex = triangles.begin();
while (vertex != triangles.end()) {
vertex++->TexCoord = vec2(0, 0);
vertex++->TexCoord = vec2(0, 1);
vertex++->TexCoord = vec2(0.5, 0);
vertex++->TexCoord = vec2(0.5, 1);
vertex++->TexCoord = vec2(0.5, 0);
vertex++->TexCoord = vec2(0.5, 1);
vertex++->TexCoord = vec2(1, 0);
vertex++->TexCoord = vec2(1, 1);

PS4 game trailer XBox One game trailer
WiiU game trailer 3ds game trailer
Top 10 Video Game
-   Why We're Excited For the FFVII Remake
-   Mortal Kombat X | Predator Brutality
-   Mortal Kombat X | Predator Fatality
-   Poly Bridge [PC] Early Access Trailer
-   Silence: The Whispered World 2 [PS4/XOne/PC] Cinematic Trailer
-   Devilian [PC] Debut Trailer
-   BlazBlue Chrono Phantasma EXTEND | Launch Trailer
-   Allison Road | Prototype Gameplay
-   Clash of Clans | 'Dark Spell Factory' Update
-   Shoppe Keep [PC] Debut Trailer
-   Orcs Must Die! Unchained [PC] What's New in Endless Summer v2.3 Patch
-   Gunpowder [PC] Launch Trailer
-   Uncharted 4: A Thief's End | E3 2015 Extended Gameplay Trailer
-   V.Next [PC] Kickstarter Trailer
-   Renowned Explorers [PC] Launch Date Trailer
Game of War | Kate Upton Commercial