Instancing and skinning are like peas and carrots. But remember, skinning isn’t the only way to deform a mesh on the GPU. In some situations, (for example, rendering aquatic life), a bone system can be overkill. If you’ve got a predefined curve in 3-space, it’s easy to write a vertex shader that performs path-based deformation.

Path-based deformation is obviously more limited than true skinning, but gives you the same performance benefits (namely, your mesh lives in an immutable VBO in graphics memory), and it is simpler to set up; no fuss over bone matrices.

Ideally your curve has two sets of data points: a set of node centers and a set of orientation vectors. Your first thought might be to store them in an array of shader uniforms, but don’t forget that modern vertex shaders can make texture lookups. It just so happens that these two sets of data can be nicely represented by a pair of rows in an RGB floating-point texture, like so:

Here’s the beauty part: by creating your texture with a GL_LINEAR filter, you’ll be able to leverage dedicated interpolation hardware to obtain points (and orientation vectors) that live between the node centers. (Component-wise lerping of orientation vectors isn’t quite mathematically kosher, but who’s watching?)

But wait, there’s more! Even the wrap modes of your texture will come in handy. If your 3-space curve is a closed loop, you can use GL_REPEAT for your S coordinate, and voilà — your shader need not worry its little head about cylindrical wrapping!

One gotcha with paths is that you’ll want to enforce an even spacing between nodes; this helps keep your shader simple. If your shader assumes a uniform distribution of path nodes, your models can become alarmingly foreshortened. For example, here’s a dolphin that’s tied to an elliptical path, before and after node re-distribution:

Now, without further ado, here’s my vertex shader. Note the complete lack of trig functions; I can’t tell you how many times I’ve seen graphics code that makes costly sine and cosine calls when simple linear algebra will suffice. I’m using old-school GLSL (e.g., attribute instead of in) to make my demo more amenable to Mac OS X.

The shader assumes that the undeformed mesh sits at the origin, with its spine aligned to the X axis. The way it works is this: first, compute the three basis vectors for a new coordinate system defined by the path segment. Next, place the basis vectors into a 3×3 matrix. Finally, apply the 3×3 matrix to the spoke vector, which goes from the mesh’s spine out to the current mesh vertex. Easy!

By the way, don’t feel ashamed if you’ve never made an instanced draw call with OpenGL before. It’s a relatively new feature that was added to the core in OpenGL 3.1. Before that, it was known as GL_ARB_draw_instanced. At the time of this writing, it’s still not supported on Mac OS X. Here’s how you do it with an indexed array: