Unity3D的全局光照和阴影:上篇(全局照明GI和局部照明)

一、全局照明和局部照明

全局照明(global illumination,GI)是用于向三维场景中添加更为逼真的光照效果的一组算法总称。全局算法不仅考虑光源发出的光与被照亮物体之间的关系,即直接照明(direct illumination),还考虑光线从某一物体的表面传递到另一个物体的表面时的关系,即间接照明(indirect illmination)。而局部照明(local illumination)则只需要考虑直接照明即可,不考虑光线在物体之间的反射。直接照明和局部照明如下图:

Unity3D的全局光照和阴影

全局照明需要考虑的是全部入射到摄像机中的光线,而局部照明则只需要考虑进入摄像机中的那一部分直接照明的光线。

Unity3D的全局光照和阴影

光线追踪是一种很合适实现全局照明的方法,这种技术通过跟踪场景中的光线传播的轨迹路径来模拟真实世界中的景象。但光追技术目前太慢,不适合大多数需要渲染图形的场合,只有在一些非实时的离线渲染上使用光线追踪技术去实现全局照明,如动画片等。目前,使用光栅器对给定顶点进行插值,生成片元,然后对片元进行着色操作,是生成实时图像的标准方法。

随着硬件性能的提升和渲染算法的不断改进,视频游戏等实时渲染领域在一定程度上也可以使用全局照明的方式来渲染了。普遍的方法是只为在场景中静止不动的物体预先针对间接照明进行计算,并把计算结果存储起来,然后在运行时使用这些间接光照信息进行渲染。因为待绘制物是静止不产生变化的,所示这种方法产生的效果在运行时仍然是正确的。

这种预先计算间接光照效果,最后把效果以光照贴图的方式存储,产生一张贴图的过程被比喻成“烘焙出一张糕饼”出来。所以unity把这种技术成为烘焙式全局照明(baked GI),或者称为烘焙式光照贴图(baked lightmapping)。这个光照贴图最终结果是把场景中静止的游戏对象的光照效果信息合并成一张大的纹理,供运行时使用。烘焙式全局光照可以利用更多的预结算时间支持用区域面光源产生的光照效果,以及支持更加逼真柔和的阴影。

Unity5.0之后还增加了一种预计算实时全局照明的技术,和烘焙式全局照明类似,这种新技术仍然限于应用在静态物体上,依然需要一个运行前预结算的阶段。但在预结算阶段中,除了“计算出当前光源发出的光线,沿着当前的传播路径照亮到本物体时的效果”之外,还要处理“如果在运行时有光线沿着别的传播路径传递到本物体表面时,光线应该沿着哪个方向传递出去”的问题,引擎会预计算所有可能的光线传播路径并存储,在运行时,将当前的光源输入预结算的光传播路径中,并计算光照效果。

由于存储的是传播路径,因此使用预结算实时全局照明技术在运行时,光源的数量、类型、位置等属性都可以改变。被照亮物体的材料属性,如吸收光的能力,自己发射光的能力也可以改变。在运行时,间接照明的效果也会相应更新这一切只要保持物体是静态的且形状不发生改变即可。

使用预计算实时全局照明也能产生较为柔和的阴影,但是除非场景很小,否则这些阴影的效果一般会比使用烘焙式全局照明所产生的阴影要粗糙些。

预结算实时全局照明是在运行时才执行最终的光照计算的,但是为了达到实时渲染的要求,引擎已经将实现它的算法优化到了很短的时间内完成。在运行时,如果光源或者被照亮物体的相关属性相比预计算阶段发生了很剧烈的变化,则会需要更多的时间计算最终的光照效果,所以如果运行平台的硬件性能非常有限,使用烘焙式全局照明可能会更高效些。

烘焙式全局照明和预计算实时全局照明都有一个局限性,即只能对静态物体进行操作,移动的物体无法将光线反射到其他物体上,反之亦然。最大程度上解决这个问题的方法是使用光照探针(light probe)拾取静态物体的反射光。光探针是场景中的某个位置点,在烘焙阶段或者预计算阶段,在该位置点上测量或者探测光线,并在此位置记录下相关的光照信息。在运行时,运动的物体将从离它最近的光探针中取出间接光照信息并使用上。

从前面可以看出,全局/局部照明和实时/预计算光照是两组不同的概念。前者是对绘制效果能达到一个怎样的仿真度的描述,后者则是执行绘制时所采取的不同算法。虽然对于目前的计算机硬件能力而言,绝大部分全局照明所产生的效果还需要使用预计算光照,以离线的方式实现。

二、引擎提供的光源类型

2.1 点光源

点光源(point light)指处在空间中某一个位置点,其大小本身可以忽略不计,并且其照亮的范围是一个球体光源,光的亮度值随与光源的距离变大而逐渐变小,当超过照亮范围(effect range)时亮度值变为0。点光源发出的光线在某点亮度值与某点到光源距离的平方成反比。

2.2 聚光灯光源

聚光灯光源(spot light)和点光源类似,聚光灯光源也有光源的位置点和作用范围,与之不同的是聚光灯光源的照亮范围是一个圆锥体,光源位置就在圆锥体的锥顶处。

2.3 有向平行光源

有向平行光源只有颜色和方向,没有具体光源位置。不会随着传播距离发生衰减。

2.4 区域面光源

实际中光源本身都有一定表面积,并且有一定的照亮区域。面光源就是其中一种,照亮区域是由其所在的空间中的区域矩形所指定的,光从它的一侧表面,均匀地向四面八方发射。对于区域面光源的照明计算相当耗费性能它不支持实时进行光照计算,因此在运行时不可使用,只能预先烘焙到光照贴图中。

2.5 cookie

在影视中,经常通过灯光效果营造一种真实景象,但本质上是虚拟出来的景象,要营造这种效果,通常是遮蔽一部分光线,通过一部分光线,然后把产生的轮廓图案投射到场景中去,因为营造这种效果的设备及形成的效果很像做曲奇饼用的花纹模具,所以称为cookie。

unity3D支持在灯光效果中使用这种cookie技术。使用了cookie技术模拟了光从窗户中穿透过来,投影到地面上。这种效果需要一个有向平行光光源和一个被称为cookie的纹理就能实现。cookie纹理中其实只有其Alpha通道数据,即透明值数据有效。因为在设计cookie纹理时,通常是把它设计成一张灰度图的形式,所以当导入一个cookie纹理时,Unity3D引擎提供了把cookie纹理的颜色亮度信息转为Alpha信息的导入选项。

三、使用实时模式光源进行全局照明

每当在Unity3D编辑器中新建一个表征光源的游戏对象时,这个光源都是实时的。该游戏对象上挂接了Light组件,并且组件的Mode属性设置为Realtime。这种光源称为实时模式光源。实时是指在每一帧中,这些光源都直接为引擎提供光照计算所需要的参数,引擎计算出当前场景的光照效果。场景中的光源或者物体如果发生移动,或者光源的颜色亮度等发生变化,光照效果可以立即得到更新。在Unity3D的Scene窗口和Game窗口中可以同时观察到更新的光照效果。

默认地,实时模式光源所发出的光线不能从一个被照亮物体的表面反弹(bounce)到另一个物体的表面上。每一个物体只受光源影响,它们之间相互不照亮,相互不影响,即只产生直接照明,不产生间接照明。但Unity3D引擎支持使用实时全局照明,选择Window->Lighting->Settings命令,在弹出的Lighting窗口把Scene选项卡的Realtime Lighting项的Realtime Global Illumination复选框选中。选中后,场景内所有的实时模式光源发出的光线同时能执行直接照明和间接照明,即可以进行全局照明。

当光源的位置和强度变换缓慢时,使用实时全局照明的光照计算方式是很有真实感的,但如果光源的位置或强度变化得过快,使用这种组合方式并不是一个高效率的方案。目前,Unity3D使用Enlighten渲染器来实现全局照明效果,和烘焙式全局照明相比,实时全局照明将会耗费大量的系统资源计算光照效果,所以这种方式更适用于中高端PC,或者PS4等最新主机平台游戏。

当Lighting窗口中的Realtime Lighting|Realtime Global Illumination复选框被选中,但某个实时模式光源不想为全局照明中的间接照明部分提供贡献时,可以将光源的Light组件中的Indiretional Multiplier属性设置为0,这意味着该光源不会为间接照明提供贡献。

当Lighting窗口中的Realtime Lighting|Realtime Global Illumination复选框被选中时,unity会使用Enlighten引擎为静态的物体预先计算他们之间的外表面到外表面的光线传递路径,即预计算实时全局照明:

