2016-02-10 52 views
3

我一直在寻找,并试图了解下面的代码位GLSL立方体签名距离字段的实现说明?

float sdBox(vec3 p, vec3 b) 
{ 
    vec3 d = abs(p) - b; 
    return min(max(d.x,max(d.y,d.z)),0.0) + 
     length(max(d,0.0)); 
} 

我明白length(d)处理SDF情况下点是关闭的“角落”(即中d所有部件正面),并且max(d.x, d.y, d.z)在所有其他情况下给我们适当的距离。我不明白的是,如果不使用if语句来检查d组件的符号,这两个组合是如何组合的。

当所有d组件都是积极的,返回表达式可以减少到length(d)的,因为这样min/max将评估 - 当所有d组件是否定的,我们得到max(d.x, d.y, d.z)。但我该如何理解中间情况呢? d的组件有混合迹象的那些?

我一直在试图将其绘制出来无济于事。如果有人能够用几何/数学术语向我解释这一点,我会非常感激。谢谢。

回答

0

我想通了一段时间以前,广泛在博客中写到这里一下: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)); 
} 

有你有它。