Search code examples
glslpolygon

Understanding GLSL function to draw polygon using distance field


Could someone help me understand the following function that draws a polygon of N sides (i.e. 3 being a triangle and 4 being a square):

float theta = atan(pos.x, pos.y);
float rotate_angle = 2 * PI / N;
float d = cos(floor(0.5 + theta / rotate_angle) * rotate_angle - theta) * length(pos);

What I understand from this illustration is that:

  1. we're interested in finding the angle indicated by the red curve (call it alpha)
  2. cos(alpha) * length will project the green line onto the blue line
  3. by comparing the size of said projection with that of the blue line (radius of circle), we know whether a test point is inside or outside of the polygon we're trying to draw

Question

Why does alpha equal floor(0.5 + theta / rotate_angle) * rotate_angle - theta? Where does 0.5 come from? What's the significance of theta / rotate_angle?

What I have read:

[1] https://codepen.io/nik-lever/full/ZPKmmx

[2] https://thndl.com/square-shaped-shaders.html

[3] https://thebookofshaders.com/07


Solution

  • Simply, floor(0.5 + x) = round(x). However, because round(x) may not be available in some environments (e.g. in GLES2), floor(0.5 + x) is to be used instead.

    Then, since n = round(theta / rotate_angle) gives edge section index which contains pos (e.g. n =-1, 0 or 1 for a triangle) , n * rotate_angle is the angle of edge center point(=blue line) which is nearest to the theta.

    Therefore, alpha = n * rotate_angle - theta is certainly relative angle from pos to the nearest center, where -rotate_angle/2 < alpha <= rotate_angle/2.

    Checking pos's projection length to the center point direction, it's possible to tell inside or outside. To detect discrete direction of polygon edges('s orthogonal vectors) seamlessly, round() function is used.