RTRT(Real-Time RayTracing)

2018提出了GeForce的RTX架构,之后不断发展

What Actually Do?

同时考虑阴影、AO、反射、GI——实际上来讲,这是一种优化用于在GPU计算的硬件方法用于加速光线追踪(加速求交的逻辑) 最后的效果是我们可以允许每一个像素可以采样一个光路样本来获得最后的渲染效果表现。(1spp) 为了得到全局光照我们考虑的就是一次直接光照+一次间接反射+一次二次反射的效果。 这种逻辑上,我们是先做一次光栅化做一次初始的渲染然后后边进行二次渲染。

对于1spp的效果,显然会有及其大的噪声,因此对于RTRT最关键的逻辑就是降噪处理。 降噪的处理技术应该例如State Of Art通过降噪来获得高质量的渲染效果。

Denoise(With 1 Spp)

  • 没有过度的模糊处理
  • 没有渲染的错误表现
  • 保存所有的细节处理
  • 速度要小于2ms来将所有帧率降噪

之前有一些SF\AAF\FSF\MAAF 不过这些工作对效果的加速无法达到需求,基于离线的降噪方法类似于IPP\BM3D\APR等也很困难。 针对深度学习类的CNN AutoEncoder是一些高度复杂度结构,时间是无法进行优化到实时端。、

Temporal

为了优化表现效果,我们使用时间上的滤波办法; 这是一种递归的算法:

  1. 我们假设上一帧是滤波好的帧,我们假设这个场景的运动是连续的(相机有一定的运动逻辑)
  2. 我们利用Motion Vector将运动的两帧关联起来,将上一帧物体位置根据MotionVector找到对应的物体,这样可以复用上一帧来获得原有效果的帧沿用指导效果,是一种增加spp的逻辑。
  3. 我们在进行屏幕空间坐标的反结算世界坐标时,我们直接反过来算逆变换就可以得到世界坐标(不过x需要是一个z-buffer的深度值才能进行合理的反演。)、且我们可以求出对应的motion矩阵,将Motion矩阵反演乘你坐标,这样就可以采集到对应帧的上一帧坐标。

同时也是是TAA的实现的逻辑。求光流是option flow的逻辑,利用深度学习的方法效果没有过于优化这个地方的逻辑。

因此,我们把公式记录为: 注意,这里上一帧的权重很高,这也是工业界进行优化的一个主流方式。

The G-Buffers

  • 常用于延迟渲染的中间数据。在渲染中我们可以存储一些额外的信息来辅助我们的渲染逻辑进行,例如逐像素深度、法线、世界坐标等。不过G-Buffer仍然属于存储世界坐标。

1spp Ray Traced GI

  • 其实部分的白色部分光照是由于显示器的clamp导致的。正常的真实的像素光线暗下来大部分原因是由于噪点的部分RGB值超过了LDR显示屏的显示效果,而无法正常显示。从HDR效果的显示屏来看对应的效果会得到更优秀的效果(或者预处理时使用tonemapping)
  • 注意,滤波不会使得画面变暗,变暗的原因主要因为HDR的image呗Clamp导致的。 下面附1sppray+denoise效果和RayTracing的不同逻辑的对比: 比较明显的差异在于:我们的AO效果的接触阴影差强人意。

Temporal Fails

  1. 场景切换/光照/分镜切换有巨大切换的效果时失效;
  2. Screen Space Issue:由于屏幕空间的信息过少,我们对于多反射的光线场景中,我们的Gbufer里面的参考不足以cover图像外产生的对应信息(比如相机倒着运动)
  3. 突然出现的新信息:Ghost Shadow Case:我们的视野效果都完全没有动,而遮挡信息发生了变化,这种遮挡的错误呈现会导致发生鬼影的状态效果。
  4. 移动速度过快的时候,会有严重的拖影
Other Fails From Shading
  • 考虑栅栏的场景,只有光源发生了移动,这样我们的Motion Vector是0,会导致阴影有强行的滞留效果,导致了motion fails。
  • 对于glossy的地面反射,由于我们的反射物体变动时地板的motion vector是不变的,所以反射的vector会有严重的滞后性。

