This is the second of a two-part article on tessellation shaders with OpenGL 4.0+. This entry walks through simple bezier patch subdivision; the previous entry gave an overview of tessellation and triangle subdivision. This article is going to be short and sweet.

Quad Subdivision

Whenever implementing a tessellation scheme, I find it best to initially get things going without any smoothing. In other words, simply divide up the patch without introducing any curvature. Here’s how our demo renders Catmull’s Gumbo model using the subdivided-but-not-smoothed approach:

To generate a simple subdivision image like this, the tessellation evaluation shader needs to consider only the 4 corners of the patch. Since we’re using 16 control points per patch, the corners are at positions 0, 3, 12, and 15. All we have to do is lerp between those four verts, and here’s the tessellation evaluation shader for doing so:

The above shader pretty much does exactly what the Python script in my other blog entry does. Note that I also write out a vec4 of edge distances to the tePatchDistance output variable; these are used for the wireframe technique, which I’ll cover shortly.

Of course, this isn’t very efficient. Some of the calculations are being performed at every vertex, but really they only need to performed once per patch. Namely, computation of the coefficient matrices (cx, cy, and cz) should be hoisted up into the tessellation control shader. Then, tcPosition can become a representation of those matrices, rather than being coordinates for the raw control points. Alas, I ran into driver / compiler issues when I made this optimization. OpenGL 4.0 is still a young technology, and the drivers need some time to mature. I’ll dig deeper when I have time, and file bug reports against the hardware vendor that I’m using.

Black and White Lines

You may have noticed that I improved on the wireframe technique presented in my previous blog entry; I now render the triangle edges in white, and the patch edges in black. The geometry shader is exactly the same as what I presented earlier:

The fragment shader is almost the same, except that I’m taking the min of four distances for the patch edges. I’m also drawing triangle edges in white, and I snuck in a specular component to the lighting computation: