专栏节选 | 26光照方案的选择
本文节选自专栏《郑洪智的Unity2018课》。
洪流学堂,让你快人几步。你好,我是郑洪智。
上周我们学习的模型、材质、贴图决定了场景中物体的形状和外观,但是光照决定了环境的颜色和氛围。光照是一个场景非常重要的一部分。
为了计算3D物体的光影,Unity需要知道照射在它上面的光的强度,方向和颜色。
场景中的光来自于Light组件、自发光物体和环境光。不同光源的颜色、方向以及强度可能都不同。我们在14课中讲解了不同的光源类型,同时别忘了25课讲的自发光材质的物体也是光源,明天的课也会讲解如何设置环境光。
Unity中有多种不同的方式计算复杂的照明效果,每种方法适合不同的情况(目标平台、目标平台的性能等)。
选择光照方案
一般来说,Unity中的光照可以分为“realtime(实时)”和“precomputed(预计算)”两种,并且这两种技术可以结合使用来创建逼真的场景光影。
- 实时光照即游戏运行中实时计算的光照技术,但是由于是实时计算,对硬件的性能要求就会比较高。
- 预计算即将一些计算过程从实时转移到了游戏发布之前,将预计算的结果存储成文件在游戏运行时就能快速读取这些预先计算好的数据,大幅提升游戏的运行效率。但是相应的,计算结果存储的文件会占用存储空间和运行时内存。
下面我们通过比较不同光照技术的功能、优点、缺点、性能差别,让你能更好的了解在何种情况下用哪种光照技术更合适。
Realtime Lighting(实时光照)
Unity中创建出来的默认灯光(平行光、聚光灯、点光源)是实时光,会在程序运行时实时计算光影效果。光源或物体移动时,可以在Scene和Game窗口实时看到光影的变化。
只使用实时光的效果。注意:阴影完全是黑色的,因为光没有发生反射,并且只有聚光灯锥体内的表面受到了光照影响实时照明是场景照明的最基本方式,对于照亮人物或其他可移动的物体非常有用。同时不需要进行额外的设置,就能看到运行的效果,非常简单。但是实时照明的光影会在游戏运行的过程中每帧计算、更新,对硬件要求相对较高。
实时照明还有一个很致命的劣势就是Unity中实时灯的光线照射到物体表面不会反弹(不会产生间接光)。现实世界中,灯光照到一个物体表面都会反射一定量的光,然后照亮其他周围的物体。比如在夜晚,月亮受到太阳照射,然后又微弱的照亮地球。
如上图中的场景,立方体背面有一堵墙。现实世界中,墙面会反射光线到立方体的背面,会点亮立方体的背面,我们先来看一看没有间接光的情况下,立方体的背面是什么样的。
仅有实时灯光的情况可以看到立方体背面是全黑的,这种情况其实不符合现实世界中的光照。我们再来看一下加入了预计算的照明后,场景会变成什么样子。
如上图,立方体在受到地面、墙面反射的间接光后,显得真实了很多。
如果想要场景中的光影更逼真,我们需要使用Unity中的预计算照明方案。
Baked lightmaps(烘焙光照贴图)
Unity可以计算复杂的静态(光源及物体都不会移动)光照效果,使用全局照明(GI)的技术,并将计算结果存储在名为“光照贴图”的贴图中。这个计算过程被称为烘焙。
烘焙光照贴图时,Unity计算了光源对场景中静态物体的光照效果。
左边是烘焙过的场景,右边是对应的光照贴图这些光照贴图既可以包含直接照射到物体表面的光,也可以包含场景内其他物体表面反射的间接光。游戏运行时,这些光照贴图可以叠加在模型原本的贴图上来创建照明效果。光照贴图可以与物体表面其他贴图叠加一起使用,例如Albedo(反照贴图)和Normal(法线贴图)等。
光照贴图在游戏过程中不能改变,因此被称为“静态”照明。但是实时灯可以在光照贴图上叠加使用,但运行时不能也没有改变光照贴图本身。
通过这种方法,我们可以在游戏中用空间换时间的方式来提高性能,适合移动平台等性能较弱的硬件。
Precomputed realtime global illumination(预计算实时全局照明)
由于静态烘焙贴图无法在运行时变化,无法用于光源移动、参数变化的情况。预计算实时全局照明技术提供了一种交互式更新复杂场景照明的技术。
通过这种方法,可以创建丰富的全局照明环境,并带有间接光,实时响应光照的变化。一个很好的例子就是一天的昼夜交替:光源的位置和颜色随着时间变化。用传统的烘焙照明,这是不可能实现的。
使用预计算实时GI的简单示例为了实现这些效果的同时还能保证游戏以可接受的帧率运行,我们需要将一些复杂的计算从运行时转移到预计算的过程中。预计算将一些复杂的计算负担从运行时转移到了开发过程中,这个过程称为“offline(离线)”过程。
这个离线过程具体是什么呢?
大多数情况下,在光照贴图中存储间接光就可以减少很多运算的过程,这些间接光很大程度决定了场景光照的真实感。间接光比较柔和,几乎没有刺眼或“高频”的颜色变化。Unity的预计算实时GI利用了这些间接光的“漫反射”特性。
一些更精细的照明细节,如清晰的阴影,通常实时灯可以渲染的更好,所以不用将它们烘焙成光照贴图。如果不需要捕捉这些复杂的照明细节,我们可以大大降低预计算实时GI解决方案的计算量和数据量。
通过预计算,可以有效减少我们在玩游戏期间更新GI照明所需的计算,也能很好地支持需要改变灯的属性(例如颜色,旋转或强度)这些需求。
为了进一步加快预计算的过程,Unity并没有直接使用原始的模型网格,而是在场景中创建一个低精度的静态近似几何图形,称为“Cluster(簇)”。
左:将场景视图设置为“Albedo”,可以清楚地看到Unity预先计算好的实时GI生成的贴图。默认情况下,该视图中的贴图大致是簇的大小。右:光照计算完成后将结果转换为光照贴图并应用到游戏的场景通常情况,游戏运行时计算全局照明时会用到“光线追踪”来计算光线的反射,这需要非常复杂处理,实时更新对性能影响很大,但是Unity会在预计算阶段预先用光线追踪来计算表面簇之间的关系。通过将场景简化,移除了复杂网格上对游戏性能影响非常大的光线追踪过程。
Unity高效地为场景创建了一个简化的数学模型,可以在游戏运行时接收不同的输入。这允许我们对在游戏运行时对场景中的灯光或模型颜色、贴图进行修改,而且可以实时看到GI在场景灯光更新后效果。然后,GI的输出可以转化为光照贴图,用于在GPU上渲染,与其他照明和表面贴图混合,处理效果并最终输出到屏幕。
收益和成本
虽然可以同时使用烘焙GI照明和预计算实时GI,但要小心同时使用两个系统的性能成本恰好是它们的总和。我们不仅需要将两组光照贴图存储在显存中,还要在运行时进行解码处理。
选择一种照明方案而不是另一种取决于项目的性质以及预期硬件的性能。例如,在处理能力有限的移动设备上,烘焙GI照明方法可能更合适。在有独立显卡的PC或最新游戏主机上,可以使用预计算实时GI,甚至可以同时使用这两种系统。
必须根据你的项目的性质和目标平台来评估采取哪种方案。当针对一系列不同的硬件时,通常选择性能最差的平台作为目标平台,然后决定采用哪种照明方案。
总结
今天学习了Unity中的光照,有三种方案可供选择:
- 实时照明:平台性能要求高,没有间接光
- 烘焙GI:平台性能要求低,有间接光,但是光源无法运行时变化
- 预计算实时GI:平台性能要求高,有间接光,光源运行时可以变化
今日思考题
想一想你玩过的游戏,里面用到的可能是哪种照明方案?
欢迎你在留言区分享,和大家一起讨论。
别忘了分享给你学Unity的朋友,也许能够帮到他。
你有没有饱受shader折磨的同学?你可以把今天的内容分享给他,或许你能帮到他。
洪流学堂公众号下方菜单最新专栏中可以查看更多技术教程。
《郑洪智的Unity2018课》,倾尽我8年的开发经验,结合最新的Unity2018,带你从入门到精通。