Unity3D的全局光照和阴影

当启用预计算的实时全局光照功能时,将场景中静态的物体表面的光照效果保存成“光照数据资源”(lightig data asset),供运行时使用。Unity3D引擎可以在运行时产生和更新一组低分辨率的光照贴图,从而达到一些单纯使用烘焙式光照贴图无法达成的动态光照效果。

实时光源可以照亮静止和运动的游戏对象,并且可以投射逼真的阴影。这些阴影显示与否,取决于选择Edit|Project Settings|Quality命令后,Quality Settings面板中的Shadow Distance项的取值,当生成阴影的位置到当前摄像机的距离大于此值时,此处就不显示阴影。

如果光源能投射阴影(Light组件的Shadow Type属性设置为Soft Shadows或Hard Shadows),场景中的动态和静态的游戏对象所对应的深度信息都将被渲染成阴影贴图(shadow map)。这些游戏对象的材质中的着色器将会对这个贴图进行采样,以便它们可以互相投射实时阴影。

四、使用烘焙式光照贴图进行全局照明

其挂接的Light组件的Mode属性设置为Baked的光源称为烘焙模式光源。Unity将会在运行前预先计算这些光源产生的直接照明和间接照明信息,烘焙到光照贴图或光照探针上。当前场景中静态物体表面的颜色信息烘焙到光照贴贴图,用以照亮动态物体的照明信息则烘焙到光照探针,在运行时不再重新计算这些照明信息。在烘焙出来的光照贴图中,可以存储静止的游戏对象投射到静止的游戏对象的阴影,可以在运行时直接使用而不需要去计算。

因为所有的光照信息都是预计算的,在运行时无法获得 烘焙模式光源发出光线的方向信息,所以不能产生镜面反射(specular reflection)效果,烘焙模式光源也不会因为场景的改变而使其光照效果发生变化。一个被烘焙模式光源照射下的运动的游戏对象,无法向另一个无论运行或者静止的游戏对象投射阴影;被烘焙模式光源照射下的静止的游戏对象,可以投射较低分辨率的阴影到运行的游戏对象上,能产生低分辨率的阴影,但要使用光照探针才能达到这种效果。

烘焙式贴图在运行期是不可改变的。场景中的一个物体在使用光照贴图去照亮它的同时,也可以使用实时光源,以颜色叠加的方式作用在它上面。所以,如果不想产生“同时用了光照贴图和实时光源,场景变得比预料中更亮了”的问题,在烘焙光照贴图完毕后,可以把场景中实时光源都去掉。

与使用实时光源相比,因为烘焙式光照贴图需要包含更详细的直接照明,所以使用烘焙式光照贴图要占用更多的内存。

五、使用混合光照进行全局照明

其挂接的Light组件的Mode属性设置为Mixed的光源称为混合模式光源。混合模式光源可以在运行时改变其位置、朝向、大小、光的颜色和强度等属性,但这种改变不能随心所欲,有较大限制。混合模式光源可以照亮静止和运行的游戏对象,并且一直贡献直接照明,可按选择提供间接照明,被混合模式光源照射下的运动的游戏对象总能在其他运动的游戏对象上投射实时阴影。

在场景中,所有的混合模式光源将使用同一种光照模式(mixed lighting mode)。要设置混合光照模式,选择Window|Lighting|Settings命令,弹出Lighting窗口,在Scene选项卡可以看到Mixed Lighting选项,这就是混合光照模式的设置选项。

该选项下面有两个子选项,分别是Baked Global Illumination复选框和Lighting Mode下拉列表:

Unity3D的全局光照和阴影

如果一个光源本身并不需要参与游戏的相关逻辑,那么它可以考虑设置成混合模式的光源,因为由混合模式光源提供的直接照明是在运行时计算,所以静止的游戏对象将会在最大程度上保持预期的视觉效果。

在混合光照模式下,Mixed Lighting选项下的Lighting Mode子选项有3种,它们分别是Baked Indirect、Shadowmask、Subtractive。

5.1 Baked Indirect照明模式

对于混合模式光源,当Lighting窗口中的Lighting Mode选项被设置为Baked Indirect时,Unity3D仅对光源提供的间接照明部分进行预计算。而所有离当前摄像机距离小于Shadow Distance值的阴影,都是在运行时实时计算。在本模式下,物体之间阴影投射与接受的关系如下表所示:

