环境光(ambient)

除了直接光照,物体也可以被间接光照照亮,间接光照是光线经过多个物体之间反射,最后进入摄像机。在标准光照模型中,我们用环境光近似模拟间接光照。环境光计算简单,通常是一个全局变量,场景中所有物体都使用这个环境光。下面等式是环境光的计算:

cambient=gambient

自发光(emissive)

这部分用于描述给定一个方向时,一个表面会向该方向发射多少辐射量。注意,如果没有使用全局光照技术,这些自发光表面不会真的照亮周围物体,只是本身看起来更亮了而已。光线直接由光源发射进入摄像机,而不需要经过任何物体的反射。计算很简单,直接使用该材质的自发光颜色:


cemissive=memissive

漫反射(diffuse)

这部分是我们研究的重点,漫反射中,视角的位置是不重要的,因为反射方向是随机的,所以可以认为在任何方向上反射分布都是一样的。但入射光线的角度很重要。漫反射有以下两种模型:

  • 兰伯特定律(Lambert’s law):反射光线的强度与表面法线和光源方向之间的夹角的余弦成正比。公式如下:
•   cdiffuse=(clight∗mdiffuse)max(0,n^∗I)

n^是法线 ; I是指向光源的单位矢量; clight是光源颜色; mdiffuse是材质的漫反射颜色。
注意,我们需要防止法线和光源方向点乘的结果是负值,所以用了max函数。

  • 半兰伯特光照模型:这个模型,在之前的兰伯特模型的基础上,把n^∗I的结果范围从[−1,1]映射到[0,1]范围内,它是为了防止物体的尾部失去其形状以及防止看起来过于平坦,公式如下:
•  
  cdiffuse=(clight∗mdiffuse)(0.5(n^∗I)+0.5)

为便于理解我找了一张两种模型差异的图,左边是 Lambertian lighting, 右边是Half Lambert lighting

unity UI流光shader_光照

高光反射(specular)

它主要用于表现完全的镜面反射。但这里的高光反射是一种经验模型,它并不完全符合真实世界的高光反射现象。而高光反射的模型有以下两种

  • Phong模型
    计算高光反射需要知道法线、视角方向、光源方向、反射方向等。下图给出了这些方向矢量:

    当然我们知道前三个即可,反射方向可以根据前三个算出来,公式为:

r=2(n^∗I)n^−I

  • 这样,我们可以用Phong模型计算高光反射:

cspecular=(clight∗mspecular)max(0,(v^∗r)mgloss)

mgloss是材质的光泽度(gloss),用于控制高光区的两点有多大,值越大,亮点越小。
mspecular是材质的高光反射颜色。
clight是光源的颜色。同样,也要防止v^∗r是负值。

  • Blinn模型

    Blinn提出了一个简单的修改方法来得到类似的结果。如上图所示,基本思想是避免计算反射方向r,为此Blinn模型引入一个新矢量h^,它可以通过v^和I的取平均后再归一化得到。即

h^=v^+I|v^+I|

  • Blinn模型公式如下:
cspecular=(clight∗mspecular)max(0,n^∗h^)mgloss
  • 这两种模型都是经验模型,所以也不能说哪个更优,在一些情况下,Blinn更符合实验结果。

逐像素or逐顶点

在顶点着色器中计算这些公式,叫逐顶点光照,在片元着色器中计算,叫逐片元光照
逐片元光照中,我们以每个像素为基础,得到它的法线(可以是顶点法线插值得到的,也可以是法线纹理采样得到的),然后进行光照计算。这种在面片之间对顶点法线进行插值的技术被称为Phong着色(Phong shading)
逐顶点光照也被称为高洛德着色(Gouraud shading),逐顶点光照中,我们在每个顶点上计算光照,然后会在渲染图元时进行线性插值,最后输出成像素颜色。由于顶点数目往往远小于像素数目,因此逐顶点光照的计算量往往小于逐片元光照。但逐顶点光照是线性插值出来的,当光照模型中有非线性计算(例如计算高光反射)时,逐顶点光照会出问题。而且对顶点颜色的差值也会使图元内部的颜色总是暗于顶点处的颜色,会有可能产生明显的棱角现象。