如果你想知道它是如何工作的,最好按照以下步骤进行:
1.首先您应该了解形状的定义。
2.最好考虑它们的2D形状,因为三个维度可能会让您感到复杂。
所以让我来解释一些形状:
圆形
![Circle](https://istack.dev59.com/JIZgy.webp)
圆形是一个简单的闭合形状。它是平面上所有距离给定点(中心点)给定距离的点的集合。
您可以使用distance()
、length()
或sqrt()
计算到广告牌中心的距离。
《着色器之书》- 第7章
正方形
![Square](https://istack.dev59.com/za8dK.webp)
在几何学中,正方形是一个正方形四边相等且四角相等(90度角)的正四面体。
我在之前的部分中描述了2D形状,现在让我描述3D定义。
球体
![Sphere](https://istack.dev59.com/cm6aL.webp)
球体是三维空间中一个完美圆形的几何对象,是完全圆形球体的表面。
像圆一样,在几何上是二维空间中的一个对象,球体在数学上被定义为所有距离给定点r相同的点的集合,但是在三维空间中。参考- 维基百科
立方体
![Cube](https://istack.dev59.com/KEik4.webp)
在几何学中,一个立方体是一个由六个正方形面、平面或边界限定的三维固体物体,每个顶点处有三个相遇。
参考:维基百科
距离函数建模
现在是理解距离函数建模的时候了。
球体
如上节所述,在下面的代码中使用length()
计算到广告牌中心的距离,您可以通过参数s进行形状缩放。
float sdSphere( vec3 p, float s )
{
return length(p)-s;
}
盒子
// Box - unsigned - exact
/// <param name="p">Position.</param>
/// <param name="b">Bound(Scale).</param>
float udBox( vec3 p, vec3 b )
{
return length(max(abs(p)-b,0.0));
}
length()
的用法和上一个例子一样。
接下来我们有 max(x,0)
,它被称为正负分解。
![Positive_and_negative_parts](https://istack.dev59.com/qgZER.webp)
这意味着下面的代码是等价的:
float udBox( vec3 p, vec3 b )
{
vec3 value = abs(p)-b;
if(value.x<0.){
value.x = 0.;
}
if(value.y<0.){
value.y = 0.;
}
if(value.z<0.){
value.z = 0.;
}
return length(value);
}
步骤 1
if(value.x<0.){
value.x = 0.;
}
![步骤1](https://istack.dev59.com/g4jXZ.webp)
步骤2
if(value.y<0.){
value.y = 0.;
}
![step2](https://istack.dev59.com/AlweR.webp)
第三步
if(value.z<0.){
value.z = 0.;
}
![step3](https://istack.dev59.com/cX4cl.webp)
第四步
接下来我们有一个去除额外部分的absolution函数。
![absolution](https://istack.dev59.com/LpYKz.webp)
![step4](https://istack.dev59.com/QxcI8.webp)
前往Absolution
![step3](https://istack.dev59.com/cX4cl.webp)
Absolution 第一步
if(value.x < -1.){
value.x = 1.;
}
![abs1](https://istack.dev59.com/Dds5e.webp)
赎罪步骤二
if(value.y < -1.){
value.y = 1.;
}
![abs2](https://istack.dev59.com/X9UG1.webp)
赎罪步骤3
if(value.z < -1.){
value.z = 1.;
}
![step4](https://istack.dev59.com/QxcI8.webp)
您还可以使用建设性实体几何来制作任何形状。
![Constructive solid geometry](https://istack.dev59.com/ryxpd.webp)
CSG基于三个基本操作:交集(∩
),并集(∪
)和差集(-
)。
事实证明,当组合两个表述为SDF的表面时,这些操作都可以简洁地表示。
![intersectSDF](https://istack.dev59.com/1goBD.webp)
float intersectSDF(float distA, float distB) {
return max(distA, distB);
}
![unionSDF](https://istack.dev59.com/fIXfc.webp)
float unionSDF(float distA, float distB) {
return min(distA, distB);
}
![differenceSDF](https://istack.dev59.com/I5BFn.webp)
float differenceSDF(float distA, float distB) {
return max(distA, -distB);
}