0%

图形学基础-Phong和Blinn-Phong光照模型

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
2
float   specFactor = pow(max(dot(reflectDir, viewDir), 0.0), 32); // 32为镜面高光系数
//其中viewDir是相机坐标和物体坐标之差,reflectDir是光照方向与物体法向的反射,如下图所示:

高光发射的值由 反射向量和观察向量决定. 当两者的夹角θ超过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)**,即光线与视线夹角一半方向上的一个单位向量。当半程向量与法线向量越接近时,镜面光分量就越大。

img

HalfDir是光照方向和视角方向的相加并归一化,最终比较的是它和normal的夹角。因为HalfDir和normal的夹角永远不会高于90度,因此不用担心dot值出现负数的情况。计算代码如下所示:

1
2
3
4
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);

在这里插入图片描述

半角向量计算公式

当观察向量与反射向量越接近,那么半角向量与法向量N越接近,观察者看到的镜面光成分越强。


Blinn-Phong: ambientColor + diffColormax(0,dot(n,l)) + specColormax(0,dot(n,h))*shininess

N:表面法向量

H:光入射方向L和视点方向V的中间向量

Shininess:高光系数

欢迎关注我的其它发布渠道