本篇我们以下面两个SDF模型为例,分别为Sphere与Cube:
不同SDF混合大体可以分为5种方式:
1.交集。字面上理解就是在渲染不同SDF模型时只留下相交部分,如让Sphere与Cube重合,重合后的模型状态如下:
通过
交集处理
后,变成:
通过 max(d1, d2)
来实现交集函数:
float intersectSDF(float distA, float distB) {
return max(distA, distB);
}
这其实挺好理解,假设SDF在RayMarching下的判断条件为 <=0.01
才能显示其SDF模型的表面,那么模型内部的SDF必然小于0.01。所以:
- 当
Cube(=0.01)
在Sphere(<0.01)
内部时,显示的是Cube的表面,因为max(Cube(=0.01), Sphere(<0.01))=Cube(=0.01)
。 - 当
Cube(=0.01)
有部分在Sphere(>0.01)外部
时,把Cube露出的部分剔除了,因为max(Cube(=0.01), Sphere(>0.01)外部)=Sphere(>0.01)外部
。因为显示模型的表面需要满足<=0.01
,所以Cube露出的部分就都剔除了
2.并集。简单理解就是把不同的SDF合并为同一个SDF。
合并SDF的方式通过
min(d1, d2)
实现。
float unionSDF(float distA, float distB) {
return min(distA, distB);
}
3.差集。在集合论中,差集指的是从一个集合中去掉另一个集合的所有元素后剩下的部分。当Cube与Sphere以如下方式组合,想去掉Cube,只留下Sphere该如何做?
根据上图可知,我们把Cube的部分都去除了,只留下了Sphere,所以可以看到一个镂空的Sphere。这种方式的实现通过如下函数定义:
float differenceSDF(float distA, float distB) {
return max(distA, -distB);
}
如果我们要去除B就在distB前加上 -
负号,如果要去除A就在distA前加上 -
负号即可。
4.混合。混合就是通过一种方法把不同的SDF进行平滑的变换。比如把Sphere变为Cube,或把Cube变为Sphere,这中间通过mix函数实现平滑变换。
mix(cubeSdf,sphereSdf, sin(iTime)*0.5+0.5)
5.重复。重复的过程就是把一个模型在x轴与z轴或y轴上重复绘制的过程。如下图:
实现方式通过类似下面的代码:
float fScene(vec3 pt) {
vec3 pos;
pos = vec3(mod(pt.x + 2, 4) - 2, pt.y, mod(pt.z + 2, 4) - 2);
return sdScene(pos, vec3(1));
}
我们通过mod函数让原点附近的sdf沿着对应轴重复绘制。以 mod(pt.x + 2, 4) - 2
做说明:
可以看到它返回的值在
-2~2
之间。我们也可以扩大在原点附近可重复sdf模型的范围,比如x轴的范围在-5~5之间。z轴范围在 -10 ~ 10之间。
p = vec3(mod(p.x+5., 10.)-5.,p.y, mod(p.z+10.,20.)-10.);