赞
踩
游戏场景的灯光无疑非常重要的,其不仅起到照亮场景的作用,好的灯光更能渲染气氛,使游戏效果更加逼真。然而又不能滥用灯光,因为灯光,阴影等会消耗大量的性能,造成游戏的卡顿,内存消耗太大等问题。因此掌握Unity中灯光,活用灯光非常关键。
对现实生活中光线的反射,折射,衍射等特性的模拟,一直以来都是计算机图形学的重要研究方向。在漫长的发展过程中,出现过很多很多计算方案,总体有这几种:
前两种方式计算量非常大,往往需要很长时间进行渲染,很难应用在游戏设计领域,在游戏设计领域,光照贴图技术依旧是主流方式。
在Unity中灯光属于直接照明(Direct Lighting),灯光本质都是空物体加上灯光组件。直接照明可以产生阴影,但光线不会反射,折射,但可以穿透半透明材质物体。
在Unity中的灯光有:平行光,点光源,探照灯,面积光;此外,还可以创建两种探针(Probe):光照探针组(Light Probe Group,保存光照信息让物体有更真实的光照效果)和反射探针(Reflection Probe,在探头位置生成反射贴图,主要让场景有更好的反射效果)。
Range: 光线射出的范围,超过这个范围则不会照亮物体;
Spot Angle: 灯光射出的张角范围。
Width: 面积光的宽度。
Height: 面积光的高度。
在Unity的灯光中可以为该灯光产生的阴影设置不同的阴影类型,分为:无阴影(NoShadows),硬阴影(HardShadows),软阴影(SoftShadows,阴影模糊效果)。其本质都是使用阴影贴图模拟的阴影效果,而不是真实光照形成的暗色区域。
三种阴影模式,无阴影就是没有阴影,硬阴影边缘清晰,而软阴影边缘柔和,更加贴近现实生活中的阴影,同时计算消耗也会更大。灯光组件上的阴影参数会随着灯光照明模式(Mode)参数不同更改,下面详细说明每个属性的意义:
在属性设置中,Resolution的参数除了使用几个定好参数,也可以使用Use Quality Setting来在Quality面板中定义的。通过Edit->Project Settings->Quality打开Quality面板,在这里可以针对不同质量等级设定参数。
Quality面板才是各种渲染设置的最终决定者。不光只是用来设置阴影质量,渲染质量等也是在这儿进行设置。在这里只介绍其中的阴影设置:
Unity提供两种渲染路径:Forward和Deferred。
除了上面提高的直接照明外,还有间接照明:
当我们进入到生成的默认Unity场景里,会看到一个默认的天空盒,无论我们往什么地方移动周边的景色都没什么变化,彷佛广阔无边。实际上,是因为天空盒跟随着开发者相机移动的,故感觉天空盒广无尽头。
天空盒如同其名,就是一个正方形的稍微大一点的盒子,且贴图是在盒子内部,形成一个全景视图。因此,天空盒的六个面的贴图必须要求是无缝贴图3,这样从任何方向看都是一副连续的画面。
要设置一个天空盒,首先要创建一个材质Material,材质的Shader处有三种选择:
将自定义完成的天空盒在Window->Lighting->Settings中应用就完成了(下面和环境光一起讲)。
环境光(Environment Lighting)的来源(Source)有三种:Skybox, Color, Gradient。
环境反射(Environment Reflections)的来源(Source)也有两种:
Mixed Lighting设置:
Lightingmapping Settings: 当Mixed Lighting的Baked Global Illumination为false时,该模块许多功能会被禁用。
Lightmapper: 指定使用哪种计算方法来计算光照贴图,提供Enlighten和Progressive。Enlighten: 这是一种常用的烘焙计算方法;
Progressive: 一种新版的烘焙计算方法,它可以先烘焙摄像机可见区域,再烘焙其它区域,所以预览较快,其提供属性选项有:
Indirect Resolution: 用来指定间接灯光照明计算的每单位有多少纹素4,纹素越大,光照细节越高;
Lightmap Resolution: 全局光照产生的光照贴图每单位有多少纹素,通常设置为Indirect Resolution的10倍左右;
Lightmap Padding: 修正两个物体在光照贴图中的纹素间隔,以避免颜色渗透;
Lightmap Size: 指定生成的光照贴图大小,光照贴图为正方形贴图,边长最大4096纹素;
Compress Lightmaps: 是否压缩光照贴图,压缩的纹理可能会带来不需要的纹理效果;
Ambient Occlusion: 允许控制环境遮挡的表面亮度(计算像素亮度和场景中附近物体之间的关系,以确定何时阻止特定像素接收附近环境光),较高的值表示遮挡区和全亮区之间较大对比度,仅适用于由GI系统计算的间接照明;
Final Gather: 启用最终聚集时,会对最后一次GI光线反射后的光照结果再以与烘焙的光照贴图相同的分辨率进行一次FG计算。这将增加光照贴图的质量但增加烘焙时间。
Directional Mode: 提供Directional和Non-Directoinal两个选项,Non-directional为平面漫反射,只有一个光照贴图存储关于表面发出光的信息。在Directional模式下,会生成第二个光照贴图来存储入射光的信息,因此需要两倍的额外光照贴图数据存储空间,shader可以根据这些入射光信息更好的表现。但是定向光照贴图无法在SM2.0或使用GLES2.0时使用,它们将回退到非定向光照贴图。
Indirect Intensity: 间接光照强度,控制实时存储的间接光照和烘焙的间接光照贴图的亮度,默认1。
Albedo Boost: 反射率提高,控制场景中的材质反射率来控制表面间反射的光量,增加此值将以靠近白色5的反射率进行间接光照计算,默认1贴合实际物理现象。
Lightmap Parameters: 设置详细的光照贴图参数(有几个默认值,也可以创建新的参数)。
Other Setting:
Debug Setting:
上面的参数设定部分其实已经涉及到很多光照贴图方面的内容了,下面来讲讲具体如何进行光照贴图的烘焙(Baking)。光照贴图(Lightmap),其实就是使用贴图来模拟全局照明的效果。
光照贴图需要将所有参与的场景物体的UV重新排列组合成互不重叠且尽量少形变的方形结构,再把光照信息烘焙到一张或几张较大尺寸的贴图中。当所有场景物体放在同一个贴图时,那么一个多边形面片上的光照信息精度就受限于该多边形面片所对应的UV在贴图中所占据的面积大小。出于场景优化考虑,我们当然希望将有限的光照贴图面积尽量多的分配给更需要的物体,因此可以修改不同场景物体的MeshRenderer组件里的所占光照贴图比例的参数6。
当我们把上面Lighting面板中的参数设置完后(或者直接使用默认参数),就可以点击Generate Lighting按钮烘焙光照贴图了。烘焙好的贴图会被储存在场景文件所在目录下与场景文件同名的子目录中,因此烘焙光照贴图前需要保存场景。(如果选择了Auto Generate,则不会在同名子目录中保存光照贴图,需要手动烘焙)。接着就可以在Lighting的Global maps选项卡查看照明系统系统正在使用的实际纹理,包括强度光照贴图,阴影遮罩和方向性贴图;在Object maps预览当前选中的游戏物体的以烘焙贴图的预览。
天空盒的信息不可能包含所有场景信息,在很多时候,对象从天空盒收集的反射信息7可能会被遮蔽,向室内对象或隧道中。要准确反射这些对象,就需要用到反射探针。**反射探针从它们的位置对周围取样并把结果写到cubemap上,并让周围经过的物体得到环境的反射镜像。**反射探针越少越好。
使用反射探针产生的cubemap的游戏物体,其MeshRenderer需启用反射探针和一个着色器来支持。
烘焙的产生的光照贴图只能用于静态游戏物体,那怎么解决动态物体的光照信息问题呢?为了让动态物体也能够获得某个地点的光照信息,就需要将这些光照信息记录下来,并在运行时能快速读取和使用。
光照探针组就是为此设计的,通过在场景中放置采样点捕捉各个方向的光线信息,将这些记录的光照信息通过球谐函数编码处理后保存为文件,这些信息占用的存储空间很少且运行时解码速度很快。场景中的Shader可以使用这些信息来模拟物体表面的光照。
使用光照探针,需要注意的是不能将所有探头放在一个平面上,必须构成立体形状,这样是为了能够从物体的头部高度或更高的空中接收光照信息。为了提高光照探头的效率,应该在光照变化大的地方多放置探头,不大的地方隔较远距离放置探头。
光照探针运行耗费性能速度也快,在照明小的,凸起的物体上有很好的效果,但是,因为探针是采样计算光照信息,因此对复杂的照明效果很难表现;且每个位置只用一个球模拟,对大模型的光照效果可能不会太好。一个场景中有多个Light Probe Group时,Unity在运行时会自动将这些Group合并,并移除位置重复的Probe。光照探针的具体使用可以参阅这篇文章。
这一篇文章断断续续写了一两周,查询了许多资料,也拜读其它许多前辈的博客,但是即便如此,对于Unity中灯光方面,自我感觉还是存在许多的疑惑。也许需要真正在实践中尝试后,再来重读这篇文章才会有新的启发吧。
这里要特别感谢这几位大神的博客,可以说我的很多内容都是参阅他们的资料才写出来的,感兴趣的读者可以去阅读一下原文:
https://blog.csdn.net/weixin_42304838/article/details/82495272
https://www.jianshu.com/p/7594b044e6dc
有时候阴影贴图出错,比如无缘无故多出一条亮缝,通常可以切换到Close Fit来解决;或者适当降低灯光阴影参数中Normal Bias参数,或将场景物体设置为双面显示。 ↩︎ ↩︎
Shadow Cascades是一种阴影贴图算法,如我们选择四层级联(Four Cascades),那么实际上会计算4次阴影贴图,每次对应场景中距离摄像机一定范围内的物体;而该距离范围划分就通过Cascades Splits中所显示的紫,绿,黄,红四种颜色区域所占比例来划分;紫色代表最近区域,阴影贴图精度也是最高的。 ↩︎
当我们选择天空盒的贴图时,注意最好不要使用.jpg或.png这种传统8位色深的图片,除非不需要对场景进行环境光烘焙;若是需要的话,应选择高动态颜色深度的.hdr或.tif图片格式(也就是HDRI)。 ↩︎
纹素,纹理元素的简称,texel,是纹理图形的基本单位,常用于定义三维对象的曲面。3D对象曲面基本单位是纹理,2D对象由像素组成。3D纹理对象靠近观看时相对较大,每个纹素可能存在好几个像素;而相同的纹理对象被移到很远的距离时,会有每个纹素变得小于像素,然后几个纹素组合成一个像素。纹素甚至可以在观察图像中丢失。 ↩︎
在现实生活中,白色的物体会反射所有光线,黑色的物体会吸收所有的光线。 ↩︎
要想出来关于光照贴图参数的设置,要将该场景物体设置为Lightmap Static,可以通过游戏物体Inspector面板右上角的Static右边的下拉箭头设置或是直接勾选MeshRender组件中的Lightmap Static属性。 ↩︎
实际上天空盒的反射就是一个系统默认的大的环境反射探针。可以在Lighting -> Settings的Environment -> Environment Reflections里设置环境反射。 ↩︎
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。