Phong光照模型是計算機圖形學中一種非常基礎的光照算法,它的高光部分計算公式如下:
specular=pow(max(0,dot(viewDir, reflectDir)),shininess)
其中viewDir是相機坐標和物體坐標之差,reflectDir是光照方向與物體法向的反射,如下圖所示:

但是這種計算方式有一個問題,如下圖所示:

當相機和光照處於同一側時,此時得到的反射向量reflectDir和視角的方向viewDir的夾角已經大於90度,因此通過dot計算得出的值為負數。表現在渲染結果中就是當相機轉到某個角度的時候,高光反射會突然消失,顯得很不自然:

為了解決這個問題,James F.Blinn與1977年提出了Phong模型的改進算法:Blinn-Phong光照算法。該算法相比於Phong增加了HalfDir的概念,如圖所示:

HalfDir是光照方向和視角方向的相加並歸一化,最終比較的是它和normal的夾角。因為HalfDir和normal的夾角永遠不會高於90度,因此不用擔心dot值出現負數的情況。計算代碼如下所示:
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);
通過增加了HalfDir,高光變換更加自然,下圖展示了Phong和Blinn-Phong的渲染比較:

