BlinnPhong 是另一种估算镜面高光的方式,相比于 上一次学习的 Phong 光照模型,更简单 高效。
BlinnPhong 是通过视线方向 和 光线方向 所形成的半角向量 来完成的。
Phong 和 BlinnPhong 算法图 对比如下:
可以看出 BlinnPhong 计算过程 比 Phong 简单了很多。
而且通过实验结果来说,两种算法得到的效果是差不多的。
简单描述下过程:
1、首先 灯光方向向量 和 视角方向向量 相加,得到 半角向量。
2、对 半角向量 和 法线向量 求 Cos 值,得到高光强度。
转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
依据上面的 BlinnPhong 公式来码代码:
CustomBlinnPhong.shader
Shader "CookBookShaders/CustomBlinnPhong" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _MainTint("Main Tint",Color)=(1,1,1,1) _SpecularColor("Specular Color",Color)=(1,1,1,1) _SpecularPower("Specular Power",Range(0.1,120))=1 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf CustomBlinnPhong sampler2D _MainTex; float4 _MainTint; float4 _SpecularColor; float _SpecularPower; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = c.a; } fixed4 LightingCustomBlinnPhong(SurfaceOutput s,fixed3 lightDir,fixed3 viewDir,fixed atten) { float3 diffuse = max(0,dot(s.Normal , lightDir)); float3 halfVector=normalize(lightDir + viewDir); float specular=max(0, dot( s.Normal , halfVector )); float finalSpecular=pow(specular,_SpecularPower); float4 c; c.rgb = (s.Albedo * _LightColor0.rgb * diffuse) +( _LightColor0.rgb * _SpecularColor.rgb * finalSpecular)*(atten*2); c.a=s.Alpha; return c; } ENDCG } FallBack "Diffuse" }
和 Phong 的效果并没有什么差异。
示例工程下载:
http://pan.baidu.com/s/1dEMU5OX
这一节对应 Unity着色器和屏幕特效开发秘籍的 3.4 节 --- 创建BlinnPhong高光类型 。这一节中书上代码出现了错误。务必参照随书代码进行修正!