一些常用术语

直接光:光线直接或者经过一次反射进入我们的视野
间接光:光线经过多次反射进入我们的视野
逐像素光:一个像素一个像素处理光照计算
逐顶点光:一个顶点一个顶点处理光照计算,这个相对逐像素处理比较节省性能,因为顶点会经过光栅化产生更多的像素,顶点

Type

directionalLight:平行光,模仿世界中的太阳光
spotLight:聚光灯,由一个点发出一个光,形成一个椎体
pointLight:点光,由一个点发出的光,形成一个球体

Range

这里指的是聚光灯椎体的高度或者点光组成的球体半径,此值越大,说明光的照射范围越大

spot angle

这个指的是聚光灯的椎体张开的角度,此角度越大,表明椎体的张开范围就越大

color

指的是光发出的颜色

Mode

1)、Realtime实时
Unity 在运行时每帧计算并更新实时灯光。没有预先计算实时灯光。

2)、Mixed混合
一种提供烘焙和实时功能的混合模式,例如对灯光的间接照明进行烘焙,同时对直接照明进行实时计算。场景中混合模式灯光的行为和性能影响取决于我们全局混合照明模式的选择。
Mixed Lights下的子模式:Baked Indirect、Shadowmask、Distance,Shadowmask、Subtractive。

3)、烘焙
Unity 在运行之前预先计算Baked Lights 的光照,灯光的直接和间接照明被烘焙成光照贴图。设置为该模式后,该灯光在程序运行时将不占用性能成本,同时,将生成的光照贴图应用到场景中的成本也较低。

intensity

光照强度

RenderMode

分为Auto,Important和Not Important模式。

Auto模式:
根据Quality Setting和光照强度,选择顶点光计算模式或像素光计算模式。

Important模式:
光线总是对每像素进行光照计算。(像素光)

Not Important模式:
光线总是以更快的渲染方式,对顶点进行光照计算。(顶点光)

shadow type

投影的类型
no shadow:不开启阴影
hard shadow:硬阴影,边缘锯齿会比较明显,当相对消耗较少资源
soft shadow:软阴影,锯齿处理的比较好,阴影柔和真实,但是会消耗较多资源,而且一般手游也不会使用实时阴影.

Light map

对一些静态物体的光照预先计算存储,这个过程叫baking(烘焙),baking的结果就是一张light map的贴图。
生成光照贴图的过程:
第一步:将光的Mode设置为Baked
第二步:将场景中不动的物体设置为静态
第三步:默认情况下,unity已经启动了烘焙工作,此时正在为你生成一张光照贴图
第四步:贴图生成完毕,可以运行游戏看一下

Unity光照处理

静态物体与静态物体之间的光照,可以用light map烘焙。
动态物体在静态物体下的光照,可以用Light Probe渲染。
动态物体与动态物体之间的光照,Unity不支持。

Light Probe(光探测器)

模拟全局光照,让动态物体得到静态物体的间接光照。预先在场景中,布置一些光探测器,在预处理阶段,把静态物体的光照信息存储下来,当动态物体经过探测器时,探测器根据预先储存的周围的光照信息,对动态物体进行重新的光照贴图。

探测照明通过3D空间中的探头对入射光进行采样并将这些信息通过球谐函数编码处理后保存成文件。这些信息占用的存储空间很少并且在运行时解码非常快。场景中的Shader可以使用这些信息来模拟物体表面的光照。

Reflection Probe(反射探测器)

用来模拟高反射物体表面对周围的实时发射。预先在场景中,布置一些反射探测器,对静态物体启用Reflection probe Static,在预处理阶段,把静态物体的反射光照信息存储下来,当动态物体经过探测器时,探测器根据预先储存的周围的反射光照信息,对动态物体进行重新的光照贴图。

Unity光照策略

烘焙的全局光照(Global illumination)和局部的实时光照

static的物体采用烘焙
非static的物体采用实时的局部光照
light mode采用Mixed模式
开启baked gi,关闭realtime gi

全局光照(Global illumination)

全局光照指的是模拟光线是如何在场景中传播的,不仅会考虑哪些直接光照的结果,还会计算光线被不同物体表面反射而产生的间接光照。

顶点光

顶点的光照颜色和强度信息,使用每个顶点的法线向量与光照方向之间的夹角的余弦值来得到。顶点之间点的光照,用插值计算的方式,计算出来。

像素光

为每个像素点计算光照。计算两个顶点的法线向量,然后插值计算出两个顶点之间每个像素点的法线向量,每个像素点的法线向量与光照方向分别进行几何运算,得到像素点的光照颜色和强度信息。

