US3S1L4-1——Phong式高光反射光照模型的逐顶点光照
US3S1L4-1——Phong式高光反射光照模型的逐顶点光照
知识回顾
公式:
- 得到的结果就是
- 光泽度是幂运算,相当于:
信息获取:
- 观察者的位置(摄像机的位置):
_WorldSpaceCameraPos
- 相对于法向量的反射向量 方法:
reflect(入射向量, 顶点法向量)
返回反射向量- 指数幂 方法:
pow(底数, 指数)
返回计算结果其他关键信息获取方式和兰伯特光照模型差不多,参考:如何在Shader中获取公式中的关键信息
利用Phong式高光反射模型实现光照效果(逐顶点光照)
关键步骤
-
属性声明(材质高光反射颜色、光泽度)
1
2
3
4
5Properties
{
_SpecularColor("SpecularColor", Color) = (1, 1, 1, 1) //材质高光反射颜色
_SpecularNum("SpecularNum", Range(0, 20)) = 0.5 //光泽度
} -
渲染标签 Tags 设置将 LightMode 光照模式设置为 ForwardBase 向前渲染(通常用于不透明物体的基本渲染)
1
Tags { "LightMode" = "ForwardBase" }
-
引用内置文件UnityCG.cginc和Lighting.cginc
1
2 -
结构体声明
对于输入到顶点着色器的参数,可以直接使用
UnityCG.cginc
的 appdata_base对于从顶点着色器输出到片元着色器的参数,需要我们自己声明结构体
v2f
1
2
3
4
5struct v2f
{
float4 svPos : SV_POSITION; //裁剪空间下的顶点坐标
fixed3 color : COLOR; //颜色信息,这里只传递颜色的rgb,而不传递透明度,故使用fixed3
}; -
基本公式实现逻辑
- 计算标准化的观察方向向量(使用世界坐标系下的摄像机坐标减去顶点坐标获取,可见:向量减法)
- 计算标准化的反射光线向量(使用反射函数 reflect() 计算,需要入射光和顶点法线,入射光需要对标准化的光源向量取反得到)
- 将光照颜色,高光材质颜色,标准化的观察方向向量,反射光线向量和光泽度代入到公式内
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26fixed4 _SpecularColor; //属性设置的材质高光颜色
float _SpecularNum; //属性设置的光泽度
v2f vert (appdata_base v)
{
v2f v2fData;
v2fData.svPos = UnityObjectToClipPos(v.vertex); //首先将模型空间下的顶点转换到裁剪空间下
//计算标准化的观察方向向量
float3 worldPos = mul(UNITY_MATRIX_M, v.vertex); //使用UNITY_MATRIX_M矩阵,将模型空间下的顶点转换到世界空间下
float3 viewDir = _WorldSpaceCameraPos.xyz - worldPos; //将摄像机坐标和顶点坐标通过相减,得到观察方向向量
viewDir = normalize(viewDir); //将观察空间向量标准化
//计算标准化的反射光线向量
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); //得到世界空间下的指向光源方向的标准化向量
float3 normal = UnityObjectToWorldNormal(v.normal); //得到世界空间下的法线向量
float3 reflectDir = reflect(-lightDir, normal); //计算反射光线向量,由于光源向量指向光源,函数需要入射向量,因此对光源向量取反
//Phong高光反射模型的实现,这里的颜色计算只取rgb,不考虑透明度的情况
fixed3 color = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(viewDir, reflectDir)), _SpecularNum);
v2fData.color = color;
return v2fData;
}
fixed4 frag (v2f i) : SV_Target
{
return fixed4(i.color.rgb, 1); //因为传递过来的颜色变量不包括透明度,因此这里需要手动指定透明度
}
所有Phong式高光反射模型的逐顶点光照的显示效果如下(左图光泽度为0.5,右图光泽度为2)
可见,随着光泽度的增加,反射光斑会越来越小
完整Shader代码如下:
1 | Shader "TeachShader/Lesson35" |
使用逐片元光照和逐顶点光照的Shader的材质显示效果如下(左边为逐片元光照,右边为逐顶点光照):
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 文KRIFE齐的博客!