八叶一刀·无仞剑

万物流转,无中生有,有归于无

导航

Blinn-Phong光照算法

Posted on 2020-05-06 20:51  闪之剑圣  阅读(2146)  评论(0编辑  收藏  举报

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的渲染比较: