正六边形的距离场The SDF of a Regular Hexagon
因为iq大佬最新更新了cool S的距离场,而我一直对距离场感兴趣,可网上除了iq公布的segment line、圆形和方形以外2D和3D距离场其实都很少都有文章,为了跟上大佬的脚步,最近推算了一下iquilezles大佬的正六边形距离场。

因为我是看代码分析的,所以我只能把代码每一行都拆开来做解释
const vec3 k = vec3(-0.866025404,0.5,0.577350269);
首先这里的-0.866025404,0.5,0.577350269分别是Cos(150°),Sin(30°)和tan(30°)
p = abs(p);
这里把二维坐标系折叠因为六边形按照x和y轴切都是对称的所以我们的坐标系变成了这样

p -= 2.0*min(dot(k.xy,p),0.0)*k.xy;
k.xy是如图所示的蓝色的单位矢量,而min函数直角和锐角全部排除在外所以受到计算影响的只有从0°~60°的黄色区域

减去2.0乘以k.xy和phong模型的specular function的reflect方法相似主要是把黄色区域全部都沿着k.xy向上移动映射到60°~120°这个时候整个坐标系就压缩成了我画的的红色区域

p -= vec2(clamp(p.x, -k.z*r, k.z*r), r);
这里我们把p-vec2分开来看作p.x-clamp(p.x, -k.z*r, k.z*r)和p.y-r
p.y-r就是求出y的距离场
p.x-clamp(p.x, -k.z*r, k.z*r)中-k.z*r和k.z*r k.z之前写过了是tan(30°)
接下来是最难的一步这里把r想象成cos按照三角形函数tan=sin/cos这里就把cos相同的矢量也就是p.y相同的矢量的+-p.x限制在p.x-k.z*r, k.z*r这个sin(+-30°)*magnitude(长度)中间,也就是说当p.x-p.x等于0(在内部)时只判断你的p.y(青蓝色的线段),只有p.x大于小于+-k.z*r,p.x在外部时才会有作用会变得越来越圆(深红色线段)

return length(p)*sign(p.y);
最后返回距离这里的sign(p.y)是为了判断距离场外面还是内部(内部都是负数)
按照这个方法其实已经可以推算出很多2D距离场了因为正五边形和正多边形都类似,当然如果你对计算机图形学感兴趣对shadertoy感兴趣可以关注我不定期更新一些图形学知识。