您的位置:首页 > 其它

Phong和Blinn-Phong光照模型

2016-03-20 19:43 375 查看
Phong和Blinn-Phong是计算镜面反射光的两种光照模型,两者仅仅有很小的不同之处。



1.Phong模型



Phone模型计算中的一个关键步骤就是反射向量R的计算:



上图中的位于表面“下面”的向量‘I’是原始‘I’向量的拷贝,并且二者是一样的,现在我们的目标计算出向量‘R’。根据向量相加原则,向量‘R’等于'I'+'V',‘I’是已知的,所以我们需要做的就是找出向量‘V’。注意法向量‘N’的负方向就是‘-N’,我们可以在‘I’和‘-N’之间使用一个点乘运算就能得到‘I’在‘-N’上面的投影的模。这个模正好是‘V’的模的一半,由于‘V’与‘N’有相同的方向,我们可以将这个模乘上‘N’(其模为1)再乘上2即可得到‘V’。总结一下就是下面的公式:



2.Blinn-Phong模型

Phong模型中计算反射光线的向量是一件相对比较耗时的任务,因此Blinn-Phong对这一点进行了改进。



Ks:物体对于反射光线的衰减系数

N:表面法向量

H:光入射方向L和视点方向V的中间向量

Shininess:高光系数

可见,通过该式计算镜面反射光是符合基本规律的,当视点方向和反射光线方向一致时,计算得到的H与N平行,dot(N,H)取得最大;当视点方向V偏离反射方向时,H也偏离N。

同时H的计算比起反射向量R的计算简单的多,R向量的计算需要若干次的向量乘法与加法,而H的计算仅仅需要一次加法。

下面是用cg着色语言书写的Phong和Blinn-Phong的顶点和片段着色程序

Phong_FragmentLighting_v.cg


structV2F{
float4position:POSITION;
float3worldPosition:TEXCOORD0;
float3worldNormal:TEXCOORD1;
};
voidPhong_FragmentLighting_v(float4position:POSITION,
float4normal:NORMAL,
uniformfloat4x4modelMatrix,
uniformfloat4x4modelMatrix_IT,
uniformfloat4x4modelViewProj,
outV2FO){
O.position=mul(modelViewProj,position);
O.worldPosition=mul(modelMatrix,position).xyz;
O.worldNormal=normalize(mul(modelMatrix_IT,normal)).xyz;
}


Phong_FragmentLighting_f.cg


voidPhong_FragmentLighting_f(float3position:TEXCOORD0,
float3normal:TEXCOORD1,
uniformfloat3globalAmbient,
uniformfloat3lightColor,
uniformfloat3lightPosition,
uniformfloat3eyePosition,
uniformfloat3Ke,
uniformfloat3Ka,
uniformfloat3Kd,
uniformfloat3Ks,
uniformfloatshininess,
outfloat4color:COLOR)
{
float3N=normalize(normal);
float3L=normalize(lightPosition-position);
float3V=normalize(eyePosition-position);

float3R=reflect(-L,N);
R=normalize(R);

//Computeemissiveterm
float3emissive=Ke;

//Computeambientterm
float3ambient=Ka*globalAmbient;

//Computethediffuseterm
floatdiffuseLight=max(dot(N,L),0);
float3diffuse=Kd*lightColor*diffuseLight;

//Computethespecularterm
floatspecularLight=pow(max(dot(V,R),0),shininess);
if(diffuseLight<=0)specularLight=0;
float3specular=Ks*lightColor*specularLight;

//color.xyz=emissive+ambient+diffuse+specular;
color.xyz=ambient+diffuse+specular;
color.w=1;
}


BlinnPhong_FragmentLighting_v.cg


structV2F{
float4position:POSITION;
float3worldPosition:TEXCOORD0;
float3worldNormal:TEXCOORD1;
};
voidBlinnPhong_FragmentLighting_v(float4position:POSITION,
float4normal:NORMAL,
uniformfloat4x4modelMatrix,
uniformfloat4x4modelMatrix_IT,
uniformfloat4x4modelViewProj,
outV2FO){
O.position=mul(modelViewProj,position);
O.worldPosition=mul(modelMatrix,position).xyz;
O.worldNormal=normalize(mul(modelMatrix_IT,normal)).xyz;
}



BlinnPhong_FragmentLighting_f.cg


voidBlinnPhong_FragmentLighting_f(float3position:TEXCOORD0,
float3normal:TEXCOORD1,
uniformfloat3globalAmbient,
uniformfloat3lightColor,
uniformfloat3lightPosition,
uniformfloat3eyePosition,
uniformfloat3Ke,
uniformfloat3Ka,
uniformfloat3Kd,
uniformfloat3Ks,
uniformfloatshininess,
outfloat4color:COLOR)
{
float3N=normalize(normal);
float3L=normalize(lightPosition-position);
float3V=normalize(eyePosition-position);

float3H=normalize(L+V);

//Computeemissiveterm
float3emissive=Ke;

//Computeambientterm
float3ambient=Ka*globalAmbient;

//Computethediffuseterm
floatdiffuseLight=max(dot(N,L),0);
float3diffuse=Kd*lightColor*diffuseLight;

//Computethespecularterm
floatspecularLight=pow(max(dot(H,N),0),shininess);
if(diffuseLight<=0)specularLight=0;
float3specular=Ks*lightColor*specularLight;

color.xyz=ambient+diffuse+specular;
color.w=1;
}



效果对比:



Phong光照模型



Blinn-Phong光照模型

通过简单的对比发现,在相同条件下Blinn-Phong的高光范围要比Phong更大,写实效果Phong光照模型更好。但算法简单,运行速度快是Blinn-Phong光照模型的优点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: