【未完成】【GAMES101】lecture8 shading2笔记
这节课虽然内容相对比较浅,但是总量特别多,全部搞懂还是比较累的。
这节课内容涵盖了Blinn-Phong reflectance model的完整形式以及核心思想,着色频率,渲染管线等,下面逐个分析。
Blinn-Phong reflectance model
Blinn-Phong模型将每个着色点的反射强度计算分为三个部分:漫反射(Diffuse),镜面反射(Specular)和环境光(Ambient)。
尤其注意,Blinn-Phong模型实际上是个经验模型,是通过数学方法模拟现实中的物理行为,因此我们应该抱着"这个模型能不能模拟出现实里的规律"的态度对待它。
请注意,下面所涉及到的向量,若无特殊说明皆为单位向量。
漫反射(Diffuse)
如下图,漫反射项 L_d的计算旨在模拟以下几个因素:
漫反射系数 k_d:通常是一个RGB向量,表示当前材质在不同颜色通道下反射光线的能力。取决于材质本身的性质(最重要)、表面粗糙度等等,比如金属的 k_d通常较小,粗糙的表面 k_d通常较大。
光线能量衰减 \frac{I}{r^2}:光照以球形向外发散衰减,数学上可以认为其与表面积成正比,因此除去常数后的形式就是 \frac{I}{r^2}。
角度对能量接收的影响 max(0,n \cdot l):反射出去的能量比例。这是个很直观的结果,表示入射光与法线夹角越小,能量越大。
漫反射是非常均匀的,在任何方向上观察的结果应该都是一样的。因此图中的观察向量v只是一个示例,对结果没任何影响
上面对公式中的各个项做了解释,可以发现它们非常不严谨,这样真的效果会好吗?事实上这种形式的Blinn-Phong模型确实不太精确,但它仍然可以一定程度模拟出现实反射的效果。
在电脑中渲染一张图片,我们需要的是正确的视觉效果,而不是与真实世界一模一样的物理规律。因此,我们的重点在于哪些因素会影响反射的强度,以及如何模拟它。
光线能量衰减项 \frac{I}{r^2},显然真实世界中绝对没有这么简单,这个公式理论上是这样推导的:
也就是说,最核心的部分是 I_d \propto \frac{I}{ r^2},只要实现这部分,光照衰减的速度就合理了,分母中的常数并不影响模拟。如果模拟的效果不理想,我们可以统一为所有材质的 k_d做修正,让它负责弥补省略常数所带来的误差。k_d 还能容纳很多这样的修正,因为这种误差对所有材质都是同等的。
镜面反射(Specular)
镜面反射项就更工程了,因为镜面反射在真实世界中的规律更复杂:
镜面反射和漫反射的形式很像,它们最大的不同是对角度的处理方法不同。
镜面反射在视觉上几乎全部以高光的形式体现,因此镜面反射只需要处理好高光即可。而高光是一个非常集中、与观察方向高度相关的视觉效果。入射角度对高光的影响非常小。具体而言:
就算是非常倾斜的入射角度,只要观察方向与出射方向接近,高光仍然会非常亮
就算是近乎直射的入射光,如果观察方向偏离太多,仍然无法看到明显的高光。
所以在Blinn-Phong模型中直接省略了入射角度对镜面反射的影响,我们只需专心处理好最重要的观察角度v。
如何衡量观察角度的影响?
再次强调,Blinn-Phong模型是一种经验模型,我们的目标是模拟出现实世界的效果。现实中,如果观察方向与出射方向重合,此时显然是高光最明显的位置;当观察方向偏离出射角度,高光自然就会变淡。因此我们得出第一个简单的规律:观察方向v与出射方向R的夹角越大,镜面反射越弱。
自然而然我们想到了通过余弦函数模拟这个效果: max(0,v \cdot R) ,这就是最初的Phong模型所采用的方式。
而Blinn-Phong模型在这个基础上做了计算上的优化。Phong模型中的计算方式需要先得出出射方向 R ,这个计算量非常大,公式如下:
这个计算太复杂了,于是Blinn-Phong模型尝试通过半程向量h(l与v的角平分线方向)与法线方向n的夹角来替代R与v的夹角,即通过 max(0,n \cdot h) 来模拟。经过计算,n与h的夹角是l与v夹角的两倍,可以完美替代!(因为它们是完全线性的关系,数值上的差异可以修正)
但为什么h与n的夹角更好算呢?h是角平分线,它可以通过v+l快速确定方向,然后正则化即可。显然这比计算出射方向R要简单的多。
曾经我有这样的疑问:n不就是l与R的角平分线方向吗?那不就可以用l+R来确定n的方向?反过来,不就可以用l-n来确定R的方向吗?
这句话前半句是对的,确实可以用l+R来确定n的方向,但反过来就不对了,l-n并不是R的方向。我们假设l+R的结果是N,N与n同向,但模长不同。我们只知道n是单位向量,但不知道N具体是多长。所以我们只能确定l-N是R的方向,无法确定l-n是不是R的方向(显然绝大多数情况都不是)