Glow的基本思路:
对场景渲染为2种纹理,一是正常效果的场景纹理,一是只保留高亮区域的高亮纹理(即辉光源,Glow Source)。把高亮纹理进行模糊处理后,再叠加到场景纹理上,就能产生类似HDR中Glare或Streak的效果。
简单测试效果如下:
Glow的效果和性能都让我非常满意。但是再进一步研究的话,比如motion blur,depth of field,lens effect(or ghost),这些如果都使用fake方式,那么每个效果都需要一个功能模块,结构会比较复杂。
如果使用HDR的渲染流程,则是;
1,渲染场景。
2,提取高亮区域。
3,对高亮区域应用bloom效果。
4,对高亮区域应用streak效果。
5,对高亮区域应用ghost效果。
……
很直观的逻辑。
另外HDR最吸引我的在于亮度范围: 亮的地方更亮,暗的地方更暗。 —— 真是很好的概括。
说到这里,不得不提及Game Programming Gems 4的一篇文章,介绍了通过动态调整Gamma来改变LDR图像中的色彩,以达到类似曝光调整的效果,性能和效果都十分令人赞赏。
HDR的流程大概为:
1,使用高亮度渲染场景,并保存为浮点数纹理。
- 应用HDR环境贴图。
- 应用高范围的材质,光源和照明模型。(即不必被局限在0~1里)
2,将高亮区域取出,保存为浮点数纹理。
- 在pixel shader里判断该像素的亮度是否大于阀值。
vec3 color = texture2D(scene, gl_TexCoords[0].st);
float lum = dot(vec3(0.3, 0.59, 0.11), color);
gl_FragColor.rgb = (lum > brightThreshold) ? color : vec3(0.0);
3,对高亮区域进行应用bloom滤镜。
4,对高亮区域应用streak滤镜。
5,对高亮区域应用ghost滤镜。
6,将scene,bloom,streak,ghost等合成为一张最终效果纹理。
7,对最终纹理应用tone mapping,及曝光调整。
HDR最广为人知的特征之一就是bloom,以至于不少人看到类似bloom或者glare的效果就高呼HDR,呵呵。
bloom的原理在于,将高亮的区域扩散出去。放在3D实现里则是,模糊高亮区域后叠加到原始图像上。所以,主要技术点在于“模糊”。
正如HDR之一中所提到的,模糊的常用方式有两种:2D高斯模糊和分步模糊。
2D高斯模糊 Multiple Gaussian Filter
2D高斯模糊能根据权重将范围之内的像素进行加权采样,以实现模糊的效果。但是一次高斯模糊并不能达到很好的效果,比如中间高亮,边缘扩散。因此需要对不同范围进行多次高斯模糊。然而大范围的高斯模糊开销极高,比如5x5的高斯模糊,处理每个像素时就需要25次纹理采样,以及更多次的浮点数加法和乘法。
分步模糊虽然能够把2D高斯模糊转换成2次1D高斯模糊,但是它在处理高分辨率图像时仍然比较高耗,适合于高精度格式的低分辨率图像处理。可以使用基于双线形过滤的Cone Filter:
streak 即星光效果,将高亮区域沿指定方向进行拉伸得到,本质上仍然是模糊的运用。Kawase同学在他的报告中介绍streak filter,类似于他的bloom filter,也是逐步扩大采样范围,具体参见他在GDC2003 的Presentation:Frame Buffer Postprocessing Effects in DOUBLE-S.T.E.A.L (Wreckless)。
测试用于X方向的streak,处理效果不错,但是用在浮点数纹理上开销很大,因为每个方向都需要进行数个Pass再叠加。而每个pass里又有数次采样再加权合成。
试验的另一种方法,使用two pass的分步模糊,分别沿“/”和“/”方向进行17次采样的1D高斯模糊。开销较小,但是streak的长度比较有限。如果加大采样的间隔,又会影响采样的效果。
Ghost效果,又称之为Sprites,或Lens effect。
传统算法(Sprites):
1,检测光源是否可见。
2,判断可见光源的可见像素有多少。
3,如果可见像素超过阀值,则渲染Sprites。
4,Sprites由多个billboard应用alpha贴图合成。
5,对场景中每个光源做以上处理。
HDR算法:
1,从场景中抽取高亮区域。
2,将高亮纹理进行关于屏幕中心的缩放。公式为:
texCoord = (texCoord-0.5)*(Scale) + 0.5;
Scale的正负和数值决定纹理被缩放的方向和尺寸。数值越大,越靠近中心,尺寸越小。
可以在pixel shader中一次进行4次缩放并叠加,比如{ 0.6, 2.0, -2.0, -0.6 },则一个光源变成共线的,尺寸对称的4个光源。对此再做一次处理,则变成16个。以此类推。
3,因为涉及到缩放,所以纹理被设为CLAMP。为了解决缩小后纹理出现边缘拉扯的情况,还需要引入一张mask纹理,
·优点
- 渲染质量高。
- 可以指定产生效果的光源。
- 光源数量少时开销很低。
·缺点
- 开销受到光源数量的影响。
- 不易处理任意形状的光源。
- 不易用于间接光源,比如高亮的反光。