Adjustments

  1. 我们先迭代到足够接近的位置再进行插值、多引入当前帧的信息(当然这样噪声会过多)
  2. 我们可以利用obj的id,对TAA迭代的时候,判断现在的对应帧物体的id是否真的正确对应上,用于判断我是否还能沿用上一帧的效果。

灵感来源于TAA、在一些品类中优化的时候是可以用的,对于特化进行处理时可以使用的。

Implementing a spatial filter

利用Gaussion/Box等Filter算法进行滤波的处理,进行高通/低通滤波,这里的逻辑可以简要参考积分变换中的逻辑来判断对应的实现逻辑。 注意,利用Gaussion/Box Filter进行贡献的时候,由于我们有均一化的逻辑,利用这种均一化的处理,我们的高斯核等能量能够保证是守恒的。

Bilateral Filtering(双边滤波)

  • 高斯滤波的结果会产生均等的模糊,会将边缘部分也进行模糊处理: 保存边缘:利用颜色的差异情况,保证差分效果,减少滤波的贡献。利用差异项作为参数来限制滤波的模糊权重。
w(i,j,k,l)=exp((ik)2+(jl)22σd2I(i,j)I(k,l)22σr2)w(i, j, k, l) = \exp\left(-\frac{(i - k)^2 + (j - l)^2}{2\sigma_d^2} - \frac{\|I(i, j) - I(k, l)\|^2}{2\sigma_r^2}\right)

可以将在边缘保持锐利的情况下保持其他部分的细节。

有一个显见的问题:我们在进行Path Tracing进行降噪操作时,我们并不能通过直接的颜色差来判断是否是边界:你无法在高噪声的场景下分辨边缘和噪声程度不同导致的颜色差异。不过对于正常的图像来说足够优秀。

Joint Bilateral Filtering(联合双边滤波)

高斯滤波考虑了绝对距离作为贡献,而在双边滤波中,我们引入了颜色距离的概念同时作为权重;因此,显然的我们可以提供更多的参数来控制逻辑——Joint/Cross Filtering。这种方法很擅长于优化Path Tracing的模式。 在渲染中,我们在Gbuffer中有位置信息/法线信息以及basecolor信息;因此我们有简单的方式能够得到更多的信息来优化噪声。

  • Gbuffer是无噪的信息

注意:不需要考虑距离问题也不需要考虑是不是归一化的正则化、也不一定要用高斯核进行处理; 针对不同的Filter核我们有不同的表现效果。

实现

假设我们拥有深度、法线以及颜色的信息; 那么对于一下情况,我们不希望进行滤波:

  1. A B的深度差很大
  2. B C的法线方向有差异(不应该是在相同面上)
  3. D E颜色上来说有差异说明不是同一位置。

联合效果就是高斯核的联合加权逻辑。在实现中,根据画面效果调优出合理的参数

Implementing Large Filters

对于每个像素,我们loop每个像素周围N * N个像素进行,但这个逻辑的复杂度会显见的变大,影响速率

fft的gpu加速没有优化太多,常规的逻辑不怎么考虑。因为正逆变换的效率很低。

Solution1:双Pass Filter滤波

我们进行一次水平滤波后在进行一次垂直滤波,再进行叠加——N2复杂度的逻辑优化到N+N的复杂度。这两种逻辑是完全等价的,即使这是一个两趟的逻辑。

二维的高斯函数是在数学上相互独立的,因此我们可以把一个高复杂度的2d算法拆解为一个两趟的算法,由独立性来讲,可以直接分离计算。

Solution2:Progressively Growing Sizes

利用层次思想优化Filter:我们从小的Filter开始逐级叠加,利用金字塔型的组合逻辑来实现逐级增加的逻辑,多趟实现一个大的滤波(trous wavelet)。

稀疏采样的目的可以减少频谱的混叠从而减少对应和部分的走样,应用更大的滤波也可以理解为提取逻辑中更低频的信号信息。

