Unity中的光照类型
1、前言Unity目前支持四种光源类型:点光源(Point Light)、平行光(Directional Light)、聚光(Spot Light)和面光源(Area Light),其中前三种光源类型,在Unity的内置管线和URP管线都可以支持实时(RealTime),面光源仅支持烘焙(baked only);在HDRP管线中,所有光源类型都是可以支持实时的。本文重点介绍不同类型光源的特点以及衰减原理,至于其各自光源的属性部分,可以在编辑器里面查看或者阅读unity官方文档的介绍。
2、平行光
平行光
1)特点
平行光的行为方式与太阳类似,可以理解为是存在无穷远处的光源,其是没有位置属性的概念的,可以放在场景中任何位置,场景中所有物体都会被照亮,而且灯光的方向始终是相同的(这也是被称为平行光的原因)。关于平行光的方向问题,平行光的方向是由其旋转属性(transform.rotation)决定的,灯光沿其局部Z轴照射。unity场景中的光照数据都是保存在剔除结果中的,我们可以通过cull.visibleLights访问到,具体代码诸如:
CullResults cull;
VisibleLight light = cull.visibleLights;
Vector4 v = light.localToWorld.GetColumn(2); // localToWorld矩阵的第三列定义了变换后的局部Z方向向量,通过索引2访问 2)衰减原理
平行光是没有衰减这一说的,因为其位置是无穷远处的,无法计算光照向量,因此游戏中都不考虑平行光的衰减问题。注意,真正的物理世界里面,平行光也是有衰减的,比如太阳照射到火星的能量就跟照射到地球的能量不一样,但是显然考虑这样的因素在游戏里面是不太合理的,因此游戏和渲染中可以忽略平行光的衰减。
3、点光源
点光源
1)特点
点光源是有位置属性的,位于空间中某个点并向所有方向(球面空间)上均匀的发出光,光照向量是由片段位置指向光源位置的一个向量,其光照强度随着被照对象与灯光的距离增大而减小,并在指定范围内(具体范围是多大,由光照的Range属性决定)达到零。点光源的光强与光源距离的平方成反比,这被称为“平方反比定律”,与光在现实世界中的行为类似。
2)衰减原理
点光源的衰减原理遵循"平方反比定律",关系形如 i/d^2 ,其中,i是光强,d是光源和片元的距离。事实上,由表达式可知,当d接近于0时,这个时候光照强度会变得无穷大,这在现实生活中明显是不真实的,当然unity也考虑到了这个问题,在旧版本中,unity其管线中使用的衰减公式为 i/(1+d^2) ,使用这个公式可以解决刚刚提到的问题,但是又会引入一个新的问题:当片元离光源很近时,光照看起来并不是很真实(偏暗)。这没有很好的办法,其实是一个tradeOff的问题。
两个衰减公式的差异
点光源还有个重要的属性,就是光照范围,其也会影响到光照的衰减,在其光照影响范围之外的物体将不会受到点光源的影响。刚刚上面提到的衰减公式并没有考虑到光照范围对光强衰减的影响,在较新的unity版本中,其目前使用的衰减公式为: (1(d^2/r^2)^2)^2, r 为Light Range, d 仍然是光源和片元的距离,这是一个比较科学的衰减公式,其曲线大致为
衰减曲线
4、聚光
聚光
1)特点
聚光的工作原理跟点光源十分类似,除了聚光的照明区域会被限制在某个角度范围内,从而形成锥形的照明区域。值得一提的是,也跟平行光类似,聚光照明也是沿着其局部Z轴的(The center of the cone points in the forward (Z) direction of the light object)。锥形区域的覆盖角度(Angle)一般是小于180°的一个正值,聚光的光强在边缘会随着锥形区域角度的增加而衰减,角度越大,fade的区域也就越大,这就是所谓的“半影”(penumbra)。
2)衰减原理
一个片元是否被聚光影响,取决于聚光方向向量和光照向量之间的关系,前者获得的方式跟平行光类似,可以通过cull访问到,后者的话,可以通过片元位置跟光源位置的向量求得。上面提到了,聚光是有一个覆盖角度属性的,当这两个向量之间的夹角小于等于覆盖角度的一半时,那么该片元就会收到聚光的光照影响。聚光的衰减是按照角度平滑的衰减的,即Angle Falloff,聚光的衰减是从内角(inner spot angle)开始,并在外角(outer spot angle)处光强降为0。我们在unity编辑器里面配置的角度属性是outer angle,inner angle我们是没有办法配置的,但是内角和外角是有一个假设关系的,即 tan(ri)=46/64*tan(ro) ,其中 ri 是内角, ro 是外角,二者都是用弧度来表示的,根据这个关系,我们可以由外角来求出内角。
unity内置管线里面是用Light Cookie来做聚光光照衰减的,在可编程管线里面,是基于上述的内角与外角的假设关系来做衰减的,具体的衰减公式为: (Ds*Dl-cos(ro))/(cos(ri)-cos(ro)) ,其中DsDl是聚光方向向量与光照向量的点积,其大致的衰减图像为
5、面积光
Unity的内置管线和URP管线都不支持实时的Area Light,一般仅仅用在光照贴图的烘焙中,这里就不多说了,当然HDRP管线里面是支持实时的面光源的,移动端游戏基本上用不到,有用到了可以再补充。
6、其他
Unity目前场景里面最多可以支持16盏可见灯光,当更多的灯光出现在场景中时,unity会按照灯光的重要性排序,排在后面的灯光(重要性低的)将会被舍弃,具体的影响灯光重要性的因素有很多,比如光源类型、光照强度、是否投射阴影以及用户对灯光的其他配置等等,灯光重要性计算公式可以参考
页:
[1]