主要实现的的Phone模型,即逐顶点光照模型。
所谓漫反射
指的就是对于那些被物体表面随机散射到各个方向的辐射度进行建模,它的效果是接近于现实中的漫反射,但它的反射是完全随机的,任何反射方向的分步都是一样的。
漫反射的计算公式如下
C.diffuse = (C.light · M.diffuse)max(0,N·L)
计算漫反射需要知道4个参数:入射光线颜色与强度C.light,材质的漫反射系数M.diffuse,表面法线N,光源方向L。max的函数意义在于将括号内的值截取在[0,1]范围内,如果是一个矢量,则对它的每一个分量都这么做。
接下来是代码部分
基础漫反射shader代码
在properties中声明一个color类型的属性,初始值设置为(1,1,1,1),即白色。
在SubShader语义块中定义一个Pass语义块,Pass语义块内就是一个渲染流程代码
首先使用Tags指明该pass的光照模式,只有定义了正确的LightMode,才能得到Unity内的内置光照变量,例如_LightColor0.
使用CGPROGRAM ENDCG包围Cg代码片,指定编译的顶点着色器代码和片元着色器代码的名称,以及包含Unity的内置文件Lighting.cginc,为了使用properties中声明的属性,还需要定义一个和该属性(fixed4)相匹配的变量_Diffuse
声明a2v与v2f的结构体,a2v是application to vertex的简写,v2f则是vertex to fragment的简写。其中a2v包含了4位数的vertex变量与3位的法线normal变量,v2f则包含了4位浮点数的方向pos变量,三位数的color变量。
接下来是顶点着色器vert
首先声明返回值 o
通过UnityObjectToClipPos函数将顶点位置从模型空间转换到齐次剪裁空间
使用UNITY_LIGHTMODEL_AMBIENT.xyz得到环境光部分变量
关键的来了,计算漫反射需要世界空间下的法线向量与光源方向的点乘,而此时的法线矢量还处于模型空间下,所以需要使用mul函数对v.normal进行转化,使用的转换矩阵则是模型空间到世界空间的转换矩阵的逆矩阵,即(float3x3)unity_WorldToObjetct。通过它与v.noraml的矩阵乘法运算,可以得出法线矢量在世界坐标系下的方向。
得到了世界空间下的法线与光源方向后,对其进行归一化得到点乘,使用saturate函数对其取值进行限制在[0,1]范围内,然后再使用_LightColor0.rgb,即光源的颜色与强度与_Diffuse.rgb材质漫反射颜色相乘,即可求得最终的漫反射光照部分。
最后在用求得的漫反射光照diffuse与环境光ambient相加,即可得到漫反射效果。
最后的Fallback“Diffuse”是与SubShader同级的,它本身也类似与SubShader。
最后的效果如下
使用了B站同款粉