今天给大家分享的是一种以较低成本实现对大尺寸kernel卷积算法模拟的技术,原文链接在文末的参考中有给出。
1. 摘要
这里给出了一种大尺寸kernel卷积计算的模拟方案,这种方案从本质上来说是通过对多个不同kernel下box filtered的image的加权混合。
大尺寸kernel的卷积算法在图形学中有着重要的应用,但是其计算消耗过高,难以做到实时效率。
本文介绍的算法由两个下采样+两个上采样组成,这两个phase都可以在GPU上完成,整体算法的复杂度只取决于输入贴图的分辨率,不受kernel尺寸影响,因此 适合用于一些在实时渲染中需要大尺寸采样的场景,如
- 非均匀模糊
- irradiance probe生成
- ray-traced glossy GI计算
2. 介绍
在图形学中经常会遇到需要使用大尺寸kernel进行卷积计算的应用场景,比如DOF,又比如高斯模糊(高斯模糊在SSAO以及SSR中经常会有应用,其关键作用在于消除高频噪声从而实现空间与时间层面的效果稳定)。
直接进行卷积运算的限制在于kernel越大,消耗越高,在实时渲染场景中会存在诸多约束。
贴图的mipmap生成是一项十分成熟的技术,其具体实现是通过box filter进行混合来完成的,且由于驱动层面的优化以及硬件自带的双线性混合指令的支持,通常具有十分高的效率。
基于上述结论,这里给出了一个对大尺寸kernel卷积运算的模拟方法:通过对多个box-filtered的mipmap进行加权混合,可以得到接近真实卷积算法的效果,且计算复杂度与kernel尺寸无关,只取决于输入贴图的分辨率,此外,这种方案对于GPU的Cache十分友好。
3. 前人工作
3.1 Kawase Filter
其基本思路是通过多个小尺寸kernel的硬件采样(box filter?)pass实现对高斯模糊的模拟,这种算法有如下一些特点:
- 各个硬件采样pass都是在原始贴图上完成,分辨率相同,各kernel尺寸也都是相同,因此每个pass的时间消耗都是相同的
- 具有比原始的大kernel高斯模糊更优的性能
- 不适合用于计算DOF等各个采样点具有不同加权值的应用场景
这种算法通常在HDR的Bloom中有较多应用。
3.2 Heat Diffuse Equation
这是为DOF而设计的低成本采样算法,其最初的Solver是CR Solver,后面有人为更好的利用GPU并行计算能力而设计了一种新的Solver——Vanila Solver
3.3 Central Limit Theorem
高斯滤波可以通过多次box filter来模拟
3.4 Bilateral高斯滤波的近似模拟
高斯滤波可以通过分割成多个pass来进行加速
3.5 本文算法
直接通过多个box filter的线性混合实现对高斯模糊的模拟,更为高效
GI的计算有两个部分:
Diffuse
irradiance probe通过SH进行表达,SH系数通过对irradiance environment map在离线模式下采样得到,radiance transfer也是预计算的。
specular
为了计算效率,通常是通过importance sampling(利用启用的计算方法,将采样点的数值除以对应的概率分布函数的取值,之后求平均值,实现对函数的积分模拟)计算得到,而在Specular BRDF中,菲尼尔项以及可见性项由于跟视线有关,需要在运行时实时计算,法线distribution项依然是离线计算的。
本文的算法可以用在diffuse的irradiance probe以及specular的菲尼尔+可见项计算。
4. 具体方案
4.1 算法管线
主要思路是通过多个box来拟合bell-shaped kernel,关键在于如何找到各个box的权重,而实际上当box级数越多,两级之间尺寸差距越小,这个结果就越精确。
整个算法由两个phase组成:
1. 下采样:通过box filter对原始贴图进行下采样,生成多级mipmap,可以用p_down表示
2. 上采样:对p_down采用一个特定的kernel进行上采样,结果为p
这里 p(0)分辨率最高,p(3)分辨率最低,上采样的计算公式给出如下:
其中:
进一步推导:
总结一下规律:
- mip分辨率越低,权重越高
- 多级mip权重之和为1
- 权重的计算与原始kernel有关
4.2 数学推导
基础公式为:
其中:
- p是经过kernel卷积后的输出结果
- x是被采样像素到当前像素的偏移
- f是kernel函数
- 是原始输入贴图
- 是第l级的mipmap
- 是第级mipmap的权重
box filter的公式给出为:
其中这个公式是有应用范围的:
box filtered贴图可以表示为原始贴图按照一定权重与范围加权输出的结果,而权重对于每级mip来说是一个常量。
根据上面两个公式,经过推导,可得kernel函数跟各级mip之间权重的关系:
4.2.1 权重计算
这里先对B做一个近似,或者说约束:
这里的近似的含义是将低于L级的mip数据都扔掉,通过不低于L级的mip来实现对原始贴图在kernel下的模拟,这种模拟是有精度损耗的,查看前面的bell-shaped图可以看到,相当于将bell的顶部删除了,且L越大,精度损耗越大。
在上面的约束下,kernel函数也可以得到一个近似:
在这种情况下f(x)可以转化为L的一个函数:
有人会想,实际上f(x) = g(0)是更为精准的表达?实际上,这里f(x)并不代表整个kernel,而是代表在x-y坐标系中某个坐标为(x,y)的点的取值(这里y被省略),而这里这个等式的含义在于将自变量从x,y转换为l,l表示的是当前mipmap的级数(可以先忽略mipmap是离散的事实,将之当成连续的来看)
由于g(m) = 0 (bell-shaped函数,m越大,权重越低,如果m趋近无穷,那么权重就趋近0),那么g(L)可以看成是-(g(m) - g(L)),括号内的内容可以看成是g'(x)在[L, m]的积分:
根据上面公式,从而可以求得权重的近似公式:
这里的一个问题是,目前只知道f(x)而不知道g(l),g(l)跟f(x)要怎么对应起来呢?后面的推导中有说明,这里是通过范围边界完成x与l之间的转换的,如x2+y2 <= 4^l/pi,就可以取边界条件等号实现两者之间的转换,从而在已知f(x)的情况下,可以转换得到g(l)。
5. 具体应用
5.1 贴图模糊
高斯函数实现贴图模糊时,对应的g(l)可以表示为:
5.1.1 推导
x,y相互独立的二维高斯分布函数可以表示为:
而之前的范围约束条件,以像素为单位,可以得到如下的公式:
边界情况,取等号,根据最后一个公式,可以得到前面的结果,用L来取代x,y是为了求取每一级的权重w(l),问题是,为什么这里要取边界的等号?
这里实际是相当于将采样kernel的范围变成了一系列的同心圆,根据x2+y2可以锁定同心圆的半径,根据半径则可以找到对应的mipmap层级与之对应(这里先抛开mipmap是离散的不看,假设是连续的),通过mipmap的正方形面积与圆形的面积近似来算得。
这个函数具有如下的极限特性:
根据
可以得到权重公式:
而权重积分公式给出如下:
从而可以得到逐级累加权重公式:
5.2 Irradiance Map计算
虽然正常情况下不太可能在运行时来计算Irradiance Map,这种方案在实际工作中用不上,但是可以参考这里在cubemap上如何进行filter加速的逻辑。
权重为余弦值,其公式给出如下:
s为单个cube surface的像素数目,为何要除以s?完整的公式为(pi/4) * (2^L/s),第一部分为最大的FOV/2,这是最高一级mipmap覆盖的范围,第二部分为跟随mipmap级数L而增加的比例。
根据前面一样的方法,求得逐级累加权重:
A与B的取值:
5.3 单采样Raytracing GI
整个渲染流程,包含4个pass:
- G-Buffer,生成Depth,Normal以及MaterialData等数据
- Raytracing,对屏幕上每个点,沿着视线的镜面方向追踪到碰撞点,取碰撞点位置处的直接光照作为反射radiance,取到碰撞点的追踪距离作为distance,上述两个数据存储在屏幕空间中,作为反射贴图。
- downsample,跟之前一样,使用box filter求得上述各个贴图的mipmap
- upsample,按照前面介绍的逐级上采样公式,计算各级近似kernel-filtered的上采样结果。
GGX权重计算公式:
其中:
- r是前面反射贴图中的distance数据
- Mp是相机投影矩阵
- sx,sy表示viewport尺寸
- z是view space中的线性深度
- N跟V分别代表法线与视线方向
- a是GGX模型中的粗糙度
混合因子计算:
由于GGX过于复杂,无法求取权重的积分,因此这里是采用累加的方式来给出的(这也给其他无法积分的应用情景提供了参考方法)。
6. 效果
行数从上到下依次是高斯模糊、Irradiance Map以及Raytracing Glossy GI效果,列数从左往右依次是Ground Truth、本文方案,以及其他方案
7. 结论
从效果对比上来看,高斯模糊等模糊类方法使用本文方法基本上差不多(毕竟已经糊成这样了)。
性能数据:
模糊是接近8倍的时间差距,GI则是接近100倍的差距。
Irradiance Map与Glossy GI效果上差距还是挺大的,不过考虑到性能对比,也不是不能接受,据作者说,主要质量损失来自这个公式( Because the sample from a mipmap is actually a bilinear interpolation among 2 × 2 box-filtered pixels (average value of a tile as a pixel) rather than the box filter of each pixel as the center, it will result in some little high-frequency losses, 从mipmap上的采样,实际上是根据采样点位置自动根据双线性插值求得的一个混合值,实际上这里更希望以像素为中心进行box filter?(无法理解,怎么就引入高频噪声了?再说了,想要采像素中央,只需要将采样位置设置为四个像素正中心就好了呀?另外,由于多级贴图本身尺寸是按照2的倍数来创建的,本身应该自动对齐,不需要做额外处理才是?或者这里理解存在偏差?)前者引入了一定的高频噪声),后面想要提升质量,可以在这个公式上下功夫:
其他使用大尺寸kernel的方案也可以考虑通过这种方式来优化,比如AO?作者也会考虑不断优化算法减少误差(不知道是不是表面话还是future work套话)
8. 参考
[1]. The Power of Box Filters Real-time Approximation to Large Convolution Kernel by Box-filtered Image Pyramid
[2]. 【论文复现】The Power of Box Filters