title: Fragment Shader: get distance from fragment to bezier curve
body: <p>Let's start with where I am;
  <img src="https://dl.dropbox.com/u/44766482/test2.png" alt="current state"></p>
  
  <p>I have a fragment shader that generates this texture through FBO. I have almost all primitives I want, except for bezier curves.</p>
  
  <p>My rather large fragment shader:</p>
  
  <pre><code>testfrag = """//fragment
  uniform float thickness; //sets beam thickness
  uniform float light; //sets beam intensity
  
  uniform vec4 lines[200]; //pairs of lines; x1, y1, x2, y2
  uniform vec3 circles[200]; //circles x,y,radius
  uniform vec4 ellipses[200]; //ellipses x,y,width, heightmultiplication
  uniform int ellipselength = 1; //amount of ellipses
  uniform int linelength = 2; //amount of linepairs
  uniform int circlelength = 1; //amount of circles
  
  
  uniform vec2 polygons[200]; //polygon data, points in x,y. (0,0) points used as end marker
  uniform int polylength; //amount of polygons
  
  
  int i; //for counter variable 1
  int i2; //for counter variable 2
  float mindistance = 1.0; //distance from fragment to next segment
  
  float P2L(in vec2 p, in vec2 lp1, in vec2 lp2) //distance point to line segment
  {
    float squared = pow(distance(lp1, lp2), 2); //squared line length
    float t = dot(p - lp1, lp2 - lp1) / squared; //relative position in parellel to line
    if (t &lt; 0.0) return distance(p, lp1); //before the line, get radius to point
    if (t &gt; 1.0) return distance(p, lp2); //after the line, get radius to point
    return distance(p, lp1 + t * (lp2 - lp1)); //otherwise, get distance line to point
  }
  float P2C(in vec2 p, in vec3 circle) //point to circle
  {
      return abs(distance(p, circle.xy)-circle.z); //euclidian distance - radius
  }
  float P2E(in vec2 p, in vec4 ellipse) //point to ellipse
  {
      return abs(sqrt(pow(p.x-ellipse.x,2) + pow((p.y-ellipse.y)/ellipse.w, 2)) -ellipse.z); // similar to circle, with factor on height
  }
  
  bool PinPoly(in vec2 p, in int start, in int len) //test if point in polygon
  {
    int i, j; 
    bool c = false;
    for (i = start, j = len-1+start; i &lt; len+start; j = i++) {
      if ( ((polygons[i].y&gt;p.y) != (polygons[j].y&gt;p.y)) &amp;&amp;
       (p.x &lt; (polygons[j].x-polygons[i].x) * (p.y-polygons[i].y) / (polygons[j].y-polygons[i].y) + polygons[i].x) )
         c = !c;
    }
    return c;
  } //balls if I know how this works
  
  
  
  void main()
  {   
  
      vec2 pos = gl_TexCoord[0].xy; // get position on fbo
      for (i = 0; i &lt; linelength; i++) //test lines
      {
          mindistance = min(mindistance, P2L(pos, lines[i].xy, lines[i].zw));
      }
      for (i = 0; i &lt; circlelength; i++) //test circles
      {
          mindistance = min(mindistance, P2C(pos, circles[i]));
      }
      for (i = 0; i &lt; ellipselength; i++) //test ellipses
      {
          mindistance = min(mindistance, P2E(pos, ellipses[i]));
      }
      i = 1;
      int first;
      while (i &lt; polylength) //test polygons
      {
          //first for line segments
          first = i-1;
          while (polygons[i] != (0.0, 0.0))
          {
              mindistance = min(mindistance, P2L(pos, polygons[i-1], polygons[i]));
              i++;
  
          }
  
          mindistance = min(mindistance, P2L(pos, polygons[i-1], polygons[first]));
          if (PinPoly(pos, first, i-first)) //then test if it is inside a polygon
          {
              mindistance = 0.0;
          }
          i += 2; //jump over the (0,0) vec2
  
      }
  
      gl_FragColor = light*(1.0/thickness)*(thickness-mindistance).xxxx; //set color of fragment
  }
  """
  </code></pre>
  
  <p>Which is called roughly like this in a pyglet environment:</p>
  
  <pre><code>def on_draw(self):
      if not self.inited:
          vert = shader.Shader(shader.texvertex)
          frag = shader.Shader(shader.testfrag)
          self.TexProgram = shader.Program([vert, frag])
          with self.TexProgram:
              self.TexProgram["lines[0]"] = (0.25, 0.5, 0.75, 0.5)
              self.TexProgram["lines[1]"] = (0.0, 0.0, 1.0, 1.0)
              self.TexProgram["circles[0]"] = (0.5, 0.5, 0.1)
              self.TexProgram["ellipses[0]"] = (0.75, 0.25, 0.1, 2.0) #x,y, width, multiplicator on height
              self.TexProgram["polygons[0]"] = (0.1, 0.9)
              self.TexProgram["polygons[1]"] = (0.2, 0.9)
              self.TexProgram["polygons[2]"] = (0.2, 1)
              self.TexProgram["polygons[3]"] = (0.1, 1)
              self.TexProgram["polygons[4]"] = (0,0)
              self.TexProgram["polygons[5]"] = (0.1, 0.1)
              self.TexProgram["polygons[6]"] = (0.2, 0.1)
              self.TexProgram["polygons[7]"] = (0.2, 0.2)
              self.TexProgram["polygons[8]"] = (0.1, 0.2)
              self.TexProgram["polygons[9]"] = (0,0)
              self.TexProgram["polylength"] = 8
              self.TexProgram["light"] = 1.05
              self.TexProgram["thickness"] = 0.02
          self.inited = True
  
      self.clear()
      else:
          with self.TexProgram:
              self.fbo.bind_texture()
              self.fbo.clear()
              t = (0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0)
              x1 = 0
              x2 = w
              y1 = 0
              y2 = h
  
              glColor4d(1,1,1,1)
              glEnable (GL_TEXTURE_2D)
              glBegin(GL_QUADS)
              glTexCoord2d(t[0], t[1]); glVertex2d(x1, y1)
              glTexCoord2d(t[2], t[3]); glVertex2d(x2, y1)
              glTexCoord2d(t[4], t[5]); glVertex2d(x2, y2)
              glTexCoord2d(t[6], t[7]); glVertex2d(x1, y2)
              glEnd()
  </code></pre>
  
  <p>The bezier curves often have more than 3 points, everything is in 2D space.
  The way I see it, there are 2 ways to solve this.</p>
  
  <p>1:</p>
  
  <pre><code>Generate points on curve.
  get closest curve point.
  generate points around curve point.
  get closest point of those.
  rince and repeat last steps until satisfactory precision is reached.
  </code></pre>
  
  <p>2:
  Come up with a formula/algorithm to get the distance analytically. I attempted this and found no solution for any number of bezier curve points, only for a constant amount.</p>
  
  <p>I would prefer a solution to the second method.
  I can come up with a solution for the first method on my own, but in case someone knows of any resources to look it up so I don't waste time could be helpful anyway.</p>