第一讲我们先用Shader实现一个最基础的光照模型。固定管线中的3D光照在DX9的龙书中已经介绍的很详细了,但是一旦换成可编程流水线,许多光照算法的实现都要用Shader自己来写,这部分的公式龙书并未详细给出,因此有必要在这里小讲一下。如果这些内容你之前已经掌握了,那本章就当作一个回顾吧,因为接下来的几章内容都会以此光照模型为基础。
光照的组成:
我们都知道,D3D中把光分为环境光、漫反射光、镜面光。计算一个顶点的颜色,就是将这三种类型的光加起来。环境光是最简单的,只需要简单的加上去就可以了。漫反射光稍微复杂一些,它与光线的入射方向,以及顶点法线都有关系,计算公式如下:
衰减系数:k = saturate(cosθ) = saturate(dot(DirToLight, normal));
则顶点处的漫反射光颜色:DiffuseColor = LightColor * k;
其中DirToLight是由顶点位置指向光源位置的向量,注意需要把它化成单位向量。normal是该顶点的法线向量,同样也是一个单位向量,角θ就是这两个单位向量之间的夹角。很显然,这个角越小,顶点能吸收的光的强度越强。这里,将光线的颜色,乘以cosθ,就得到了该顶点能接收的光的强度,而cosθ呢
镜面光相比前两种光,其计算更加复杂。它不仅与光线方向和法线方向有光,而且与视点所在位置也有关系。如果能反射入我们眼睛的光线越多,当然我们看起来物体就越亮。镜面光的计算公式如下:
图中的所有向量都已经化成了单位向量,其中点A就是顶点所在的位置。向量AS就是顶点位置指向光源位置的向量,即DirToLight,向量AE是从顶点位置指向视点位置的单位向量,AN就是顶点的法线,AB这条线比较特殊,它相当于∠EAS的角平分线,同样也是一个单位向量,它的计算方式并不复杂:
AB = normalize(AE + AS)
即将AE和AS两个单位向量相加,根据向量加法的平行四边形法则,则得到的就是∠EAS角平分线