US3S2L3——纹理结合光照模型
US3S2L3——纹理结合光照模型
单张纹理结合 BlinnPhong 光照模型
如果要让有纹理的模型受到光照影响,就需要让纹理颜色结合光照模型计算出来的颜色,计算出模型显示在屏幕上的最终颜色
体现在 Shader 计算中,有以下的三点注意点:
- 
纹理颜色 需要和 漫反射颜色 进行乘法叠加,它们两共同影响最终的颜色,也就是需要计算反射颜色 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15sampler2D _MainTex; // 贴图纹理对应的映射成员 
 fixed4 _MainColor; // 漫反射颜色
 struct v2f
 {
 float4 pos: SV_POSITION; //裁剪空间下的顶点坐标
 float2 uv: TEXCOORD0; //纹理UV坐标
 float3 wNormal: NORMAL; //世界空间下的法线
 float3 wPos: TEXCOORD1; //世界空间下的顶点坐标
 };
 fixed4 frag (v2f i) : SV_Target
 {
 fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _MainColor.rgb; // 反射率,即纹理颜色和漫反射材质颜色乘法叠加共同决定的颜色
 }
- 
兰伯特光照模型计算时,漫反射材质颜色使用第一步计算出来的颜色计算 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18sampler2D _MainTex; // 贴图纹理对应的映射成员 
 fixed4 _MainColor; // 漫反射颜色
 struct v2f
 {
 float4 pos: SV_POSITION; //裁剪空间下的顶点坐标
 float2 uv: TEXCOORD0; //纹理UV坐标
 float3 wNormal: NORMAL; //世界空间下的法线
 float3 wPos: TEXCOORD1; //世界空间下的顶点坐标
 };
 fixed4 frag (v2f i) : SV_Target
 {
 fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _MainColor.rgb; // 反射率,即纹理颜色和漫反射材质颜色乘法叠加共同决定的颜色
 // 漫反射颜色
 float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); // 指向光源的方向
 fixed3 lambertColor = _LightColor0.rgb * albedo.rgb * max(0, dot(i.wNormal, lightDir));
 }
- 
最终使用的环境光叠加时,环境光变量 UNITY_LIGHTMODEL_AMBIENT 需要和第一步计算出来的颜色进行乘法叠加,为了避免最终的渲染效果偏灰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
 26
 27
 28
 29
 30
 31
 32sampler2D _MainTex; // 贴图纹理对应的映射成员 
 // 漫反射颜色、高光反射颜色、光泽度
 fixed4 _MainColor;
 fixed4 _SpecularColor;
 float _SpecularNum;
 struct v2f
 {
 float4 pos: SV_POSITION; //裁剪空间下的顶点坐标
 float2 uv: TEXCOORD0; //纹理UV坐标
 float3 wNormal: NORMAL; //世界空间下的法线
 float3 wPos: TEXCOORD1; //世界空间下的顶点坐标
 };
 fixed4 frag (v2f i) : SV_Target
 {
 fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _MainColor.rgb; // 反射率,即纹理颜色和漫反射材质颜色乘法叠加共同决定的颜色
 
 // 漫反射颜色
 float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); // 指向光源的方向
 fixed3 lambertColor = _LightColor0.rgb * albedo.rgb * max(0, dot(i.wNormal, lightDir));
 
 // 高光反射颜色
 float3 viewDir = normalize(UnityWorldSpaceViewDir(i.wPos)); // 视角方向
 float3 halfA = normalize(viewDir + lightDir); // 半角向量
 fixed3 specularColor = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(i.wNormal, halfA)), _SpecularNum);
 // 最终颜色,环境光需要和乘法叠加反射颜色
 fixed3 color = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo + lambertColor + specularColor;
 return fixed4(color.rgb, 1);
 }效果对比(左图为不叠加 albedo,右图为叠加 albedo):    
其他的计算步骤同 BlinnPhong 的逐片元光照 实现
完整 Shader 代码如下:
| 1 | Shader "TeachShader/Lesson50" | 
显示效果(左边是不计算光照效果的 Shader,右边是使用 BlinnPhong 逐片元光照的 Shader):

可见,结合了光照模型计算结果的模型能够收到光照的影响,出现背光变暗的效果
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 文KRIFE齐的博客!
