Unity Shaders and Effects Cookbook 中 Creating a Phong Specular type这一章,里面的Phong模型是这样算的。
inline fixed4 LightingPhong(SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
{
float diff = dot(s.Normal, lightDir);
float3 reflectionVector = normalize(2.0 * s.Normal * diff - lightDir);
float spec = pow(max(0, dot(reflectionVector, viewDir)), _SpecPower);
float3 finalSpec = _SpecularColor.rgb * spec;
fixed4 c;
c.rgb = (s.Albedo * _LightColor0.rgb * diff) + (_LightColor0.rgb * finalSpec);
c.a = 1.0;
return c;
}
其中对于这句
float3 reflectionVector = normalize(2.0 * s.Normal * diff - lightDir);
书里是这么解释的“We then calculate the reflection vector taking the vertex normal, scaling it by 2.0 and by
the diff value, then subtracting the light direction from it. This has the effect of bending the
normal towards the light; so as a vertex normal is pointing away from the light, it is forced to
look at the light”
书里配的插图是这样的
但事实上这个Reflection Vector不可能是这样的,从名字上看这个向量叫做“反射向量”,它实际上也确实指的都是反射的光的方向,而不是统一朝向光源。从一个顶点上来看,状况应该是这样的。
如果把它放在一个球上,它的计算结果应该是这样的:
其中绿色的线表示法线方向,黄色的线代表光照方向,红色是反射向量。只看反射向量,这个图是这样的。
换成平行光,反射向量是这样的
得出的反射向量与视线方向做点乘,当目光与光照方向垂直时
得到的结果是这样的——平行光
点光源:
以上