现代OpenGL+Qt学习笔记之十一:使用halfway向量提高光照计算效率
主要内容
本文介绍另一种光照计算的方法,可以减少光照计算的效率,当需要计算光照的的顶点/片元的较多时,使用该方法可以提高着色器的运行效率,从而提高渲染效率。
halfway向量
现代OpenGL+Qt学习笔记之七:Phong光照及在GLSL中使用函数一文中已经介绍了Phong光照模型的原理及计算方法。本文将对镜面反射光强(specular)成分的计算方法进行优化。从而达到提高光照计算效率的目的。
在之前的介绍中,镜面反射光强的计算是通过下列公式实现的:
其中向量 r 是光的反射方向, v 是反射点到观察点的方向。向量 r 的计算公式为:
共需要进行一次点乘运算、一次加法运算和多次乘法运算。下面就引入halfway向量 h 来简化镜面反射光强的计算。
我们定义 h 为如下向量:
各向量之间的关系如下图( h 在使用前需要进行单位化):
注意到 n 是向量 r 和 s halfway向量,而 h 是 v 和 s 的halfway向量,不难证明, v 和 r 之间的夹角是 h 和 n 之间的夹角的两倍,因此 r⋅v 也是与 h⋅n 存在一定的正比例关系,因此在计算镜面反射光强时,可以用 h⋅n 代替 r⋅v ,虽然计算结果不一样,但是要表达的意义是一样的。即有:
这样做的好处很明显,就是不需要计算 s 而只需要进行一次加法计算就能得到 h ,计算量大大减小,计算效率自然会提高。
当然,在参数 f 一定时,镜面反射的效果会有所不同。
halfway向量的实现
使用这种方式计算镜面反射光强的方式非常简单,只需要修改相关着色器程序中的部分代码即可。在现代OpenGL+Qt学习笔记之七:Phong光照及在GLSL中使用函数一文源码的顶点着色器中,修改部分代码,首先删除计算向量 r 的行:
vec3 r = reflect( -s, norm );
而增加计算向量 h 的代码如下:
vec3 h = normalize( v + s );
再将计算镜面反射光强spec的语句改为:
spec = Light.Ls * Material.Ks *
pow( max( dot(h, norm), 0.0 ), Material.Shininess );
保存并运行程序,结果如下:
原始的未采用该方法计算的结果如下:
这里因为顶点较少,并没有列出运行时间比较性能,不过从计算方式上看,肯定是在性能上有所优化的。从结果上看,当参数 f 的值相同时,使用halfway向量的渲染结果的镜面区域更大。
源码地址:http://download.csdn.net/download/chaojiwudixiaofeixia/10014848