APP下载

基于傅里叶级数的次序无关透明渲染算法

2021-07-09宋晓峰

现代计算机 2021年14期
关键词:半透明级数消耗

宋晓峰

(四川大学计算机学院,成都 610065)

0 引言

半透明物体的实时渲染是计算机图形学中的重要研究课题之一,在游戏、虚拟现实、仿真模拟等领域有着重要应用。传统的半透明物体渲染算法需要根据到摄像机的距离对半透明物体进行排序,然后由远到近依次进行绘制,然而当多个半透明物体之间遮挡关系比较复杂,或者单个半透明物体自身包含多层半透明面片时,这种传统方法不能得到正确的结果。为了解决这一问题,通常需要使用次序无关透明(Order Inde⁃pendent Transparency,OIT)渲染算法。

精确的OIT 算法一般使用深度剥离[1]或链表[2]来做像素级别的片元排序,虽然能够得到精确的结果,但是效率低下且显存消耗高。近年来,为了提升效率或节省显存,一些启发式OIT 算法相继出现。基于K-Buf⁃fer 的OIT 算法[3-4]能够有效控制显存的消耗,但是对于存在大量半透明物体的复杂场景表现较差。基于加权混合的OIT 算法[5-6]效率较高且易于实现,但是结果存在很大误差。基于矩的OIT 算法[7-8]使用矩信息来重建透射率函数,能够取得较好的近似结果,但是由于存储矩信息需要使用较高的精度,因而对显存的消耗仍然较高。

本文提出了基于傅里叶级数的OIT 算法,此算法借鉴了Fourier Opacity Mapping(FOM)一文[9]中的算法思想,即使用傅里叶级数来近似半透明物体对光的吸收率函数。同时,本文提出使用Lanczos-Local-Type σ-Averaging(简称σ-Averaging)方法[10]对FOM 的傅里叶近似方法进行改进,很大程度地降低了Gibbs 效应的影响。实验表明本文提出的OIT 算法可以得到较为准确的结果,同时具有较高的效率和较低的显存消耗,具有较大的实际应用价值。

1 算法实现

1.1 使用傅里叶级数近似透射率函数

给定同一像素坐标下的n个片元,片元颜色依次为l0,l1,…,ln-1,片元透明度为α0,α1,…,αn-1,片元深度为z0,z1,…,zn-1,则对所有片元进行颜色混合之后的结果L可以使用公式(1)计算得出。

其中,T(z)是透射率函数,表示从深度z处发出的光线,在穿过半透明物体之后,最终到达摄像机的光线的占比,其计算方法如公式(2)所示。从公式(2)可以看出,为了计算透射率,需要知道一个片元被其他片元的遮挡情况,这通常需要存储片元的深度值,并对片元按照深度值排序之后依次进行混合计算,因而直接使用公式(2)计算透射率的算法往往具有高昂的显存消耗与计算代价。

为了能够更加高效地计算透射率,本文算法使用了傅里叶级数的前m(m∈N*)项和来近似透射率函数T(z),计算方法如公式(3)所示。

其中Ak与Bk为傅里叶级数的系数,其计算方法满足公式(4)与公式(5)。公式(3-5)的具体证明过程可以参考Fourier Opacity Mapping 一文[9]。

相较于片元排序方法,使用傅里叶级数近似透射率函数的好处包括两点:①透射率的计算不依赖于半透明片元的执行顺序,不再需要对片元进行排序,因而效率更高;②由于不需要对片元排序,因而不需要存储片元深度及其材质信息,作为替代,存储的是具有更低显存消耗的傅里叶级数系数,因而节省了显存消耗并降低了读写显存的时间代价。

1.2 结合σ-Averaging方法减弱Gibbs效应

使用傅里叶级数来近似透射率函数会产生Gibbs效应,该效应主要发生在透射率函数的阶跃点附近,表现出明显的过冲与下冲(如图1 中绿色曲线所示),从而导致计算得到的透射率存在较大的误差且波动较大。为了减小误差,本文采用了σ-Averaging 方法,该方法为傅里叶级数添加了一个σk系数,能够明显地减弱Gibbs 效应的影响(如图1 中红色曲线所示),σk系数满足公式(6)。

图1 Gibbs效应以及σ-Averaging效果示意图

在结合σ-Averaging 方法之后,本文使用公式(7)来计算透射率。

其中指数p∈R*用于调整σk的影响强度,p值越大,Gibbs 效应越弱。然而p值过大时,会导致阶跃点处曲线过于平缓,反而会增大误差。本文算法采用p=1.0,可以大大减弱Gibbs 效应的影响,同时阶跃点附近的误差也可以接受。

1.3 渲染算法

本文渲染算法的实现分为以下四个步骤:

步骤1:渲染场景中的不透明物体,将渲染结果保存到纹理Tex0 中。此步骤中不透明物体的渲染可以使用任意渲染算法来实现。

步骤2:渲染场景中的半透明物体,结合公式(4)与公式(5),为每个像素计算傅里叶级数的系数,并将系数值保存到纹理Tex1 中。由于每个像素都单独对应一个透射率函数,因而每个像素都需要做一次傅里叶级数展开近似,即像素间的傅里叶级数系数相互独立,需要分开保存。

对于单个像素而言,需要遍历该像素下的所有片元,计算每个片元对傅里叶级数系数的贡献量,即:

然后将每个片元的贡献使用Blend One One 的方式累加到纹理Tex1 中,便可得到该像素下的最终系数,即公式(4)与公式(5)的计算结果。

