全局光照,简称GI,是一个用来模拟光的互动和反弹等复杂行为的算法,要精确的仿真全局光照非常有挑战性,付出的代价也高,正因为如此,现代游戏会先一定程度的预先处理这些计算,而非游戏执行时实时运算。
选择一个照明专案
广义的来说,Unity的全局光照是”实时”或是”预先计算好”的,在某些情况下两种方法可以结合使用,照出更逼真的场景。本节我们会针对两种技术的差异优势和使用时机做个简单的描述。
实时照明(REALTIME LIGHTING)
实时照明是场景里照亮物体最基本的方法,这些灯源会把光线照射到场景并以每一帧的频率更新,用来照亮角色和会动的对象,可惜的是,Unity实时照明里的光线不会反射,因此我们才导入了全局光照系统,启用了预先计算的技术,都是为了表现一个更逼真的场景。
烘焙全局光照(BAKEDGI LIGHTING)
当烘焙一张光照贴图(Lightmap)时,场景内的静态对象会基于光的影响算出一张贴图成果,并迭在场景对象之上建立照明效果:
这些”光照贴图”可以包含场景内投射到物体表面的直接光源,以及在不同物体间反射的”间接光源”,这样的光照贴图可以透过物体材质上的着色器(Shader)描述像是颜色的表面信息(Albedo)和凹凸(Normals)信息。
烘焙光照所产生出来的贴图,是无法在游戏运作的时候变更运算的,因此被定义为静态(Static),虽然仍可在这层贴图上继续迭加光源计算,但两者已无法交互运算,通常我们采用这光照法来让低阶的手机能顺利执行,解决光在游戏中运行的效能问题。
预计算全局光照(PRECOMPUTED REALTIME GI LIGHTING)
虽然传统的静态光照贴图无法在游戏执行时改变场景光照条件,但预先计算的实时全局光照系统能帮我们实时运算复杂的场景光源互动,透过这种方法,就能建立昏暗的环境带有丰富的全局光照反射,并实时反映光源的改变。
为了在合理的帧率实现这些效果,我们需要在实时运算之前先将一堆垄长的数字数据做”预计算”,预计算负责计算游戏过程中光的复杂行为,它可以在时间空档时进行计算,我们称作一个”脱机”运算。
如何运作?
Unity从表面上采样底层贴图,并从广义定义颜色的值到一个大型的群组,或是”丛集”,这会产生一个低解析的仿真静态几何,以方便我们用来计算光照。
Unity把光迹追踪用在计算这些表面的丛集关系 - 在预计算”光传输”的阶段,然后把世界串成一个网络结构,我们在关键性的游戏过程就不再需要耗费效能的光迹追踪法。通过一个简化的算法可以在游戏过程中变化输入结构,这代表我们可以改变光源或是表面颜色,并很快的看到场景内全局光照的影响,算出的结果产出光照贴图透过GPU着色,并和其他照明或是表面混合,最后输出到屏幕上。
收益和成本(BENEFITS AND COSTS)
虽然可以同时使用烘焙方式的GI和预计算的GI,但要注意是同时仿真两个系统,效能负担也会两次运算的总和,不只是因为要储存两套光照贴图在显卡内存,同时着色器也得付出两次的处理成本。
最终要选择哪个方法还是要取决于你项目的性质和预期的硬件考虑,例如在手机平台上,效能和内存限制较高,烘焙的GI法就会比较适合,如果是在有显卡的计算机上或是游戏机上执行,那可能使用预计算实时全局光照,或两个同时使用就比较可行。决定采用哪一种方法可以针对你的目标平台评估,记得如果项目要同时符合几个不同的硬件需求,往往都是以效能最高的平台为考虑。
预先计算的过程(THE PRECOMPUTE PROCESS)
在Unity里,预计算是在背景执行,不管是自动流程或是手动启用,计算期间你都可以继续编辑你的游戏对象而不受影响,预计算的时候会在右下角出现一个进度条,不同的算法会有不同的运算阶段,进度条上方也会显示阶段名称与进度。
从上面的例子可以看出,11个工作已经进展到第5个,”丛集”还有108件工作要执行完才会到第6个会话。
启用一个预计算(STARTING A PRECOMPUTE)
只有静态对象会被纳入GI预计算,要让预计算启动首先必须最少要有一个静态对象。从属性面板,将对象的Static勾选起来,这会将该物体所有跟静态对象相关的旗标打开,包含导航旗标或是批处理旗标,这或许不是你想要的,针对预计算只要把”Lighting Static”这个旗标打勾即可。
自动/手动预计算(AUTO/MANUALPRECOMPUTE)
如果你的场景设为自动(Lighting->Scene->Auto),Unity的预计算就会自动启动,否则就需要点击在Auto旁边的”Build”按钮手动启动预计算。
手动启动预计算会对场景所有的照明与各方面进行重新评估并重新计算,如果你希望有选择性的计算,可以从”Build”旁边的下拉选单来选择。
使用烘焙GI或是预计算GI(ENABLINGBAKED GI OR PRECOMPUTED REALTIME GI)
预设情况下,两种计算法在Unity里都是启用状态(Lighting->Scene),因为如此,你可以针对单独的光源设定要采用哪种计算法(Inspector->Light->Baking)
在一个场景同时采用两种方法可能会对效能造成负担,最好的做法在同一个时间只用一种方法,要关闭任何一种方法可以从GI的接口(Lighting->Scene),把不要用的方法取消打勾即可,只有有打勾的算法会计算,任何相关光的设定都会被覆盖。
预灯光设定(PRE-LIGHTSETTINGS)
- 烘焙模式是”Realtime”,代表这些灯光仍然会照亮你的场景,Unity的预计算GI系统会处理间接光。
- 烘焙模式是”Baked”,那么这些灯光将会透过Unity的烘焙GI系统处理直接光源和间接光源,产生出来的光照贴图一旦贴到场景上在执行期间是不能改变的。
- 烘焙模式为”Mixed”,场景内的静态对象会被烘焙GI拿去做计算,然而,不像”Baked”模式,混合模式的灯光仍会继续运算即时光源到非静态对象上,这对于你想把静态环境烘成光照贴图,但同时又希望同样一盏灯能为会动的角色计算阴影很有帮助。
GI快取(GI CACHE)
无论是烘焙还是预计算系统,Unity会”缓存”场景的光照数据到”GI快取”,并会在计算时尝试重复运用这些数据来节省时间,你对场景的改变会影响这个数据重复利用的多寡。
如果你要清除这个快取可以从(Preference->GICache->Clear Cache)来清除,清除后代表所有数据都必须重新运算,因次会花费一些时间,在某些情况下你也许需要降低档案空间大小(例如要把项目转到另外一台计算机)是有帮助的。
场景设定(SCENESETUP)
选择着色路径(CHOOSING A RENDERING PATH)
Unity支持许多著色技术或”路径”,在启动一个项目时,必须要订出出一个路线。
- Forward Rendering,Unity预设。每个对象著色是根据每个影响对象的光,透过”Pass”来著色,所以有可能一个对象被重复著色了好几次,取决于有几盏灯在作用范围里。
- 优点:快速,也代表硬件需求低,提供了自定义”着色模型”,快速处理透明度,也支持像是多重采样柔边(MSAA)的硬件功能,等等有些在其他路径上是无法实现的功能。
- 缺点:对象被越多盏灯光影响,花费的运算成本就越高,如果你能管理好你的灯光数量,那这个路径会是一个非常快速的解决方案。
- Deferred,是延迟了光的遮蔽与混合信息直到第一次接收到的表面的位置 法线 以及材质数据著色到一个”几何缓冲器”(G-buffer)作为一个屏幕空间的贴图,最后合成这些结果。
- 优点:照明的著色成本是和像素数量成正比,而非灯光数量,因此你不用再管控场景灯光数量,某些游戏类型将会是一个关键优势。
- 通常需要较强大的硬件,对于手机平台支持度也较低。
选择一个色彩空间(CHOOSING A COLOR SPACE)
色彩空间决定采用哪种算法来计算照明或材质加载时的颜色混合。你可以从PlayerSetting里面找到”Color Space”来设定(Edit->ProjectSetting->Player)
- Linear,推荐。
- 优点:
- 1.让场景内的提供给着色器的颜色也会因为光强度增加变亮,比较接近真实的色彩空间;
- 2.着色器能在没有Gamma补偿的情况下对贴图进行取样,这有助于确保颜色质量在经过著色管道还能保持一致性,能提高色彩和计算的精度。
- 缺点:Linear颜色空间有些手机平台甚至有些游戏机不支持,应该说PC或是一些新手机硬件和次世代游戏机才会支持Linear颜色空间。
- 优点:
- Gamma
着色器的颜色也会因为光强度增加变亮,亮度马上会转为以白色做为参考,这将不利于图像的质量。
不支持Linear的平台就得用Gamma方法替代了。
高动态范围(HDR)
如同颜色空间,相机的”Dynamic range”动态范围是需要指定的,从本质上来说,这是用来定义相机截取的最亮与最暗的颜色范围,要启用HDR可以从相机组件里把HDR项目打勾即可,要注意的是,某些手机硬件是不支持HDR的,在著色路径为ForwardRendering并启用MSAA柔边时也不支援HDR,HDR和Linear颜色空间一起搭配是最好的,在处理非常明亮的颜色的时候还能保有准确性。
在默认的情况下,Unity是使用低动态范围(LDR),颜色会以每个频道8位储存三原色(红 绿 蓝),8位确切的意思是用8个0或1的数字组合成的值,一共会有256种组合,三个频道256 x256 x 256可以组合出1600万种色采来表达从黑色到白色不同层度的灰阶。
在现实环境中,颜色远远超出1600万个色阶,颜色和亮度的排列甚至远远超越了我们人眼所能辨识的,同样的,Unity能够处理超出这些范围的颜色并输出高于LDR设备支持的颜色,用来提供给像是计算机画面的高质量结果,尽管现今输出装置仍有很多限制,这些多出来的数值仍然可有很多的应用。启用HDR之后,会储存更大精度的颜色资料(使用浮点运算表示),能处理更多更亮的颜色范围。
HDR能让我们在同一画面下维持两个巨大差异的亮度,例如场景的阴影区域和户外的亮光,我们也可以在环境场景建立一个”光晕”或发光特效,透过这些特效或可视的光影效果能增加画面的真实感,但也要小心处理这些效果以防止他们曝光过度。
色调映射(TONEMAPPING)
以摄影来比喻的话,如果我们使用不同的曝光度来拍摄我们的场景,我们可以先观察到哪些颜色会因为曝光过度而遗失,浅色调在很亮的区域可能被白色给覆盖过去,暗色调可能会被黑色给覆盖,这像是计算机图学的”色调映像”,当颜色在显示设备(比如计算机屏幕)表现范围之外时,算法会将颜色修正为装置合理的颜色并重现在屏幕上,当相机启用HDR时,建议相机加入Tonemapping这只程序(Assets->ImportPackage->Effects),这只程序可以帮你转换控制超出范围的颜色成为合理的颜色。
环境光(AmbientLighting)
场景中一个照亮整体环境非常重要的就是”环境光”,可以说是影响场景光源最全面的一个要素。
使用环境光的好处是耗用效能很低,因此在手机平台上只要灯光数量控制得宜也能得到很好的表现,你可以从Lighting窗口(Window->Lighting)找到EnvironmentLighting设定区域(Lighting->Scene),改变Ambient Source来改变环境光来源。
反射源(REFLECTIONSOURCE)
默认的情况下,场景中的对象会使用Unity内建的标准着色器(StandardShader)来著色,标准着色器是一个基于物理的着色器(PBS),它会透过模仿真实世界的物理特性像是反射或能量传递等来模拟真实世界里光在材质上的表现。
当使用标准着色器时,每一个材质都会具有一定程度的镜面反射(specularity)和金属反射(metalness)属性,在没有强大的硬件来处理即时光迹追踪反射的情况下,我们得仰赖预先计算著色反射,我们使用了一个由六张描述天空的图片所组成的方体贴图(Cubemap)或从Unity 5用来从定点搜集环境信息的反射探头(Reflection Probe)产生所需的贴图,然后在和其他光和地表信息混合运算来仿真如同我们真实世界看到的反射效果。
在预设的情况下,调高Specular和Metalness会更清楚的反射天空盒,反射的来源可以从设定来调整。
场景内的对象在默认的情况下会反射天空盒的内容,但你可以从Lighting接口里找到ReflectionSource属性来改变来源,指定一个新的方体贴图,或指定一个反射探头来定义。
反射探头(REFLECTIONPROBES)
这种探头从他们的位置对周围取样并把结果写到方体贴图,可以让周围经过的物体得到环境的反射影像。你可以透过GameObject->Light->Reflection Probe来新增一个反射探头,反射探头的位置会决定方体贴图取样的内容,以及反射所看起来的样子,一般来说,基于效能考虑反射探头越少越好,请记住,反射探头并非用来让物理得到精确结果,而是让游戏世界有更好的反射,大多数情况下几个安排妥当的反射探头就很足够了。
在反射探头的属性面板我们可以设定Type为实时(Realtime),烘焙(Baked)或自定义(Custom),需要明白的是,实时反射的设定对效能极为不利,每多一个实时反射探头就会多出额外六次的著色运算,因此摆设实时的反射探头应该要有明确的需求,例如反射会闪动的霓虹灯,否则一般来说建议设成烘焙的就够了,效能也会好很多。
需要注意的是,只有标记为”ReflectionProbe Static”的对象才会被反射探头取样,从属性接口上静态对象(Static)的下拉选单打勾即可,相反的,实时的反射探头会对所有可见的物体取样,除非你在屏蔽(Mask)选单指定剔除它。
照亮一个场景(LIGHTINGA SCENE)
我们已经介绍了一些在Unity里针对场景照明开始工作之前所需要考虑的条件,希望你对目标平台该用哪些设定已经有了一个方向(手机平台采用烘焙GI和Gamma颜色空间,PC或游戏机采用实时GI和Linear颜色空间),接下来让我们来看看有哪些协助制定光源的工具。
定向光源(DIRECTIONALLIGHTS)
“定向光”非常适合用来模拟阳光,使用定向光不用考虑距离,只有旋转会影响定向光的照射结果。
旋转预设的定向光会导致天空盒也跟着更新,如果光的角度和地面平行就可以做出日落的效果,把光源转到天空导致变黑就能做出夜晚的效果,从上往下照就会模拟日间的效果。如果天空盒有指定为环境光源(Ambient Source),那么天空盒的颜色就会影响环境里面的对象。
点光源(POINT LIGHTS)
点光源可以想象是在3D空间里一个对着所有方向发射光线的点,很适合用来制作像是灯泡, 武器发光或是从物体发射出来的爆炸效果,点光源的亮度从中心最强一直到范围属性(Range)设定的距离递减到0为止,光的强度从光源到距离成反比,这是所谓的”平方反比定律”,类似光在现实世界的行为。
点光源开启阴影运算是很耗效能的,因此必须谨慎使用,点光源的阴影为了要给六个不同的世界方向会运算六次,在比较差的硬件开启此功能会造成较大的效能负担。
当在场景中加入点光源时要注意,目前它们不支持阴影的间接反射,这代表由点光源产生的光线,只要在距离内有可能会穿过对象反射到另外一面,这可能会导致墙壁或地板”漏光”,因此放置点光源要格外注意,然而如果是采用Backed GI的话,就不会有这类的问题产生。
聚光灯(SPOTLIGHTS)
聚光灯有许多用途,他们可以用来模拟路灯, 壁灯,或许多创意用法,例如模拟手电筒,因为投射区域能精确的控制,因此很适合用来模拟打在角色身上的光或是模拟舞台灯光效果等等。光线会因为离源头越远而递减,可以注意到光也会因为越靠近锥体边缘而变弱,我们称之为半影区,这会因为锥体角度变大而更明显。和点光源一样,使用预计算GI时,聚光灯不支持间接光阴影,这表示灯光会穿过几何影响到另外一面,因此放置投射灯要特别注意。
区域光(AREA LIGHTS)
区域光可以当作是摄影用的柔光灯,在Unity里面他们被定义为单面往Z轴发射光线的矩形,目前只能和烘焙GI一起使用,区域光会均匀的照亮作用区域,虽然区域光没有范围属性可以调整,但是光的强度也是会随着距离光源越远而递减。
区域光用在建立柔和的照明效果非常有用,光线在任何方向穿过光的表面时会产生不同方向的折射 - 造成在对象上产生漫反射,常见的用途是拿来当作天花板壁灯或是背光灯,为了实现这功能,我们必须从每个光照贴图像素上发射一定数量的光线,背对着区域光以确定光有能见度,这代表区域光的计算是消耗很大的,而且会延长烘焙的时间,但如果运用得宜可以增加场景光的深度,那么消耗就很值得,值得注意的是区域光只能用在烘焙,因此不影响游戏效能。
发光材质(EMISSIVE MATERIALS)
虽然区域光不支持实时GI,Unity提供另外一个柔和的灯光效果叫做发光材质(Emissive Materials),和区域光一样,发光材质可以让物体表面发光,他们可以反射场景内像是颜色或是光强度等等能在游戏内改变的光源,自发光(Emission)是一个在标准着色器(Standard Shader)内的属性,允许静态对象成为一个发光体,预设情况下是0,代表指定了这个材质并不会有任何的自发光反应,HDR颜色选择器能指定发光颜色,强度能在0-1的范围调整,来建立类似区域光的效果。
发光材质并没有范围属性,但从材质发出的光会以二的次方速度递减,自发光材质只会作用在有标记为”Static”或”LightmapStatic”卷标的对象,同样的,如果发光材质附加在非静态对象或像是角色的动态对象则不会有任何作用。
然而,材质设定只要emission数值大于0,即使他们不接收场景光源在画面上也会有发光的效果,这种效果也可以透过将emission属性底下的”Global Illumination”改为”None”,像这样的自发光材质很适合来模拟霓虹灯等类似的光源。
发光材质只会影响场景内的静态对象,如果你想要影响像是角色的动态对象,就必须采用光探头系统(Light Probes),在游戏周期改变发光材质的值会更新光探头取样,并直接在结果上看到变化。
光探头(LIGHT PROBES)
静态对象只被Unity全局光照GI系统计算,为了使动态对象能够和静态场景接收到的光影信息互动,我们需要纪录这些光的信息并做成可以在执行期间快速存取的格式。我们在场景放置许多取样点来截取各个方向搜集来的信息,颜色信息会被编成能在游戏中快速被取出的一组数值(或系数),这些取样点我们称为”光探头”。
使用了光探头的场景,注意图中光探头放置位置在光线容易变化的地方,例如阴影或是颜色转换的地方。
光探头允许移动对象接受由全局光照GI所计算出来复杂的反射光源,对象在著色网格的时候会判断附近光探头的位置并且把光的信息一并融合计算,这是透过找寻由光探头所产生的一个四面体,然后决定哪个四面体的落入对象的轴向,这样就能让场景内的动态对象正确地接受光信息,如果没有放置光探头,动态对象就无法接受全局光照的信息,造成动态对象比场景还要暗。
预设的情况下,场景是没有任何光探头的,你必须从GameObjects->Light->LightProbe Group自行建立光探头群组。假如全局光照里的Auto是打勾的(Lighting->Scene->Auto),当光源或是静态对象更新时,光探头信息也会实时更新,没打勾的话必须点Build运算才会更新。
Unity全球官方网站,原文:UNITY 5 - LIGHTING AND RENDERING
Unity 5 中的全局光照技术详解(建议收藏)