阴影产生原理(Shadow Map)

首先把摄像机的位置放在与光源重合的位置,那么场景中该光源的阴影区域就是那些摄像机看不到的地方。在前向渲染中,如果场景中最重要的平行光开启了阴影,Unity就会为该光源计算它的阴影映射纹理(shadowmap)。这张阴影映射纹理本质上也是一张深度图,记录从光源出发得到从该光源处观察到的深度纹理。

Unity选择使用了一个额外的Pass来专门更新光源的阴影映射纹理,这个Pass就是LightMode标签被设置为ShadowCaster的Pass。这个Pass渲染目标不是帧缓存,而是阴影映射纹理(或深度纹理)。

传统的阴影映射纹理技术

在正常渲染的Pass中把顶点位置转换到光源空间下,以得到它在光源空间中的三维位置信息。然后,使用xy分量对阴影映射纹理进行采样,得到阴影映射纹理中该位置的深度信息。如果该顶点的深度值(通常由z分量得到)大于阴影映射纹理中该位置的深度值,那么说明光源无法照到,该点在阴影中。

屏幕空间的阴影映射技术

在Unity5中,Unity采用不同于传统的阴影映射纹理技术,即屏幕空间的阴影映射技术(Screenspace Shadow map)。需要注意,屏幕空间的阴影映射需要显卡支持MRT(Multiple Render Target,多重渲染目标,GPU允许我们把场景同时渲染到多个渲染目标纹理中),需要OpenGL ES 3.0,Metal支持。
当使用了屏幕空间的阴影映射技术时,Unity首先会调用LightMode为ShadowCaster的Pass来得到光源的阴影映射纹理以及摄像机的深度纹理。
然后,根据光源的阴影映射纹理和摄像机的深度纹理来得到屏幕空间的阴影映射纹理。
把每一个像素根据它在摄像机的深度纹理值得到在世界空间的坐标,再把它的坐标从世界空间转换到光源空间中,和光源的ShadowMap中的深度值对比,如果大于ShadowMap中的深度值,那么说明光源无法照到,处于该光源的阴影中。
这样,屏幕空间的阴影映射纹理就包含了屏幕空间中所有有阴影的区域。如果我们想要一个物体接收来自其他物体的阴影,只需要在Shader中对屏幕空间的阴影映射纹理进行采样。由于屏幕空间的阴影映射纹理是屏幕空间下的,因此,我们需要把表面坐标从模型空间转换到屏幕空间中,然后使用这个坐标对屏幕空间的阴影映射纹理进行采样即可。

物体接收来自其他物体的阴影

如果我们想要一个物体接收来自其他物体的阴影,只需要在Shader中对屏幕空间的阴影映射纹理进行采样,把采样结果和最后的光照结果相乘来产生阴影结果。

物体向其他物体投射阴影

如果我们想要一个物体向其他物体投射阴影,就必须把该物体加入到光源的阴影映射纹理的计算中,从而让其他物体在对阴影映射纹理采样时,可以得到该物体的相关信息。在Unity中,这个过程可以通过为该物体执行LightMode为ShadowCaster的Pass来实现,还会在这个Pass中产生一张摄像机的深度纹理。

着色器替换技术(Shader Replacement)

使用着色器替换技术选择那些渲染类型(即SubShader的RenderType标签)为Opaque的物体,判断它们使用渲染队列是否小于等于2500(内置的Background、Geometry和AlphaTest渲染队列均在此范围内),如果满足条件,就把它渲染到深度和法线纹理中。

Shadow Castcade

Shadow Castcade,就是远处的阴影用分辨率比较小的贴图,近处的阴影用分辨率比较大的贴图,提升了近处阴影的质量,但增加了性能开销。

Shadow Distance

超出此距离的物体(来自相机)不投射阴影,因为远处的对象不需要渲染到阴影贴图中。将阴影距离设置的尽可能低,可以提高渲染性能。

实时阴影

实时为每个顶点计算法线向量,与光照方向进行几何运算,然后得到这个顶点的颜色。

Halo:模拟Point light周围的光晕

Lens Flare:模拟真实镜头中的太阳光斑,通常放在太阳的位置

Light的性能优化
实时光源越少越好,甚至不用实时光
利用离线烘焙,light mapping
Spotlight(聚光灯)开销很大,少用
限制像素光的数量
Culling Mask 在不需要进行光照计算的层,取消勾选
谨慎使用实时阴影
尽量用Hard Shadow
减少Shadow Distance
不用Shadow castcade