SDF(signed distance field)

        一般来说,无论2d或者3d资产都有隐式(implicit)显式(explicit)两种存储方式,比如3d模型就可以用mesh直接存储模型数据,也可以用sdf、点云(point cloud)、神经网络(nerual rendering)来表示,2d资产(这里指贴图)也是如此。比如贴图一般直接使用rgb、hsv等参数来进行表示,但这样子再放大图片后会出现锯齿,所以想要获取高清的图像就需要较大的存储空间,这时候就需要矢量表示,在2d贴图中sdf就是为了这种需求产生的。

        SDF(Signed Distance Field)在3d和2d中都有对应的应用。在3d中光线追踪对于性能的消耗过大,所以sdf常常被用来作为物体的隐式表达,配合ray marching达到接近光线追踪的效果,也有比如deepSDF这种对于模型的隐式表达方面的应用。在2d中,sdf常常被用来表示字体,原神的面部渲染中阴影部分贴图也是基于sdf生成的。

        SDF的本质就是存储每个点到图形的最近距离,即将模型划出一个表面,在模型表面外侧的点数值大于0,在模型表面内侧的点数值小于0

对于任意的给定点,距离函数能够给出其到一个物体上最近点的最小距离(这个距离可能是带符号的)。

 

此外,SDF也具有一些比较好的性质,例如混合一个移动边界时,比如希望得到A、B时刻之间某时刻的边界时,SDF就能取得比较好的结果,如下图所示,试图混合A、B时刻之间的边界,如果直接混合 lerp(A,B) 可能得到如灰色区域所示的结果,但如果将该边界转换成SDF后,即 SDF(A) 、 SDF(B) ,再进行混合 lerp(SDF(A),SDF(B)) ,再将混合后的SDF还原得到最终结果 SDF−1(lerp(SDF(A),SDF(B))) :

 或者对两个不同结构的物体进行混合时,可以混合它们的距离函数。

SDF可以被用来做ray marching,来解决光线和SDF的求交问题,这背后有一个key idea:某一点SDF的值等价于其附近的安全距离,从一点出发在每个step沿着ray的方向移动SDF(p)的距离,此处的p指的是当前step时的那个点。该方法对于运动物体(刚体)可行,对于形变物体需要重新计算SDF。

此外,SDF能被用于估计大概的percentage of occlusion,即SDF的值一定程度上反应观察者能够看到的“安全”角度,该角度越小意味着越少的可见性,阴影应该越黑。下图中下方灰点表示shading point,该射线指向面光源中心,通过计算安全角度近似估计可见性。

 

具体算法流程(在ray marching的过程中,为了得到这个最小“安全”角度,记录下每一个step时对应的角度,并选择其中最小的角度作为最终结果。):

  1. 在ray marching每一步计算安全角度,分别得到p1、p2、p3
  2. 根据p1、p2、p3计算出其中最小的安全角度
  3. 根据该最小安全角度,近似得到可见性

 

在实时渲染中,为了节约计算量可以把arcsin去掉,因为SDF(p)与p到o距离的比值已经可以反映夹角的大小,最终可以写为:

min{k⋅SDF(p)/|p−o|,1.0} ,其中越大的k,可以得到越接近1.0的值,会使得半影区域的过渡带越小,阴影也会越“硬”。

优缺点

优点:速度快(这里忽略SDF的生成过程,与shadow map相比,该方法更快,基于shadow map的方法时间开销主要使用在生成shadow map,此外当渲染本身使用Ray Marching方法时,使用SDF生成阴影更加方便);高质量。

缺点:需要预计算(生成SDF);需要高存储(目前有一些方法使用层次化存储结构,在不同层次使用不同粒度);可能有artifacts。

参考视频

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>