US3S1L6-2——Blinn-Phong式高光反射光照模型的逐片元光照
知识回顾
公式:
高光反射光照颜色=光源的颜色×材质高光反射颜色×max(0, 标准化后顶点法线方向⋅标准化后半角向量方向)光泽度
- 标准化后顶点法线方向⋅标准化后半角向量方向 得到的结果就是 cosθ
- 半角向量方向=视角单位向量+入射光单位向量
- 光泽度是幂运算,假设光泽度为 n ,相当于:(max(0,cosθ))n
利用Blinn-Phong式高光反射模型实现光照效果(逐片元光照)
关键步骤:基本和逐顶点一致
区别:
- 在顶点着色器计算顶点和法线相关数据
- 在片元着色器中计算Blinn-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 54
| Shader "TeachShader/Lesson42" { Properties { _SpecularColor("SpecularColor", Color) = (1, 1, 1, 1) _SpecularNum("SpecularNum", Range(0, 20)) = 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 halfA = normalize(viewDir + lightDir); fixed3 color = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(i.wNormal, halfA)), _SpecularNum); return fixed4(color.rgb, 1); } ENDCG } } }
|
显示效果(光泽度统一为5):
可见,Blinn-Phong式高光反射模型比Phong式高光反射模型的高光效果更加均匀,面积也更大
而逐片元光照相比逐顶点光照的高光光斑边缘也更加平滑