blinn-phong高光:
H=normalize(V+L);
specular=pow(saturate(dot(N,H)),shiness);
会遇到如下问题:
图中光源在surface背面,但却仍然产生高光。(可以验证,不使用半角向量h,而使用反射向量r的原始phong高光也存在类似问题。)
此问题的一种简单解决办法,是判断出光源在surface背面则令specular为0,即:
H=normalize(V+L);
specular=pow(saturate(dot(N,H)),shiness);
if(dot(N,L)<0){
specular&#61;0;
}
这样确实能避面背光面产生高光&#xff0c;但是在背光面和受光面之间高光突然截断会产生过硬的明暗交界线。
也见过有算法是用specular直接乘以一下diffuse&#xff0c;从而获得柔和过度&#xff0c;但往往会过于柔和。
为了使交界线处过度柔和且柔和程度可控&#xff0c;可以采用如下技巧&#xff1a;
首先不难看出上面代码等价于&#xff1a;
H&#61;normalize(V&#43;L);
specular&#61;pow(saturate(dot(N,H)),shiness);
specular*&#61;step(0,dot(N,L));
为使过度平滑&#xff0c;只需用smoothstep代替step&#xff0c;即&#xff1a;
H&#61;normalize(V&#43;L);
specular&#61;pow(saturate(dot(N,H)),shiness);
specular*&#61;smoothstep(0,0.12,dot(N,L));
这样就ok了。
注&#xff1a;smoothstep(0,0.12,dot(N,L))的含义就是&#xff1a;当dot(N,L)<0时&#xff0c;取0&#xff1b;当dot(N,L)>0.12时取1&#xff0c;当dot(N,L)介于0与0.12之间时平滑插值。