Date: 16 Aug 2015
在3D游戏中,很多时候游戏是对现实自然环境的一种模拟,这种模拟当然也少不了对光照的模拟,因为没有了光照,就什么都看不见了,游戏也就无从谈起了。最近看了几篇有关 Unity 引擎中光照的教程。这些教程虽然是依据 Unity 引擎写成的,但其中一些关于光照的原理是比较通用的,所以在这里总结一下。
简单来说在 Unity 中光源可以分为两类,一是定向光源,二是点光源。然后这两种光源又可以根据他们的数量分为单一的和多重的。
定向光源有点像是物理学中的平行光,在这种情况下光在反射面上的毎一点的入射角度都是相同的。而且定向光源的强度是不会衰减(attenuation)的。
点光源中「光线」都是从同一个点发射出来,所以在反射面上点的光的入射角度会不一样,这个角度可以通过入射点和光源之间的向量来计算。而且点光源的光的强度会随着距离的增大而衰减的。
在 Unity 中光反射的模拟并不是简单的去计算反射光的角度(这也是我一开始的误解),而是通过入射光和反射表面的相关参数去模拟经过光源照射后模型表面的视觉变化。下面就来说一下常见的两种光反射的模拟。
漫反射也叫做 Lambertian 反射,它是用来表示光线照射在物体粗糙的表面后会无序地向四周反射的现象。这种反射在日常生活中很常见。在漫反射模拟中我们并不关心光的反射角度,而需要关心的是反射光的强度,因为我们之所以能够看到现实世界中的物体也是因为这些物体把光反射到了我们的眼睛里。再回忆一下以前学过的物理知识我们就可以知道反射光的强度与其入射角有关,入射角度越大反射光强度越小,反之亦然。那么入射角度和反射光之间的关系可以用入射角的余弦值(consine)来表示。最终反射光的强度可以通过下面这个公式进行计算。
N 为反射面法线的方向向量,L 为入射光的方向向量;K 为常数,表示反射平面的反射系数,黑色平面为0,白色平面为1。
在定向光源下直接使用这个值和模型表面颜色的进行相关的计算就可以模拟漫反射了。但是在点光源中由于光的强度会有所衰减,所以这个值还要乘以衰减程度的值才能用于漫反射模拟。
局部高光是这样一种现象:物体在阴影中的部分并不会是完全看不到的,而且有的部分反而会变得更亮。产生这种现象的原因是:在阴影中的这些部分虽然没有被光源直接照射到,但是周围物体反射的光(环境光,Ambient Light)会照射到它,这样这些部分也变的可见了。在 Unity 中有内置的变量 UNITY_LIGHTMODEL_AMBIENT.rgb
来表示环境光,因此我们也可以来模拟局部高光。
局部高光可以用 Phong 反射模型来实现:
其中:R 为反射光向量,V 为反射点到视点的向量;然后 K 和 n 都是关于模型表面材质的常量。同样如果是点光源的话,还需要考虑入射光的衰减。
需要注意的是无论是漫反射还局部高光都不是单独存在的,一个完整的光反射模拟应该是由漫反射、环境光和局部高光这几种现象的模拟共同完成的。