US3S1L4-2——Phong式高光反射光照模型的逐片元光照
知识回顾
公式:
高光反射光照颜色=光源的颜色×材质高光反射颜色×max(0, 标准化后观察方向向量⋅标准化后的反射方向)光泽度
- 标准化后观察方向向量⋅标准化后的反射方向 得到的结果就是 cosθ
 
- 光泽度是幂运算,相当于:(max(0,cosθ))n
 
信息获取:
- 观察者的位置(摄像机的位置):
_WorldSpaceCameraPos 
- 相对于法向量的反射向量 方法:
reflect(入射向量, 顶点法向量) 返回反射向量 
- 指数幂 方法:
pow(底数, 指数) 返回计算结果 
其他关键信息获取方式和兰伯特光照模型差不多,参考:如何在Shader中获取公式中的关键信息
利用Phong式高光反射模型实现光照效果(逐片元光照)
关键步骤:基本和逐顶点一致
区别:
- 在顶点着色器计算顶点和法线相关数据
 
- 在片元着色器中计算Phong式高光反射光照
 
Shader实现如下:
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
   | Shader "Unlit/Lesson36" {     Properties     {         _SpecularColor("SpecularColor", Color) = (1, 1, 1, 1)            _SpecularNum("SpecularNum", Range(0, 20)) = 0.5              }     SubShader     {         Pass         {             Tags { "LightMode" = "ForwardBase" }    
              CGPROGRAM             #pragma vertex vert             #pragma fragment frag
              #include "UnityCG.cginc"             #include "Lighting.cginc"
              struct v2f             {                 float4 svPos : SV_POSITION;                      float3 wNormal : NORMAL;                         float3 wPos : TEXCOORD0;                     };
              fixed4 _SpecularColor;             float _SpecularNum;
              v2f vert (appdata_base v)             {                 v2f v2fData;                 v2fData.svPos = UnityObjectToClipPos(v.vertex);                              v2fData.wNormal = UnityObjectToWorldNormal(v.normal);                        v2fData.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;      
                  return v2fData;             }
              fixed4 frag (v2f i) : SV_Target             {                 float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.wPos);                   float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);                           float3 reflectDir = reflect(-lightDir, i.wNormal);                                                fixed3 color = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(viewDir, reflectDir)), _SpecularNum);                 return fixed4(color.rgb, 1);             }             ENDCG         }     } }
   | 
 
显示效果(左边为逐片元光照,右边为逐顶点光照):
显然,逐片元光照的效果更平滑