US3S1L5-1——Phong光照模型的逐顶点光照
US3S1L5-1——Phong光照模型的逐顶点光照
知识回顾
Phong光照模型公式:
其中:
- 环境光颜色 =
UNITY_LIGHTMODEL_AMBIENT
(或者:unity_AmbientSky
、unity_AmbientEquator
、unity_AmbientGround
)- 漫反射光颜色 = 兰伯特光照模型 计算得到的颜色
- 高光反射光颜色 = Phong式高光反射光照模型 计算得到的颜色
利用Phong式光照模型实现光照效果(逐顶点光照)
关键步骤:
-
计算兰伯特光照模型
1
2
3
4
5
6
7
8
9
10
11
12
13fixed4 _MainColor; //属性设置的漫反射颜色
//计算兰伯特光照模型 颜色相关函数(逐顶点)
//参数:
// objNormal: 顶点的法线信息
fixed3 getVertLambertColor(in float3 objNormal)
{
float3 normal = UnityObjectToWorldNormal(objNormal); //将模型空间下的法线转换到世界空间下
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); //光源0在世界坐标系下的位置标准化,用于和法线计算夹角
//兰伯特光照模型的实现,这里的颜色计算只取rgb,不考虑透明度的情况
fixed3 color = _LightColor0.rgb * _MainColor.rgb * max(0, dot(normal, lightDir));
return color;
} -
计算Phong式高光反射光照模型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21fixed4 _SpecularColor; //属性设置的材质高光颜色
float _SpecularNum; //属性设置的光泽度
//计算Phong高光反射光照模型 颜色相关函数(逐顶点)
//参数:
// objVertex: 顶点坐标
// objNormal: 顶点的法线信息
fixed3 getVertSpecularColor(in float4 objVertex, in float3 objNormal)
{
//计算标准化的观察方向向量
float3 worldPos = mul(UNITY_MATRIX_M, objVertex); //使用UNITY_MATRIX_M矩阵,将模型空间下的顶点转换到世界空间下
float3 viewDir = _WorldSpaceCameraPos.xyz - worldPos; //将摄像机坐标和顶点坐标通过相减,得到观察方向向量
viewDir = normalize(viewDir); //将观察空间向量标准化
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); //得到世界空间下的指向光源方向的标准化向量
float3 normal = UnityObjectToWorldNormal(objNormal); //得到世界空间下的法线向量
float3 reflectDir = reflect(-lightDir, normal); //计算反射光线向量,由于光源向量指向光源,而函数需要入射向量,因此需要对光源向量取反
//Phong高光反射模型的实现,这里的颜色计算只取rgb,不考虑透明度的情况
fixed3 color = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(viewDir, reflectDir)), _SpecularNum);
return color;
}
完整的Shader代码如下:
1 | Shader "TeachShader/Lesson38" |
显示效果(漫反射颜色为红色,高光反射颜色为白色,光泽度为5):
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 文KRIFE齐的博客!