Phong和Blinn-Phong光照模型都是基于经验的渲染模型,都是高光反射模型
Blinn-Phong 光照模型,又称为 Blinn-phong 反射模型(Blinn–Phong reflection model)或者 phong 修正模型(modified Phong reflection model),是由 Jim Blinn于 1977 年在文章“Models of light reflection for computer synthesized pictures”中对传统 phong 光照模型基础上进行修改提出的。
和传统 phong 光照模型相比,Blinn-phong 光照模型混合了 Lambert 的漫射部分和标准的高光,渲染效果有时比 Phong 高光更柔和、更平滑,此外它在速度上相当快,因此成为许多 CG 软件中的默认光照渲染方法。此外它也集成在了大多数图形芯片中,用以产生实时快速的渲染。在 OpenGL 和 Direct3D 渲染管线中, Blinn-Phong 就是默认的渲染模型。
Phong不能处理的情况
Phong模型在计算镜面光系数为:
1 | float specFactor = pow(max(dot(reflectDir, viewDir), 0.0), 32); // 32为镜面高光系数 |
高光发射的值由 反射向量和观察向量决定. 当两者的夹角θ超过90时,截断为0.0.就没有高光反射分量了.因此Phong模型能处理的是下面的左图中(θ≤90)的情况,而对于右图中(θ>90)的情况则镜面光成分计算为0.
但是这种计算方式有一个问题,如右图所示:当相机和光照处于同一侧时,此时得到的反射向量reflectDir和视角的方向viewDir的夹角已经大于90度,因此通过dot计算得出的值为负数。表现在渲染结果中就是当相机转到某个角度的时候,高光反射会突然消失,显得很不自然:为了解决这个问题,James F.Blinn与1977年提出了Phong模型的改进算法:Blinn-Phong光照算法。该算法相比于Phong增加了HalfDir的概念
而右图的这种情况实际上是存在的,将镜面光成分取为0,没有很好地体现实际光照情况。
Blinn-Phong
Blinn-Phong模型不再依赖于反射向量,而是采用了所谓的 **半程向量(Halfway Vector)**,即光线与视线夹角一半方向上的一个单位向量。当半程向量与法线向量越接近时,镜面光分量就越大。
HalfDir是光照方向和视角方向的相加并归一化,最终比较的是它和normal的夹角。因为HalfDir和normal的夹角永远不会高于90度,因此不用担心dot值出现负数的情况。计算代码如下所示:
1 | vec3 lightDir = normalize(lightPos - FragPos); |
半角向量计算公式
当观察向量与反射向量越接近,那么半角向量与法向量N越接近,观察者看到的镜面光成分越强。
Blinn-Phong: ambientColor + diffColormax(0,dot(n,l)) + specColormax(0,dot(n,h))*shininess
N:表面法向量
H:光入射方向L和视点方向V的中间向量
Shininess:高光系数