I have read an article about rendering quadratic splines on a GPU with a shader.

The algorithm is explained like this:

  • For each quadratic Bézier curve we use Bézier control points of the curve to create triangles. Triangles we get contain curves that are either convex or concave.

  • Then we need to assign [u v] coordinates to the vertices of the triangles (article says that we assign values [0 0], [½ 0], and [1 1]; I'm not sure why these values are used).

  • Then it say that instead of using [u v] coordinate to look up a color value as in texture mapping, we use the [u v] coordinate to evaluate a procedural texture. The pixel shader computes the expression u^2 - v using the sign of the result to determine pixel inclusion. For convex curves, a positive result means the pixel is outside the curve; otherwise it is inside. For concave curves, this test is reversed.

At the end of the article an example implementation of that algorithm is provided (reproduced below). It says it is a "quadratic curve pixel shader" so as I understand it, it should be able to render both convex and concave curves, but I am only able to get it to render convex curves.

Is it an incomplete example? If not, how / where it is specified if the curve is convex or concave?

float4 QuadraticPS(float2 p : TEXCOORD0, float4 color : COLOR0) : COLOR  
       // Gradients  
       float2 px = ddx(p);  
       float2 py = ddy(p);  
       // Chain rule  
       float fx = (2*p.x)*px.x - px.y;  
       float fy = (2*p.x)*py.x - py.y;  
       // Signed distance  
       float sd = (p.x*p.x - p.y)/sqrt(fx*fx + fy*fy);  
       // Linear alpha  
       float alpha = 0.5 - sd;  
       if (alpha > 1)       // Inside  
         color.a = 1;  
       else if (alpha < 0)  // Outside  
         // Near boundary  
         color.a = alpha;  
       return color;  

PS: Gradients and Chain rule sections of the shader are about anti-aliasing I think.

  • \$\begingroup\$ Code is direct copy of Quadratic Curve Pixel Shader example provided in the article. I have implemented it in my test program and it is only rendering convex curves. I am unable to make it render concave curves without modifying the shader (passing in another value for specifying the type and multiplying "sd" with -1 when curve is concave). Am I missing something or is this shader as is provided in this example only able to render convex curves? \$\endgroup\$ – zigzag Jan 17 '14 at 14:22
  • \$\begingroup\$ ...because for concave curve formula should be changed from p.x*p.x - p.y to p.y - p.x*p.x. I am passing in [0, 0] [1/2, 0] [1, 1] as [u, v] texture coordinates for vertices of my test triangle and it seems to me mathematically impossible to pass in uv coordinates that would cause concave result. Unless I am wrong in some way. \$\endgroup\$ – zigzag Jan 17 '14 at 14:44
  • \$\begingroup\$ Asking for help understanding some external resource isn't a question that's particularly well-suited to the site. If you were to ask a question such as "how, in general, can you determine this property of a curve" or reproduce a sufficient enough description of the resource that your question can be understood without following the link and reading the article, that would be better. \$\endgroup\$ – user1430 Jan 19 '14 at 1:35
  • \$\begingroup\$ I have reworded the question. I hope its clearer now. \$\endgroup\$ – zigzag Jan 19 '14 at 9:50
  • 1
    \$\begingroup\$ In case it's useful, here's a working version in GLSL, but all in a fragment shader. shadertoy.com/view/4tj3Dy This also shows a different way to render 2d quadratic bezier curves: shadertoy.com/view/MtS3Dy And lastly, rendering 1d (explicit) Bezier curves is quite a bit easier than 2d if you are interested in seeing that a 1d cubic bezier curve rendered: shadertoy.com/view/Xd2Xz1 \$\endgroup\$ – Alan Wolfe May 29 '15 at 15:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.