Blinn-Phong

前面的章节我们总结了phong模型,它有三个分量,分别是ambient,diffuse,specular。
关于ambient的计算没有什么疑问。
关于diffuse的计算也没有什么疑问。
但是specular的计算,这里我们需要一个角度,也就是反射方向与视线方向的角度

1
vec3 specular = specularStrength * pow(max(dot(viewDir, reflectDir), 0.0), shininess); * lightColor * objectColor;

实际上我们要计算viewDir与reflectDir之间的余弦。这就有个问题了,当dot(viewDir, reflectDir)<0的时候,从上面的公式看,是没有镜面高光效果的,这是不对的,如下所示:
BlinnPhong
左边是没有问题的,但是右图的余弦小于0,它也应该是能观察到高光效果的,但是从上面的计算公式看,它的specular分量为0。因此这个模型是存在缺陷的,因此Blinn-Phong模型对此处做了改进。

我们引入了半程向量:
半程向量就是光线方向与观察方向的中间向量。当半程向量与法线越接近,则高光越明显。半程向量的引入,就解决了上面的问题。
BlinnPhong1

1
2
3
4
5
6
7
vec3 lightDir   = normalize(lightPos - FragPos);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 halfwayDir = normalize(lightDir + viewDir);

float spec = pow(max(dot(normal, halfwayDir), 0.0), shininess);
vec3 specular = lightColor * spec;
vec3 result = specular * objectColor;