通常来讲,想要模拟真实的环境光照来生成一张图像需要考虑这样一种流程:首先,光线从光源中发射出来;然后,光线和场景中的一些物体相交,其中一部分光线被吸收,一部分被散射;最后,摄像机吸收了一些光,产生了一张图像。

光源

在实时渲染中,光源可以看作是一个没有体积的点,用l表示其方向,用辐射度(irradiance) 来量化。比如平行光,其辐射度可通过计算在垂直于l的单位面积上单位时间内穿过的能量来得到。而计算物体表面的辐射度,可以利用光源方向l和表面法线n之间的夹角的余弦值来得到。(ps. 方向矢量默认模长为1)。实际计算中,辐射度与cosθ成正比,所以使用点积来计算。

吸收与散射

光源与物体相交的结果有两个:散射吸收。散射只改变光线方向,不改变光线密度和颜色,而吸收相反。光线在物体表面的散射又分为折射(或说透射)和反射两种。光照模型中,高光反射属性表示物体表面的反射,漫反射属性表示物体表面的折射,吸收和散射。出射度用来描述出射光线的数量和方向。辐射度与出射度的比值也就是材质的漫反射和高光属性。

着色

着色是指根据材质属性,光源信息,使用一个等式去计算沿着某观察方向的出射度的过程。此等式就是光照模型(Lighting Model).

BRDF光照模型

BRDF全称Bidirectional Reflectance Distribution Function。当给定模型表面一个点时,BRDF包含了对该点外观的完整描述。在给出入射光线和辐射度时,BRDF可以给出在某个出射方向上的光照能量分布。由于它是理想和简化后的模型,它并不能真实反映物体和光线的交互,故作为经验模型。 此时不得不说一句计算机图形学第一定律:如果它看起来是对的,那么它就是对的。

标准光照模型

标准光照模型的基本方法将进入到摄像机内的光线分为4部分:

  • 自发光(emissive):描述当给定一个方向时,一个表面本身会向该方向发射多少辐射量。
  • 高光反射(specular):描述当光线从光源照射到模型表面时,该表面会在完全镜面反射方向上辐射出多少辐射量。
  • 漫反射(diffuse):描述当光线从光源照射到模型表面时,该表面会向每个方向散射多少辐射量。
  • 环境光(ambient):描述其他所有的间接光照。

环境光

间接光照是指光线在进入摄像机之前经过了多次物体的反射。在标准光照模型中,使用一种被称为环境光的部分来近似间接光照。

自发光

自发光是指光线没有经过任何反射之间进入到摄像机中。标准光照模型使用自发光(颜色)来计算这个部分的贡献,但该物体并不被当成一个光源,去照亮周围的其他表面。

漫反射

漫反射光照符合兰伯特定律(Lambert’s Law),反射强度与表面法线和光源方向之间的夹角的余弦值成正比

高光反射

高光可以使得物体具有金属的材质。一般采用Phong模型或者Blinn模型去计算,其中Blinn模型在摄像机和光源距离够远时会快于Phong模型。两者都是经验模型

逐像素/逐顶点

通常来讲,在片元着色器中计算光照被称为逐像素光照,而在顶点着色器中计算被称为逐顶点光照。逐像素光照以每个像素为基础得到其法线,然后计算光照模型,又称Phong着色(Phong Shading,不同于Phong光照模型)。逐顶点光照又称为高洛德着色,它在每个顶点上计算光照,在渲染图元内部进行线性插值,输出成像素颜色。很显然其计算量小于逐像素着色,但由于使用线性插值,将导致明显的棱角现象。

参考

Unity_Shaders_Book : https://github.com/candycat1992/Unity_Shaders_Book

Unity Scripting Reference : https://docs.unity3d.com/ScriptReference/index.html