从0开始的OpenGL学习(二十八)-Blinn-Phong

本文只要解决一个问题:

如何使用Blinn-Phong光照模型使高光更柔和、更平滑?

引言

在光照文章中,我们介绍了Phong光照模型来模拟真实的场景。看起来效果不错,但还是有点细微差别,啥差别呢,别急,你往下看。

Phong光照模型的缺陷

在开始之前,请先下载这里的源码配置一个新工程。编译运行一下代码,你会看到这样的效果:

Phong光照模型

这就是Phong光照模型的缺陷。什么,你说你看到的不是这样?哦,忘了说了,要把镜面高光的光泽度信息改成1.0。在光泽度为1.0的情况下,Phong光照模型的缺陷就暴露无遗了。

啥是光泽度?这问题问的好,笔者也快忘了,赶紧翻翻之前写过的文章。哦,原来是高光的集中度。找到片元着色器中的这一行代码pow (max(dot(viewDir, reflectDir), 0.0), 32.0);,把32.0改成1.0你就能看到上图中的效果了。Phong光照模型的缺陷也只有在这种特定情况下才会显现。

可以非常清楚地看到,在边缘部分,镜面高光的区域被立刻切断了!出现这种问题的原因是,在Phong光照模型中,观察向量和反射向量之间的夹角不允许大于90度。一旦夹角大于90的,观察方向和反射方向的点积就会变负数,而我们在计算的时候会把这个负数截断到0,这样,镜面高光部分就完全看不到了。

你可能会这样想,我们的观察向量和反射方向夹角不会大于90度的,对吧?

大错特错!要知道,我们的观察角度可以是四面八方的,没有什么法律规定我们只能沿着反射方向观察,如果我们观察的方向和光源是在同一边呢?这样视线方向和反射方向的夹角就可能大于90度,产生不真实的效果:


产生不真实效果的原理

从图上看就非常明显了。当我们的观察方向在法向量右边时,没问题,反射方向和视线的夹角theta不会大于90度。但是,如果我们的观察方向在法向量的左边,我们的观察方向和反射方向的夹角就可能大于90度了。这种情况下,误差就会产生。

Blinn-Phong光照模型

1977年,一个名叫James F. Blinn的人提出了另一种计算镜面高光的方法。运用这种方法的Phong光照模型就称为Blinn-Phong光照模型。从名字上就可以看出,这种模型并没有对Phong模型进行大改动(否则就是Blinn光照模型了)。没错,它只是对计算镜面高光的算法进行了改动,换了一种镜面高光的计算方法。

Blinn的镜面高光计算原理是:不用反射向量计算,取而代之的是用一种名叫半角向量(halfway vector)的向量代替。半角向量是根据观察方向和光线方向来进行计算的,取观察向量和光线向量夹角的一半作为新向量的方向。这样,观察方向和反射方向的夹角就无关紧要了:


半角向量的原理

这样,当观察方向和反射方向就完美的重合时,半角向量就进化成法向量了。

让我们来看看如何计算这个半角向量。这里有一个简单的公式:


半角向量计算公式

公式非常简单,还记的向量相加的意义吗?没错,就是将第二个向量平移到第一个向量的终点,然后从第一个向量的起点到第二个向量的终点所形成的一个新向量。我们将光线向量和观察向量都规范化,这样相加得出的向量必定能平分两个向量的夹角。最后,再将其规范化成单位向量就大工告成了!

用GLSL来实现就是:

vec3 lightDir = normalize(lightPos - FragPos);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 halfwarDir = normalize(lightDir + viewDir);

于是,镜面高光量的计算就变成了:

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

使用法向量和半角向量来代替观察向量和反射向量计算点积,再计算光泽度的幂指数值,就成为了镜面高光度。

好了,Blinn-Phong光照模型就这些东西,简单吧?编译运行代码,我们来看看结果:


Blinn-Phong光照模型的高光计算

还有一点微妙的区别是,通常反射向量和观察向量的夹角要比半角向量和法向量的夹角要大些。因此,如果想要用Blinn-Phong模型得到类似Phong模型的效果,计算时,用的光泽度信息要大点。经验表明,Blinn-Phong模型的光泽度大小要是Phong模型的2到4倍。

下面两张图显示了两种模型在同一个角度观察的显示区别。Phong模型的光泽度为8,Blinn-Phong模型的光泽度为16:


PHONG

BLINN_PHONG

在同一个位置就可以很明显地看到区别,使用Blinn-Phong模型的光看上去聚拢程度更高。相对而言,Blinn-Phong的效果就更加真实。

最后,给出一个观察相同角度不同模型的小技巧。我们可以在片元着色器中定义一个bool变量用作开关,当按下键盘上的b键时,开启Blinn-Phong模式,再按一次b键就关闭Blinn-Phong模式。这样,就能很明显地看出差别。修改后的片元着色器代码如下:

if (blinn) {
    spec = pow (max (dot(normal, halfwayDir), 0.0), 16.0);
}
else  {
    spec = pow (max(dot(viewDir, reflectDir), 0.0), 8.0);
}

最后,按照我们一贯的作风,提供完整的代码以供参考。

总结

在这一章中我们就只学了一个知识点就是Blinn的处理镜面高光的方法。简单点说,就是使用法向量和半角向量的点积值代替Phong模型中反射向量和观察向量的点积值。半角向量是光线向量和观察向量相加的结果向量,表示平分两个向量的夹角。在结束的时候,提到了由于夹角值的差距,使用Blinn-Phong模型计算高光时要将光泽度信息设置成Phong模型的2到4倍较为合适。

好了,学习结束,休息、休息~

下一篇
目录
上一篇

参考资料

www.learnopengl.com(非常好的网站,建议学习)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容