Unity进阶修炼之路(3)——光照:下篇

阴影

有光必有影,阴影是由于光照到遮挡的物体然后投射到另一个物体表面形成的。关于在unity中投射阴影的条件,可以参看上篇的插图

阴影暗斑

这里写图片描述这里写图片描述
来看这两张图,左面的是正确的光照阴影,右边的圆柱体顶部,产生了细小的斑痕,但这是不正确的。该圆柱体顶部应该是光滑的,并不可能出现这样的斑痕。造成这种现象的原因,涉及到我们先前提过的Shadowmap,在阴影贴图中保存的是远近位置的深度信息,当使用阴影贴图来决定是否生成阴影时,我们是需要将顶点位置来和该顶点在阴影贴图中的信息做大小比较。但是,这个存储信息可能不准确。原因有很多情况,包括阴影贴图的分辨率造成的精度丢失,贴图采样算法造成的计算精度丢失等。那么一旦一个原本位于更靠远位置的点,因为精度问题,被计算成位于前面的话,就会产生一个原本不该存在的阴影。

为此,unity提供了一个Bias轴和Normal Bias法线轴偏移值来解决这个问题。前者在点的深度上增加了一定的正向偏移,后者在点的法线方向上增加偏移防止两个深度值接近的点在计算时,因为精度问题出现深度信息的误差。注意的前者不能调整的过大话,会造成阴影面积变小看上去和物体断裂,这是因为原本处于更远位置的点,被计算成了更近的位置,也就是原本该产生阴影的地方,现在不产生阴影。后者调整过大,也会使阴影面积变小,因为在法线方向上的偏移,造成物体受光面积增大,而背光面积变小,因此能产生阴影的面积变小

Shadow Pancaking

这个翻译过来叫阴影平坠?好吧,暂且就这么叫吧。阴影平坠也是解决阴影暗斑的一种方法。它的思路是,假设在一个复杂的场景中,如果光源离阴影投射物体很远,那么就会难免有一些我们无法预料的物体遮挡了光源而产生阴影。这个阴影是我们不希望的,也就是阴影暗斑。那么我们通过剪裁光照空间,给该空间设定一个近剪裁平面,只有位于该平面内的物体才能投射阴影,那么就可以剔除那些我们不希望看到的阴影。
这里写图片描述这里写图片描述

可以看到,左图就会产生一些细小的阴影斑点,右图,我们将光照空间裁剪到绿色平面内。
使用这个方法时,unity是通过调整Shadow Near Plane Offset属性来完成。需要注意的是,首先,该方法不会截断一个mesh,如右图,如果物体模型的mesh正好跨过了该平面,跨过平面的点的位置会被夹逼到该平面上,从而改变了mesh的形状,此时投射出来的阴影可能会不准确。

第二点需要注意的是该值如果调的太低,会产生漏光。看右图,如果绿色的平面被往上推的过多,原本该产生阴影的半圆将被裁剪,从而不再产生阴影形成光线的镂空。

阴影级联

先来看一张图
这里写图片描述

可以看到在靠近屏幕的地方产生了锯齿。这是因为,当生成阴影贴图时,阴影是在光照空间的,这会有一个透视现象。那么离光较远的地方,阴影占用的阴影贴图的面积更大(看下图光线发散,点光源在越远处扩散的面积越大),而近处的阴影占用面积较小。当转到视图空间时,较小的阴影有可能里视口更近,根据近大远小的规则,很可能这个阴影部分被放大,从而形成失真,也就是锯齿。

这里写图片描述

解决方法是我们对阴影贴图分辨率分层次。离光源近的部分,拥有更高的分辨率,避免在转换到视口空间时信息不足而产生锯齿

光照探针

前面已经解释过光照探针,这里不介绍如果正确的使用设置光照探针。我只提一下在unity文档中比较晦涩的部分。
我们说过,光照探针是探测光如何穿越空间的。因此,当一个受光照的物体,位于光照探针中,其接受到的光照由该光照探针决定。而光照探针则是对于光穿越该探针的空间的起点和终点做一个插值计算。因此,如果在这个起点的光照和终点的光照接近,甚至一样,那么这个插值是没有意义的。这也是为是么unity文档中告诉我们,要正确的设置光照探针的密度,位置。

另外,如果我们使用了lod,只有最高细节的模型的间接光是被烘焙的,低模的间接光采用光照探针的方法实现。所以如果在使用lod的时候,我们没有正确放置光照探针,那么lod模型显示是错误的

环境光遮挡

环境光遮挡决定了多少环境光会被照射到物体的表面。也就是说,即使是从物体表面反射出的环境光,仍会进一步的收到遮挡,所以实际显示出来的光照效果会更暗。Unity在使用Realtime GI时 ,会使用实时环境光遮挡,这无需我们的操作。如果需要使用烘焙的环境光遮挡,则要进行设置。

光照贴图的定向模式

在unity中,光照贴图有两种模式,定向与非定向。定向模式比非定向模式多使用一张光照贴图。这第二张光照贴图决存储了主光源的方向,和一个比例系数,该系数决定了第一张光照贴图中有多少光可以沿这个方向射入物体表面。因为有了这两个信息,定向光照贴图将产生类似法向贴图产生的高低效果,而非定向模式,只能是简单的光华的漫反射了

至此,大致把光照中涉及的概念写完了。老实说,没想到写博文也挺累的,看似几个自己理解的概念,要写下来真的也花了不少时间。重申下,这两篇只涉及对概念的理解上的解释,具体的实现,操作,还请参考unity的文档或是其他网上资料。

对于光照,还有两个相关概念,一个是gamma采样,一个是meta pass,后者我会在介绍shader的时候来写,如果我没有忘记的话,gamma的话,看我有时间另补一篇吧,写博客真的很累呢。