Unity3D的全局光照和阴影

5.2 Shadowmask照明模式

阴影蒙版(shadowmask)是一种纹理,它和与之搭配使用的光照贴图纹理使用相同的uv采样坐标和纹理分辨率。阴影蒙版的每一个纹素中存储着它对应的场景某位置点上至多四个光源在此的遮挡消息,即记录着这一点中,有多少光源能照的到,对多个光源照不到的信息。至于为什么最多支持四个光源,原因是在目前的GPU架构中,一个纹理像素最多只支持四个颜色通道,如RGBA。

在此模式下, Unity3D预先计算从静止的游戏对象投射到其他静止的游戏对象上的阴影,即由间接照明贡献的阴影,并将它们存储在一个单独的阴影蒙版纹理中,因此Unity3D在阴影蒙版中存储的唯一的阴影信息是静止的游戏对象投射到其他静止的游戏对象上的阴影。如果某处有超过四个光源产生阴影,则多出来的混合模式光源将会转用烘焙式光照计算,具体哪个光源转用烘焙式光照计算阴影由引擎决定。每个光探针可以存储最多4个光源的遮挡信息。如果4个以上的光源发出的光线相交,其余的混合模式光源则会(自动地)改为使用烘焙模式,并且这些光照信息是预先计算好的。又因为混合模式光源的阴影蒙版在运行时是有保留的,所以运动的游戏对象所投下的阴影可以与预计算并存储在阴影蒙版中的阴影正确的合成,而不会导致重复投影(double shadowing)的问题。

在这个模式中,间接照明效果和阴影衰减都存储在了光照贴图中,阴影被存储在一张额外贴图(阴影蒙版)上、当只有主定向光源时,所有被照亮的物体都会作为红色出现的阴影蒙版中。红色是因为阴影信息存储在纹理的Red通道中,事实上,贴图中至多可以存储4个光照的阴影,因为它只有4个通道。

在Shadowmask模式下,其他静止的游戏对象向一个静止的游戏对象投射阴影时,是不受Shadow Distance选项的范围限制的。只有运动的游戏对象向静止的游戏对象投射阴影时才受此限制,要在ShadowDistance范围内才能生效。且此部分阴影是通过阴影贴图实现的。同时运动的游戏对象也可以从静止的游戏对象处接受阴影的投射,而这部分的阴影是通过光探针实现的,这些阴影的保真程度取决于场景中光探针的亮度。一般来说,阴影蒙版纹理贴图分辨率比实时阴影贴图的分辨率要低一些。

Unity3D引擎自动对静态和动态游戏对象生成的重叠阴影进行组合,因为控制静态游戏对象的光照与阴影蒙版和控制动态游戏对象的光照与阴影信息的阴影贴图将会被编码成遮蔽信息(occlusion information)。

在Shadowmask模式下,物体之间阴影投射和接受的关系如下:

Unity3D的全局光照和阴影

5.3 Subtractive照明模式

在 Subtractive模式下,将光源的直接照明部分烘焙进光照贴图,而将在其他模式下用来组合动态和静态的阴影的信息丢弃。因为所有的光源被烘焙进光照贴图了,所以Unity3D引擎不会在运行时做任何光照计算。除了主有向平行光源之外,在其他混合模式光源的照射下,静止的游戏对象都不会产生任何镜面反射或者高光效果,也无法接收从运动的游戏对象投射来的阴影。运动的游戏对象能被实时照明,并支持光泽反射,但这些运动的游戏对象只能借助于光探针才能从静止的游戏对象处接收阴影。

在 Subtractive模式下,主有向平行光(通常是太阳)是唯一的光源,它将运动的游戏对象上的阴影实时地投射到静止的游戏对象。从静止的游戏对象投射到其他静止的游戏对象上的阴影会被烘焙到光照贴图中,即便是主有向平行光也是如此。Unity3D引擎无法保证烘焙的阴影和实时阴影能正常的融合,所以在Lighting窗口设置了Realtime Shadow Color选项。Unity使用该选项指定的颜色组合实时阴影和预烘焙的阴影。

在 Subtractive模式下,物体之间阴影投射和接受关系如下:

Unity3D的全局光照和阴影

版权声明:本文为CSDN博主「小橙子0」的原创文章,
遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cgy56191948/article/details/105268015

最新文章