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高光类型 。这一节中书上代码出现了错误。务必参照随书代码进行修正!