多个SDF模型并集后的平滑操作

Number of views 133

我们在RayMarching 不同SDF的混合中介绍了不同SDF的常见4种混合的方案。但是在这些混合方案实现过程会发现,不管是并集交集还是差集所呈现的混合结果都会很生硬。我们如何实现平滑的混合过程是本文讨论的要点。

假设我们定义了如下几个函数:

$$
L_1=x^{1/2}
$$

image1740749995548.png

$$
L_2=(x-2)^2
$$

image1740750369470.png根据RayMarching 不同SDF的混合并集操作中介绍,两个SDF可以通过min进行,所以我们新增:

$$
L_3=min(L_1, L_2)
$$

image1740750513844.png可以看到SDF已经合并。但是两条线的拐角处非常生硬。我们如何让其更加平滑,在继续介绍之前我们可以新增一个工具函数,用于在L1与L2间进行插值操作。那么我们需要先完成一个如下的插值函数,当k为0时值为L1,当k为1时值为L2:

$$
L_4=kL_2+(1-k)L_1 {0<=k<=1}
$$

image1740752463847.png

如果我们想让线性插值函数做到与min函数一样的效果(即实现并集的效果),那么我们应该让k在第一个拐点之前等于0,在第一个拐点与第二个之间等于1,第二个拐点之后继续等于0,那么我们就不能简单使用滑块来表示k值了。而应该实现一个映射函数。我们先找出L1与L2函数的两者间共用的规律,通过:

$$
L_5=L_2-L_1
$$

可以看到L2与L1的交点在相减之后y为0:

image1740753290407.png

这很容易理解,也确实没有问题。但是我们需要让它能够平滑处理,此时交点就不能为0,而应该取k在0~1之间的值,如0.5,那也很简单,让L5加上0.5即可:

image1740753601256.png

我们限制下L5,让其超出1的部分限制为1:

image1740753805997.png

继续限制小于0的部分取0:

image1740753893492.pngOK,我们已经得出了在L1的部分,值为1,在L2的部分,值为0,并在拐角处有插值渐变的过程。实际上如果我们把 L4=k·L2+(1-k)·L1变为 L4=k·L1+(1-k)·L2这样做实际上已经可以了。但是我们采用了 L4=k·L2+(1-k)·L1的方案,所以,我们应该让L1的部分值为0,L2的部分值为1。所以,可以让L5乘以 -1并加上1:

$$
L_5=-max(0, min((L_2-L_1)+0.5, 1))+1
$$

此时就得到我们想要的了:

image1740754682675.png然后,我们把L5替换k:

image1740754833418.png

长了两个角出来了,这肯定是有问题了,实际上它应该在我如下图所示的位置就应该进行平滑过渡处理了:

image1740755005606.png

此时我们可以让L5不管是等于0还是等于1都映射为0,中间的过渡部分自然会呈现大于0的波形图线:

$$
m=L_5(1-L_5)
$$

image1740755688114.png

此时,我们让L4减去m,此时可以看到,线已经在指定区间了:

image1740755768215.png

但是还是生硬,那我们让m乘上0.5?终于可以了。

image1740755827962.png

为了可以调整平滑的程度,我们可以让L2-L1除以k,得到:

image1740756598852.png有瑕疵,我们应该也要让m乘上k,此时可以调整混合平滑度的式子就此诞生了:

image1740756647500.png

另外,k不一定在0~1之间的范围,可以是任意范围,这样平滑的程度可以任意调整:

image1740756982917.png

这是图线的链接地址

0 Answers