我想通了一段时间以前,广泛在博客中写到这里一下:http://fabricecastel.github.io/blog/2016-02-11/main.html
下面是摘录(见全文后更全面的解释):
考虑四点,A,B,C和D.让我们粗略地减少距离函数来尝试去除最小/最大函数以了解它们的效果(因为这是令人费解的关于这个函数的)。下面的符号有点草率,我用方括号来表示2D矢量。
// 2D version of the function
d(p) = min(max(p.x, p.y), 0)
+ length(max(p, 0))
---
d(A) = min(max(-1, -1), 0)
+ length(max([-1, -1], 0))
d(A) = -1 + length[0, 0]
---
d(B) = min(max(1, 1), 0)
+ length(max([1, 1], 0))
d(B) = 0 + length[1, 1]
好的,到目前为止没有什么特别的。当A位于正方形内部时,我们基本上得到了基于平面/线的第一个距离函数,当B位于第一个距离函数不准确的区域时,它被归零并得到第二个距离函数(长度)。诀窍在于C和D的另外两种情况。让我们来解决它们。
d(C) = min(max(-1, 1), 0)
+ length(max([-1, 1], 0))
d(C) = 0 + length[0, 1]
---
d(D) = min(max(1, -1), 0)
+ length(max([-1, 1], 0))
d(D) = 0 + length[1, 0]
如果你回头看上面的图表,你会注意到C'和D'。这些点分别具有坐标[0,1]和[1,0]。这种方法使用两个距离场在轴上相交的事实 - D和D'与正方形距离相同。
如果我们将矢量的所有负向分量零点并取其长度,我们将得到点与正方形之间的正确距离(仅适用于正方形以外的点)。这是max(d,0.0)所做的;一个组件式的最大操作。只要向量具有至少一个正分量,min(max(d.x,d.y),0.0)将解析为0,只留下等式的第二部分。如果点在方格内,我们想返回方程的第一部分(因为它表示我们的第一个距离函数)。如果载体的所有成分都是阴性,很容易看到我们的状况会得到满足。
这种理解应该在您将头围绕它时无缝地变回到3D。你可能会也可能不需要亲手绘制几张图来真正“获取”它 - 我知道我做过了,如果你对我的解释不满意,会鼓励你这样做。
这个工作落实到我们自己的代码,我们得到这样的:
float distanceToNearestSurface(vec3 p){
float s = 1.0;
vec3 d = abs(p) - vec3(s);
return min(max(d.x, max(d.y,d.z)), 0.0)
+ length(max(d,0.0));
}
有你有它。