ios 不被遮挡 阴影_图形学之 - 你的物体脱节了 —— 什么是软阴影,如何正确使用...

9deb8cd683958a8699166bc09a91f39e.png

今天换一篇基础的文章,因为还有不少美术朋友在这个细节上不甚明白

fabfc9ed6ba97ed6119e097b07cfccad.png

有光的地方就有阴影,然而在计算机里要正确渲染出阴影绝对不是一件容易的事。而正确使用阴影可以让你的场景真实度大大提升。

阴影的行成是因为光线被物体遮挡了。如果光线只是来自于一个绝对小的点,那么这个事情很容易。比如你可以画一条伸到光源处的线,这条线到达光源前被挡住的话就说明当前处在阴影当中。不过如此理想的点在现实中不存在,不然就会出现发光的黑洞奇点这种奇怪的物理现象。而事实上用这样一个假想条件渲染出来的画面通常也不真实(这个就不只是阴影问题了),如此画出的阴影我们称之为硬阴影,这种光源称之为点光源

很明显软阴影的存在是因为现实中没有这种理想的发光点,光源都是有一定大小的。我们假设一个光源有0.2m x 0.2m的大小,然后把这个光源拆成6个点光源来模拟。结果如下图所示。可以发现随着点光源的不断叠加,阴影边缘开始变得柔和了!

d459970b9c5a218b277890a334f18a3e.png

72a6751ece84daa1e6f3c15f1d531930.gif

748f746fc18ed822dd4348d8c2068f97.png
UE4里面的PCF软阴影。不难看到有跟我们拆分点光源方式有同样的条纹。其实两者内部概念是很相似的。

不难想象,如果我们继续把这个光源拆成更小的点光源,我们会得到一个相当柔和的边缘,这个就是软阴影,它的柔边叫作半影(Penumbra)

那么软阴影为什么复杂呢?这就要提到概率的问题。前面说了,如果我们要知道一个像素是不是处在阴影当中,画一条延伸到光源的线就行了。如果是点光源,那么这个问题是确定的:要么被遮住了,要么没有被遮住。 但是对于软阴影就不同了,因为光源可以分解为无数个小的点光源组成,你画这样一条线,根据这条线另一端延伸到的光源上的位置的不同,有可能处在阴影中,有可能不在。这就是数学上讲的不确定性,测量的度量叫概率。而且其实软阴影“软”的部分正好对应被遮挡概率不为100%的位置,进一步可以说,半影的不透明度其实等于遮挡概率。(从几何上讲就是可视立体角的大小)。

而我们如今的电脑在框架上讲是个确定性机器,由确定模拟不确定是比较麻烦的。我们平常看到的图像是由确定性的光栅化行成的(关于光栅化大家可以自己搜索一下)。对光线跟踪算法来说相对好点,但对于基于光栅化的游戏引擎来说就不一样了。电脑在绘制阴影的时候实际上对每个虚拟点光源都要完全测量一次整个场景(被照到的部分)的遮挡情况。如果我们把光源拆为6个虚拟点,那么电脑需要测量6次,也就是近乎6倍的计算量。而且嘛,效果还不是很好,可能需要100个以上才稍微好看点!

-------------------------------------------------

在接着往下之前我们得简单插播一下什么叫阴影贴图。阴影贴图实际就是一张从点光源位置生成的一张遮挡关系图,是光栅化渲染所特有的。既然叫贴图,电脑随后会把这张图投射到三维世界中,就行成了阴影。

-------------------------------------------------

那么要计算出这个概率,我们需要采样。为此科学家们琢磨出了不少”馊“主意。有一个经典的算法叫PCF(Percentage Closer Filtering),它的概念是把遮挡情况简化为一个存在于阴影贴图里的2.5D空间,然后随机进行采样,然后平均。大家平时在某些软件里看到的PCF5x5或者PCF3x3就是这个技术,后面的数字代表横向和纵向采样次数。“软边缘”面积越大,要求的采样次数越多。