注意在步骤2 执行渲染前需要关闭深度写入与背向面剔除,这样才能保证所有半透明片元不被丢弃。此外,由于此步骤执行渲染只是为了计算傅里叶级数的系数,因而无需进行光照计算等任何无关操作,从而保证算法的高效性。

步骤3:再次渲染场景中的半透明物体,对于每个像素的每个片元,读取步骤2 中生成的纹理Tex1。

使用公式(3)计算透射率,然后使用公式(1)计算该片元对像素颜色的贡献,即:

然后将每个片元的贡献使用Blend One One 的方式累加到纹理Tex2 中,便可得到该像素下的最终颜色,即公式(1)的计算结果。注意此步骤与步骤2 类似,在执行渲染前同样需要关闭深度写入与背向面剔除。

步骤4:读取纹理Tex0 与Tex2,将两张纹理颜色进行合并,即可得到最终的渲染结果。纹理颜色的合并计算方法如公式(11)所示。

其中Ctrans是半透明物体的颜色,存储在Tex2 纹理的RGB 通道中;Copaque是不透明物体的颜色,存储在Tex0 纹理的RGB 通道中;K是为了归一化而引入的项,存储在Tex2 纹理的Alpha 通道中,K的计算满足公式(12)。

Ttotal是总透射率,满足公式(13)。

2 实验结果

本文实验所使用的硬件为NVIDIA GeForce GTX 1060 3GB GPU 以及Intel Core i5-7400 CPU。实验结果的渲染分辨率均为1600×900。

2.1 σ-Averaging方法的有效性验证

图2 展示了原函数较为复杂的情况下σ-Averaging方法的效果,图中绿色曲线是使用公式(3)做傅里叶级数近似的结果,红色曲线是结合σ-Averaging 方法之后,即使用公式(7)做傅里叶级数近似的结果。可以看出,σ-Averaging 方法明显地削弱了Gibbs 效应,与原函数更加接近。

图2 σ-Averaging方法效果示意图(m=16, p=1.0)

表1 给出了使用与不使用σ-Averaging 方法这两种情况下的傅里叶级数近似结果的误差,误差采用RMSE(Root Mean Squared Error,均方根误差)作为衡量标准。从表1 可以看出使用σ-Averaging 方法的误差明显更低,且当m取值较小时,使用σ-Averaging 方法的优势更为明显。注意由于OIT 算法只需要使用阶跃点处的透射率,因而此实验中计算RMSE 时只考虑了阶跃点。

表1 使用σ-Averaging 与不使用σ-Averaging 两种情况下的傅里叶级数近似结果的误差对比

2.2 不同算法的渲染结果对比

此实验对比了WBOIT 算法[5]、MBOIT 算法[7]以及本文算法的渲染结果,实验中使用基于链表的OIT 算法[2]作为参考标准,并使用RMSE 用于衡量渲染结果的误差。本文在WBOIT 对比算法的实现中使用了Mc⁃guire 等人于2017 年提出的新的加权混合公式[6],在MBOIT 对比算法的实现中使用了四阶矩。本文算法的实现中使用了傅里叶级数的前四项,即m=4。

从图3 可以看出,WBOIT 算法的渲染结果存在明显的错误,误差较大。MBOIT 算法与本文算法的误差较小,渲染结果与Ground-Truth 算法之间没有明显的差别。虽然MBOIT 算法的误差小于本文算法,但是其显存消耗更大且效率更低(见表2~5)。图4 对比了渲染复杂模型时不同算法的渲染效果与RMSE,可见WBOIT 算法的误差仍然最大,MBOIT 算法与本文算法的误差相近。(算法性质决定了MBOIT 算法在片元数目n取值较小时具有更小的误差,n取值较大时其误差与本文算法相近)。

图3 不同算法的渲染结果对比

图4 不同算法的渲染结果对比(复杂模型)

2.3 不同算法的渲染效率与显存消耗对比

表2-表5 给出了不同场景下四种算法渲染一帧消耗的时间以及每个像素需要使用的显存。实验使用了如图5 所示的四组不同场景。从表中可以看出在不同场景下,本文算法的渲染用时与显存消耗均仅高于WBOIT 算法,相比MBOIT 算法具有明显优势。

表2 渲染效率与显存消耗对比(场景1)

表3 渲染效率与显存消耗对比(场景2)

表4 渲染效率与显存消耗对比(场景3)

表5 渲染效率与显存消耗对比(场景4)

图5 实验所用场景示意图

3 结语

本文给出了一种实时的次序无关透明渲染算法,该算法使用傅里叶级数近似透射率函数,并使用σ-Averaging 方法来减弱Gibbs 效应。实验表明,本文算法既有较好的效果,又有较低的计算代价与显存消耗,适用于实时渲染领域,具有很大的实际应用价值。在未来的研究工作中,具有前景的改进方向之一是寻找一组更合适的基函数来取代傅里叶基(例如使用小波基),可能进一步提高算法的精确度,或者减少存储消耗。

猜你喜欢

半透明级数消耗
无穷级数敛散性的判别方法探讨
月球上的半透明玻璃珠
那头,此岸
学会爱自己
二重Dirichlet级数在收敛半平面内的增长性
一个非终止7F6-级数求和公式的q-模拟
一年级数学期末小测试
半透明三维物体表面光泽真实感实时渲染方法
Clear Your Mental Space
If We Burne d All the Fossil Fuel in the World