Your graphics puzzle for the day

Just the other day, I wrote a trivial geometry shader to tesselate cubic 2D Bezier curves on the fly, so we get nice curved edges for free. Remembering that the geometry shader sits between the vertex shader and the fragment shader, and its purpose is to create new geometry on the fly, the code looked like this (my apologies to the direct threedeese readers – I only speak OpenGL):

vec4 pp[4] = ... // control points
for (int i=0; i<=10; ++i) {
  float u = i / 10.0f // interpolation control
  float omu = 1.0f-u;
  vec4 spline_p = pp[0] * omu * omu * omu +
                  pp[1] * omu * omu   * u +
                  pp[2] * omu   * u   * u +
                  pp[3] * u   * u   * u;
  EmitVertex();
}

This worked nicely, generated really good looking splines, and was fast. Then I wanted to backport this to the CPU in case the user doesn’t have geometry shaders. We could be using OpenGL evaluators, but it seemed simple enough, right? Like this:

float pp[4][2] = // control points
for (int i=0; i<=10; ++i) {
  float u = i / 10.0f // interpolation control
  float omu = 1.0f-u;
  float spline_p[2] = {
    pp[0][0] * omu * omu * omu +
    pp[1][0] * omu * omu * u +
    pp[2][0] * omu * u   * u +
    pp[3][0] * u   * u   * u,
    pp[0][1] * omu * omu * omu +
    pp[1][1] * omu * omu * u +
    pp[2][1] * omu * u   * u +
    pp[3][1] * u   * u   * u}
  glVertex2fv(spline_p);
}

No matter what I tried, this wouldn’t work – the lines come out garbled. The endpoints are in the right places, but the interior vertices tend to bend towards a common point. The bug is fairly obvious: the second and third cubic Bernstein polynomials are wrong (I was missing a factor of 3 there).

Now for the puzzle: why did the lines look right on the geometry shader?

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s