【UE】SDF - 使用有向距离场(Signed Distance Fields)整各种活-3-距离场的平滑混合
之前的文章中介绍了距离场,在开始整活之前还需要了解如何混合距离场。这篇文章中介绍如何平滑的混合两个以上的距离场。没错,根本没有所谓之前的文章,这堆文章现在还没写,我假装写了因为介绍距离场的文章挺多的,所有还在考虑是否有必要浪费网络资源。
由于时间和精力的关系,这系列文章都没有一次写完,内容都会保持动态更新,会进行补充。
之前的文章中介绍了距离场,在开始整活之前还需要了解如何混合距离场。
这篇文章中介绍如何平滑的混合两个以上的距离场。

Min混合
通常最直接的SDF混合方式是使用min进行计算min(a,b)
可以看到交界处是锐利的
所谓min,它的运算过程是:
float min(float a, float b)
{
return (a < b) ? a : b;
}

结果如图:
使用两个距离场进行演示,使用step勾勒边缘查看边界:
可以看到距离场直接过渡非常锐利:
SMin混合
大名叫Smooth Minimum
使用SMin函数对距离场混合,使边界平滑。


Smin有多种算法可以选择,下面的算法名的颜色对应实例中的颜色:
混合效果:


算法
Smin当然不是自带的函数(比如min),而且有很多种计算方式。
方式对应的算法如下
函数下方为Custom写法,和对应的蓝图实现
只在个别函数贴出了Custom写法和蓝图写法
目前没时间给每条都做一遍,举一反三吧朋友们
我慢慢补吧
Exponential
float smin(float a, float b, float k)
{
k *= 1.0;
float r = exp2(-a / k) + exp2(-b / k);
return -k * log2(r);
}


Root
float smin(float a, float b, float k)
{
k *= 2.0;
float x = b - a;
return 0.5 * (a + b - sqrt(x * x + k * k));
}
Sigmoid
float smin(float a, float b, float k)
{
k *= log(2.0);
float x = b - a;
return a + x / (1.0 - exp2(x / k));
}
Quadratic Polynomial
float smin(float a, float b, float k)
{
k *= 4.0;
float h = max(k - abs(a - b), 0.0) / k;
return min(a, b) - h * h * k * (1.0 / 4.0);
}
Cubic Polynomial
float smin(float a, float b, float k)
{
k *= 6.0;
float h = max(k - abs(a - b), 0.0) / k;
return min(a, b) - h * h * h * k * (1.0 / 6.0);
}
Quartic Polynomial
float smin(float a, float b, float k)
{
k *= 16.0 / 3.0;
float h = max(k - abs(a - b), 0.0) / k;
return min(a, b) - h * h * h * (4.0 - h) * k * (1.0 / 16.0);
}
Circular
float smin(float a, float b, float k)
{
k *= 1.0 / (1.0 - sqrt(0.5));
float h = max(k - abs(a - b), 0.0) / k;
return min(a, b) - k * 0.5 * (1.0 + h - sqrt(1.0 - h * (h - 2.0)));
}


Circular Geometrical
float smin(float a, float b, float k)
{
k *= 1.0 / (1.0 - sqrt(0.5));
return max(k, min(a, b)) -
length(max(float2(k - a, k - b), 0.0));
}
K值
可以看到函数需要一个参数K,平滑最小值需要在 a 和 b 的值“接近”的区域内实现平滑的、非二元的过渡。其范围是0-1。
这个"接近"的定义就是K,是常规距离单位。意义是:公差 k 范围内,表面足够接近时,它们会相互混合,是kernel的缩写,后续会提到。
观察K的0-1变化:
进阶:算法
上面函数中的代码是对 GPU进行优化的,这掩盖了它们之间的相似性,但如果我们稍微重新整理一下代码,就会发现根式(root)、S型(Sigmoid)、二次(quadratic)、三次(cubic)、四次(quartic)和圆形(circular)变体非常相似,并且属于同一个家族。
下面的这些代码和上面的是等价的,是不考虑GPU优化的标准写法:
// root
float smin(float a, float b, float k)
{
k *= 2.0;
float x = (b - a) / k;
float g = 0.5 * (x + sqrt(x * x + 1.0));
return b - k * g;
}
// sigmoid
float smin(float a, float b, float k)
{
k *= log(2.0);
float x = (b - a) / k;
float g = x / (1.0 - exp2(-x));
return b - k * g;
}
// quadratic polynomial
float smin(float a, float b, float k)
{
k *= 4.0;
float x = (b - a) / k;
float g = (x > 1.0) ? x :
(x < -1.0) ? 0.0 :
(x * (2.0 + x) + 1.0) / 4.0;
return b - k * g;
}
// cubic polynomial
float smin(float a, float b, float k)
{
k *= 6.0;
float x = (b - a) / k;
float g = (x > 1.0) ? x :
(x < -1.0) ? 0.0 :
(1.0 + 3.0 * x * (x + 1.0) - abs(x * x * x)) / 6.0;
return b - k * g;
}
// quartic polynomial
float smin(float a, float b, float k)
{
k *= 16.0 / 3.0;
float x = (b - a) / k;
float g = (x > 1.0) ? x :
(x < -1.0) ? 0.0 :
(x + 1.0) * (x + 1.0) * (3.0 - x * (x - 2.0)) / 16.0;
return b - k * g;
}
// circular
float smin(float a, float b, float k)
{
k *= 1.0 / (1.0 - sqrt(0.5));
float x = (b - a) / k;
float g = (x > 1.0) ? x :
(x < -1.0) ? 0.0 :
1.0 + 0.5 * (x - sqrt(2.0 - x * x));
return b - k * g;
}
这个家族中的所有平滑最小值函数通过使用 min() 和核函数(kernel),都是关于 SDFs(符号距离函数) a 和 b 的直接差异的函数。
这就是为什么称其为“直接差异家族”(Direct Difference Family,简称 DD 家族)。
现在,这个家族中所有平滑最小值函数之间唯一不同的就是函数 g(x)。我称这个函数 g(x) 为平滑最小值的“核函数”(Kernel)。核函数在定义平滑最小值的许多特性方面起着重要作用。目前,这里是上述几个核函数的图形:

核函数 g(x) 的形状非常特殊。当 x 趋向于正无穷大时,也就是当 b 远大于 a 时,g(x) 趋向于恒等函数 x,此时平滑最小值返回 a。另一方面,当 x 趋向于负无穷大时,也就是当 a 远大于 b 时,g(x) 趋向于 0.0,此时平滑最小值趋向于 b。
本质上,核函数的行为类似于函数 max(x, 0),或者如果你熟悉机器学习的话,它类似于 ReLU,但以一种更平滑的方式。这正是平滑最小值中“平滑”特性的来源。实际上,如果我们令 g(x) = max(x, 0),一个完美的修正器,那么平滑最小值在数学上会退化为普通的最小值。
核函数在平滑最小值的归一化过程中扮演了非常重要的角色。请注意,在图表的右侧,我标出了核函数在原点处的值,也就是它与 y 轴交点的高度。这是因为当我们与两个 SDF(a 和 b)等距时,也就是当 x = (b-a)/k = 0(即 a = b)时,这个值就是我们从 b 中减去的值。这是我们需要用来对这个家族的所有平滑最小值进行归一化的值,因为它表示了源 SDFs 之间生成的混合区域中最厚的部分。
如果你想自己计算这些归一化值,请注意,在 Sigmoid 核函数的情况下,你会遇到 0 除以 0 的情况,因此你需要使用洛必达法则(L’Hopital’s Rule)来得到正确答案。
更多推荐



所有评论(0)