ref: https://zhuanlan.zhihu.com/p/35098986
题图: UE4 Distance Field Ambient Occlusion
Shadow
最基本的制作阴影的方法就是从光源发射射线, 然后判断着色的点和光源之间是否被物体遮挡, 有遮挡是阴影内, 无遮挡是阴影外. 但是这么做的结果投射出来的阴影边缘比较硬. 现实中我们见到的阴影都会有柔和的半影区, 如下面两个图所示:
HardShadow
SoftShadow
使用SDF做柔和阴影具有先天优势, 因为场景内的距离信息全都有. 上图的做法就是计算每个着色点距离本影的距离, 如果接近, 那么就计算一个跟距离有关的衰减作为半影的值去模拟柔和阴影. 现在回头看看利用SDF计算阴影的方法, 我们很容易联想到, 这方法类似计算环境遮蔽啊, 所以, SDF当然可以用来计算AO.
Ambient Occlusion
AO是Crytek[1]发扬光大的. 我们可以在碰撞点周围随机采样位置信息, 距离碰撞点在一定范围内, 算作AO的权重加权:
AO Only
目前为止, 我们的渲染对象都是简单的几何体, 可以使用公式描述, 但是如果想要更进一步使用SDF的话, 比如在游戏内, 我们需要面对更复杂的几何体, 可能无法用公式描述, 怎么办呢? 因此我们需要把这些复杂物体映射成SDF.
Create SDF
Evans[2]提出一种方法: 使用立体贴图存储SDF. 后来UE4的Mesh Distance Field[3]也使用了类似的方法. 但是两者的都有一个主要的缺点就是比较耗内存. 后者把这个技术限制在DX11或更高的API特性才能使用, 并且只能用在等比缩放的静态物体上.
Evans的方法是用OBB分多个切片, 然后切片和物体相交算SDF.
Evans, 2006.
如果是简单的物体, 可以实时算, 复杂的话可以离线算好实时渲染时使用. 另外一种变通方法是使用立体网格每一个网格去采样目标物体的三角面, 寻找距离最近的三角面做SDF. 这种方法首先需要存储立体贴图比较耗内存, 其次是目标物体越复杂这个算法就越耗时, 目前我还没有去看UE4的实现, 但是根据使用方式猜测是这种方法.
作为测试和演示, 我采用的方法是把3d信息平铺到2d贴图上:
采用2D平铺模拟3D texture
SDF Visualization
SSS
这里使用的方法基于Simon Green[4]使用depth map快速模拟SSS。
截图来自 Real-Time Approximations to Subsurface Scattering
利用SDF进行简单的SSS
可以使用魔参调整通透度
[1] Mittring, M., Finding Next Gen CryENGINE™ 2, 2007.
[2] Alex Evans, Fast Approximations for Global Illumination on Dynamic Scenes, 2006.
[3] Daniel Wright, Dynamic Occlusion With Signed Distance Field, 2015.
[4] Simon Green, Real-Time Approximations to Subsurface Scattering, 2004.
编辑于 2018-04-09