解析GLSL基于距离场绘制多边形的函数原理
先看目标代码:
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);
问题拆解与解答
1. theta / rotate_angle 的意义
theta是当前点pos相对于原点的极角(从x轴正方向逆时针旋转的角度),rotate_angle = 2π/N是把整个圆周N等分后,每份的角度(也就是N边形相邻两个顶点与原点连线的夹角)。
这个除法的作用是把极角转换成“等分区间的相对位置”:比如N=4(正方形)时,rotate_angle=π/2,若theta=π/4,计算结果是0.5,说明这个角度在第0和第1个等分区间的中间;若theta=3π/4,结果是1.5,说明在第1和第2个区间中间。这个值的整数部分是当前角度所在的区间序号,小数部分是在区间内的占比。
2. 0.5的由来与floor(0.5 + 比值)的作用
我们的目标是找到离当前theta最近的那个N边形顶点的极角,本质是把theta归到最近的等分线角度上。
拿正方形举例,等分线角度是0、π/2、π、3π/2:
- 当
theta在(0, π/4)(区间前半段)时,theta/rotate_angle < 0.5,加0.5后小于1,floor取整结果为0,对应极角0; - 当
theta在(π/4, π/2)(区间后半段)时,theta/rotate_angle > 0.5,加0.5后大于1,floor取整结果为1,对应极角π/2;
这里的0.5就是区间中点的阈值,加0.5后再取整,相当于实现了“四舍五入”的效果,能把每个区间内的角度自动归到离它最近的等分线(顶点极角)上。如果不加0.5,直接取整会把整个区间的角度都归到左边界,无法实现“找最近顶点”的需求。
3. 为什么alpha等于这个表达式
floor(0.5 + theta / rotate_angle) * rotate_angle 计算出的就是离当前theta最近的N边形顶点的极角,用这个值减去theta,得到的就是当前点极角与最近顶点极角的差值——也就是你说的alpha,它是当前点到原点的连线,和最近的多边形“对称轴”(顶点与原点的连线)之间的夹角。
后续用cos(alpha) * length(pos)把当前点到原点的距离投影到这条对称轴上,对比投影长度和多边形外接圆半径的大小,就能判断点是否在多边形内部。
内容的提问来源于stack exchange,提问作者DrinkPractical9526

