什么是Bloom?
Bloom是由于透镜不能完美地让光线聚焦与同一点而导致图像上的高亮区域的颜色向周围溢出的效果。在渲染上,一般采取多次模糊的方式来实现颜色向周围溢出的效果
在opengl教程中是这样描述Bloom的实现思路:确定一个亮度阈值,提取当前Frame Buffer(HDR范围),计算当前Frame Buffer每个像素点的亮度值,若当前像素点的亮度值大于设定的亮度阈值,则将当前像素值写入一张RT中,随后对这张RT模糊,最后和原FrameBuffer相加
opengl教程的思路没有错,雀氏阔以实现Bloom效果,但这种方法得到的Bloom效果并不好。Bloom效果好不好看,关键在于
- Bloom的对象——该亮的地方特别亮,不该亮的地方别亮(否则画面整体都很模糊)
- Bloom对象的中心(亮度高的地方)特别亮
- 颜色向四周扩散的半径足够大(否则画面表现力不够)
- 更亮的颜色扩散半径更大;暗的颜色扩散半径更小,甚至于不扩散
UE曾在2016 GDC上分享过它们实现的Bloom算法,如下图所示。不难看出,好的Bloom算法,中间亮度应特别高,越向边缘走,亮度越低
为什么需要HDR?
计算机的精度是有限的,最终显示的颜色值都会被clamp在[0, 255],即使是HDR。那为什么还需要HDR呢?
HDR在这里的作用是为了更好的向外扩散的效果,高亮的颜色能有效地扩散到四周(因为模糊的本质是加权平均)
如何实现更大的扩散范围
都知道Bloom效果边缘的辉光效果是通过模糊效果实现的,那么如何扩大Bloom的扩散范围呢?
Jorge Jimenez在2014年Siggraph上分享过他实现的一种Bloom算法,这其中它通过边降采样升采样边模糊,并在最后将所有升采样得到的结果都叠加在一起来扩大Bloom的扩散范围
虽然这种方法雀氏可以扩大Bloom的扩散范围,但叠加多个模糊结果会导致最终的亮度值远超预期,设置是几倍之多,尤其是PBR中的高光部分,会异常明显!虽然Tone mapping阔以稍微缓解这一问题,但并非长久之计
为了解决这一问题,Jorge Jimenez提出类似高斯模糊的方式,在mip0、mip1间根据权重加权平均——weight = 1/(1 + Luma)
这一方法也有一定损失,会减弱Bloom的效果,但高光更加稳定!
更多的,还阔以在最后叠加时,除以降采样次数来削弱亮度暴涨的问题
总结Bloom步骤
- 第一次降采样时减去阈值并加权模糊
- 降采样 + dual blur
- 升采样 + 叠加到原图
- 最后除以降采样次数 * Bloom强度
效果
自定义的Bloom如下
unity自带的如下
代码仓库
https://github.com/chenglixue/Bloom
Comments | NOTHING