Shader系列(2):Phong光照模型

    Lambert模型能很好的表示粗糙表面的光照,但不能表现出镜面反射高光。1975Phong Bui Tong发明的Phong模型,提出了计算镜面高光的经验模型,镜面反射光强与反射光线和视线的夹角a相关:

    Ispecular = Ks*Is*(cos a) n

    其中Ks为物体表面的高光系数,Is为光强,a是反射光与视线的夹角,n为高光指数,n越大,则表面越光滑,反射光越集中,高光范围越小。如果V表示顶点到视点的单位向量,R表示反射光反向,则cos a可表示为VR的点积。模型可表示为:

   Ispecular = Ks*Is*(VR) n

    反射光放向R可由入射光放向L(顶点指向光源)和物体法向量N求出。

    R = (2NL)N – L

1) VertexShader
float4x4 matWorldViewProjection;
float4x4 matWorldView;
float4x4 matView;
float3 lightPos;

struct VS_INPUT
{
float4 position : POSITION0;
float3 normal: NORMAL;
};

struct VS_OUTPUT
{
float4 position : POSITION0;
float3 normalInView: TEXCOORD0;
float3 lightDirInView: TEXCOORD1;
float3 viewDirInView: TEXCOORD2;
};

VS_OUTPUT vs_main( VS_INPUT Input )
{
VS_OUTPUT Output;

Output.position = mul( Input.position, matWorldViewProjection );
Output.normalInView = normalize(mul( Input.normal, matWorldView));
Output.lightDirInView = normalize(lightPos - mul( Input.position, matWorldView));
float3 position = mul( Input.position, matWorldView);
Output.viewDirInView = normalize(matView[3].xyz - position);
return Output;
}

 

2) PixelShader

float4 ambientColor;
float4 diffuseColor;
float4 specularColor;

struct PS_INPUT
{
float3 normalInView: TEXCOORD0;
float3 lightDirInView: TEXCOORD1;
float3 viewDirInView: TEXCOORD2;
};

struct PS_OUTPUT
{
float4 color : COLOR0;
};


PS_OUTPUT ps_main( PS_INPUT In )
{
PS_OUTPUT Out;

float4 diffuse = max( 0, dot( In.normalInView, In.lightDirInView ));
diffuse = diffuse * diffuseColor;

float3 vReflect = normalize( 2 * dot( In.normalInView, In.lightDirInView) * In.normalInView - In.lightDirInView );

float4 specular = specularColor * pow( max( 0, dot(vReflect, In.viewDirInView)), 2 );

Out.color = ambientColor + diffuse + specular;

return Out;
}

 

Shader系列(2):Phong光照模型_第1张图片

 Phong光照模型效果

转载于:https://www.cnblogs.com/cxrs/archive/2013/01/22/Lambert%e5%85%89%e7%85%a7%e6%a8%a1%e5%9e%8b.html

你可能感兴趣的:(Shader系列(2):Phong光照模型)