OutlierRemoval

在正常的着色逻辑中,能够合理映射的范围只是0-255内,而对于蒙特卡罗方法,进行迭代加和后,会出现一些超级亮的点,这些点只使用滤波时会有雪花屏的影响,很难以补偿解决。(LDR的颜色范围内,亮的点会被扩散成更大的白色噪点。) 我们把过亮范围内的颜色值解决为Outlier。(firefly)

  • Idea:这个过程会影响滤波,因此我们为何不在滤波之前预先解决掉这一部分的问题? (如果想要得到准确的结果,应该等待更多采样来降低bias贡献和,因此这个过程如果进行了detection和Clamping的话,能量并不守恒。) 我们利用均值和方差的逻辑进行阈值判断,将超过阈值的部分视为Outlier;针对超过这个范围内合理范围的颜色值,我们将其clamp到相应的位置(也就是说,根据卷积核的情况不同,对应的removeal算法也并非是稳定的取值。)

我们只是将其clamp到有效的范围内(这个范围可能会在颜色空间上应用高斯的描述效果来更深入的进行范围滤波后的颜色优化逻辑),并非是直接扔掉了这一个点。

其实这种Clamp的逻辑也和后边Temporal Clamping的优化逻辑相似,那个噪声小取那边的效果做相应的优化处理。 我们只是把相应的clamp逻辑优化处理为利用迭代的范围,将outlier的颜色约束到合理范围内解决。

SpatioTemporal Variance-Guided Filtering(SVGF)

  • 是一种降噪的操作,不过有更多的Trick等更加优化;基于vector的算法

Filtering Guiding

Depth

深度参考指数:这是一个指数衰减逻辑,但是并不是类高斯函数;小的分布子项作为平滑核防止除零

wz=exp(z(p)z(q)σzz(p)(pq)+ϵ)w_z = \exp\left(-\frac{|z(p) - z(q)|}{\sigma_z |\nabla z(p) \cdot (p-q)| + \epsilon}\right)

理解:A-B在统一平面,应该有相互贡献,而只考虑深度时,他们不应该有明显的相互影响,这两个逻辑相悖。而我们的分母处存在p-q的梯度映射,通过一个梯度映射的scale放缩,我们就能解决这一点的贡献逻辑。

其实从这一角度来讲,我们其实是把对应的距离理解为在对应物体根据法线的切平面方向得到的对应深度差判断

Normal
wn=max(0,n(p)n(q))σnw_n = \max(0, n(p) \cdot n(q))^{\sigma_n}

整个场景在不应用法线贴图时,我们直接应用macro的法线就可以进行合理的判断clamp了。一般情况下我们会采用没有应用法线贴图的normal应用。(指数项用于控制高光强度)

Luminance

利用标准差和gfilter进行随时间的平均,可能会有噪声的估计误差,因此在再次计算之前的权重再最后进行一次计算,以避免颜色的误差影响对应项权重。 使用Luminance也是再hdr情况下的优化,如果为RGB空间利用RGB颜色处理也是相同情况。

wl=exp(li(p)li(q)σlg3×3(Var(li(p)))+ϵ)w_l = \exp\left(-\frac{|l_i(p) - l_i(q)|}{\sigma_l\sqrt{g_{3\times3}(\text{Var}(l_i(p)))}} + \epsilon\right)

Failure Case

只有光源移动而物体没有移动端时候,对应的阴影会产生拖影。

RAE

  • 是一种基于深度学习的方法,是一种图像空间的后处理,用神经网络进行优化(需要利用Gbuffer优化)。
  • 再latent的高维空间进行优化,利用U-Net网络进行图像优化,才利用每一层都是用convolutional block,在每一层的网络自己循环的同时,也保留上一帧的信息,利用学习过程先encoder再恢复decoder。
  • 没有使用Motion Vector的匹配——后边也会有Transformer的进行优化。

Bias

会有残影残留问题+效果没有更加的优秀,showcase部分没有优于svgi,并且有shadow以优化表现的嫌疑。