本节书摘来自华章出版社《Unity着色器和屏幕特效开发秘笈》一 书中的第3章,第3.3节,作者:(美)Kenny Lammers,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
3.3 创建Phong高光类型
Phong高光模型是最基础且表现最友好的高光类型。它会计算出光在物体表面的反射方向与观察者视线方向之间的对比结果。它是一种非常常见的高光模型,从游戏到电影都有诸多的应用。虽然在镜面反射的精确建模上它并不是最接近现实的,但在大多数情况下它都显得极为逼真。另外,如果你的观察对象是远离相机的而且不需要对高光进行精确计算的时候,Phong高光模型是表现着色器高光效果最好的方式之一。
在本节中,我们将要学习的内容包括如何对Phong高光类型进行逐顶点操作,以及在表面着色器中使用Input结构体的新参数进行逐像素操作。我们还会看一看它们之间的差别,并探讨两种不同实现方式的使用条件以及原因。
3.3.1 准备工作
1.创建一个新的着色器、材质和物体对象,并对它们进行适当命名以方便找到它们。
2.最后,将着色器附加到材质上,然后将该材质赋给新建的物体对象。建好场景后,再创建一个方向光,这样才能看出我们编写的高光效果。
3.3.2 如何操作
1.阅读至此,你可能已经发现了一个模式,我们似乎总是喜欢从基础的部分开始编写着色器。现在,我们将如下所示的属性添加到着色器中:
2.然后我们需要确保位于SubShader块中的CGPROGRAM块中添加了相应的属性
变量。
3.现在,我们需要添加自定义的光照模型,以便计算Phong高光。将下面的代码添加至着色器的SubShader()函数中。现在先不要关心这些内容的意义,因为我们将在下一节中逐行地解释每一句代码:
4.最后,我们还应该告诉CGPROGRAM块,它需要使用我们自定义的光照函数而不是内置的函数。为了做到这些,我们对#pragma语句进行如下修改:
3.3.3 实现原理
我们只将光照函数本身进行分解,因为对于着色器的其余部分你应该相当熟悉了。
我们简单地从使用光照函数为我们提供的一个视点方向开始。希望大家记住,Unity已经为我们提供了一系列可以使用的光照函数,但是为了正确地使用它们,你还必须使用相对应的正确参数。
在这里,我们正在创建的是一个高光着色器,所以我们需要选择的是视点相关型的光照函数结构。因此,我们用如下代码编写该函数:
这样就会告诉着色器我们想要建立的是一个自定义的视点相关型着色器。当然,你还要确保光照函数的命名与#pragma语句的声明相一致,否则Unity无法识别你的光照模型。
接下来,光照函数会首先计算顶点法线和光的入射方向或矢量的点积值来声明一个常用的漫反射组件。我们将得到一个返回值,当该值为1时,表明物体是正对着光源方向的,反之该值为-1时表明物体是背对着光源方向的。
然后我们计算反射向量,先对顶点法线的向量值进行缩放,将该值乘以2.0后再乘以diff值,得到的值减去光照的方向向量值。这样做的原因是为了实现法线朝向光源弯曲的效果,所以作为一个远离光源的法线向量,它将被强制朝向光源方向。为了得到更直观的视觉表现可以参考下图。产生这种效果的调试脚本放在本书的支持页面www.packtpub.com/support上。
接下来,我们需要做的就是创建spec值和颜色值。为了得到这两个值,我们对反射向量和视角方向进行点积运算,然后对结果求_SpecPower次方,最后将_SpecularColor. rgb值乘以spec值得到我们最后的高光。
下图展示的是我们在着色器中进行单一的Phong高光计算的最终结果: