Phong模型认为镜面反射的光强与反射光线和视线的夹角相关:
计算公式为:R + L = 2 * dot(N, L) * N 即 R = 2 * dot(N,L) * N - L
光源发出灯光,在材质表面反射,材质决定吸收灯光的什么分量和反射什么分量,而材质本身是不具有颜色的!在现实世界中,我们看到的物体颜色不是属于物体的,而是光与其作用后反射的。代码和效果图如下:
Shader "Sbin/MySpecularFrag"
{
properties
{
_SpecularColor("Specular",color)=(1,1,1,1)
_Shininess("Shininess",range(1,32))=8
}
SubShader
{
Pass
{
tags{"LightMode"="ForwardBase"}
CGPROGRAM
#pragma multi_compile_fwdbase
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
#include "lighting.cginc"
float4 _SpecularColor;
float _Shininess;
struct v2f
{
float4 pos:POSITION;
float3 normal:TEXCOORD0;
float4 vertex:COLOR;
};
v2f vert(appdata_base v)
{
v2f o;
o.pos= mul(UNITY_MATRIX_MVP,v.vertex);
o.normal=v.normal;
o.vertex=v.vertex;
return o;
}
fixed4 frag(v2f IN):COLOR
{//ambient color
fixed4 col= UNITY_LIGHTMODEL_AMBIENT;
//diffuse color
// dot(n,l)
float3 N=UnityObjectToWorldNormal(IN.normal);
float3 L=normalize(WorldSpaceLightDir(IN.vertex));
float diffuseScale=saturate(dot(N,L));
col+=_LightColor0*diffuseScale;
//specular color
float3 V=normalize(WorldSpaceViewDir(IN.vertex));
float3 R=2*dot(N,L)*N-L;
float specularScale=saturate(dot(R,V));
col+=_SpecularColor*pow(specularScale,_Shininess);
return col;
}
ENDCG
}
}
}
Blinn-phong光照模型。
它是以Phong模型为基础的,效果是能让高光更加柔和,更平滑。其实这个模型的效果并不比Phong模型 高级,使用blinn-phong 进行光照渲染,在同样的高光系数下,高光领域覆盖范围较大,明暗界限不明显。所以它真实感还没Phong模型强。但是这个模型运算速度要快些。因此在DX中默认的高光模型就是它。Blinn-phong光照模型公式为:H = (L + V) / |L + V| ),其中N是入射点的单位法向量,H是光入射方向L和视点方向V的中间向量,通常也称之为半角向量(半角向量被广泛用于各类光照模型,原因不但在于半角向量蕴含的信息价值,也在于半角向量是很简单的计算。镜面高光由n和h的夹角决定如图所示:
代码及效果图如下:
Shader "Sbin/MySpecular"
{
properties
{
_SpecularColor("Specular",color)=(1,1,1,1)
_Shininess("Shininess",range(1,64))=8
}
SubShader
{
Pass
{
tags{"LightMode"="ForwardBase"}
CGPROGRAM
#pragma multi_compile_fwdbase
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
#include "lighting.cginc"
float4 _SpecularColor;
float _Shininess;
struct v2f
{
float4 pos:POSITION;
float4 color:COLOR;
};
v2f vert(appdata_base v)
{
v2f o;
o.pos= mul(UNITY_MATRIX_MVP,v.vertex);
float3 L=normalize(WorldSpaceLightDir(v.vertex));
float3 N=UnityObjectToWorldNormal(v.normal);
float3 V=normalize(WorldSpaceViewDir(v.vertex));
//Ambient Color
o.color=UNITY_LIGHTMODEL_AMBIENT ;
// Diffuse Color
float ndotl=saturate(dot(N,L));
o.color+=_LightColor0* ndotl;
//Specular Color
//float3 wpos=mul(_Object2World,v.vertex).xyz;
float3 H=L+V;
H=normalize(H);
float specularScale=pow(saturate(dot(H,N)),_Shininess);
o.color.rgb+=_SpecularColor * specularScale;
return o;
}
fixed4 frag(v2f IN):COLOR
{
return IN.color+UNITY_LIGHTMODEL_AMBIENT;
}
ENDCG
}
}
}