有人可能要问,为什么不直接模糊阴影? 其实大佬们也是这么想的! 可惜数学上阴影所在的空间跟三维场景的空间并不同(光源视点的step空间),无法直接模糊。历史上科学家们做过各种模糊的尝试,但都不太实用。比如有把阴影分解到cosine频域空间的,有利用exp函数做逼近的,还有利用多次渲染先勾画阴影边缘的。后来还有创新式利用反向跟踪的,利用几何着色器进行边缘空间扩张的,等等,等等... ...这个领域不大但栽的人却不少。

所以直到现在,几乎所有游戏引擎依然采用的是80年代的PCF算法或者它的改进版PCFSS。以及部分引擎用的是SFSS。这个就不详聊了。

但是阴影贴图有个很大问题。阴影贴图本身是有精度限制的,PCF的软阴影可以把这个问题更加放大。这个问题叫做peter panning,会让阴影和物体接触点脱节,让人觉得物体没触地或者移位。而最近兴起的contact shadow(接触阴影)也是为了解决这个脱节问题而生,它采用的是屏幕空间光线跟踪,距离很受限,但脱节区域通常也都很小。

9bd788f8daae25f0705b1e07f87761a0.png
这个脱节问题在各大游戏里不要太常见

8d0439832f844cc0ada6b6f372beaa9a.png
PCF软阴影的问题: 左-基础效果,中-仅调整bias,右-仅开启接触阴影

3c420e3ad25c12243199eb860de63fca.png

303179e9d56d84ba1229706ba5226405.png
UE4里面可以调整阴影脱节的几个选项。注意Shadow bias不能调得太小,否则会出现另一个著名问题-shadow acne。

这几个问题都是阴影贴图算法天生的。所以能做的是尽量降低bias到一个合适水平,提高分辨率,少做很细很薄的遮挡体,然后高端平台上开启接触阴影。

除此之外,PCF也不能解决半影精确性的问题。因为半影必须离接触点越远,越不确定,面积越大颜色越浅。

这个问题直到硬件光线跟踪的出现终于得到解决(对,最终还是要靠老老实实一根光线一根光线地采样)。

16a443186afe157fb8a747a6f354898e.png
UE4的阴影对比:左-光线跟踪阴影,右-PCFSS。光线跟踪解决了脱节和半影精确性问题

画质提升不少,而且光线跟踪阴影可能可以增加渲染性能。因为传统的级联阴影贴图会导致大量重绘(当你在统计数字里看到场景三角形比实际处理三角形小几倍的时候,阴影就是一个最大幕后推手。)。当三维物体数量太多时,重绘会导致CPU负担显著增加。而光线跟踪几乎不会导致CPU负担问题。同时,由于储存方式的不同,传统阴影贴图可能导致更大的显存和显存带宽占用。就连手机端的PowerVR 显卡,最新款的架构也开始支持光线跟踪,而且光线跟踪阴影甚至可以比传统阴影贴图快一倍以上*。

32c8c79648ef32c46c5ac9b6c1380750.png
移动端光线跟踪对比:左-光线跟踪,右-传统阴影贴图

光线跟踪虽好,但是当下还有不少引擎的灯光烘培用的是传统阴影贴图。此时合理排布阴影分辨率,改变遮挡体厚度等操作依然必不可少。真心希望完全不需要烘培的时候早点到来(UE5?)

最后其实环境遮蔽也是一种软阴影,这里就不展开了。

所以如果你的目标群体有支持光线跟踪的硬件,采用光线跟踪阴影是最直接最简单的手段。否则需要像上文说的一样不停调整几个关键参数。

由于有了光线跟踪,曾经困扰大家的阴影贴图分辨率重要性也降低了。传统处理大空间需要的级联阴影贴图也变得不那么重要了。只需要打开光线跟踪阴影,可以看到画质的大幅提升。Just one simple flip.

END < 原文在公众号:图形学那些事

* : Reference: https://www.imgtec.com/blog/ray-traced-shadows-vs-cascaded-shadow-maps/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值