引言 本文翻译自 光綫追蹤降噪技術 ,概述光线追踪降噪方法,包含滤波、时空、采样和人工智能技术,以改进光追应用的收敛性和时间一致性。
蒙特卡洛光线追踪是一种基于随机样本的累积来近似给定场景的方法,一般来说该方法是缓慢的,但随着基于最新图形卡的实时光线追踪解决方案的出现,在去噪技术上的研究有了复苏。
这些去噪技术包括使用导向模糊内核的滤波 技术;机器学习 驱动的滤波器或重要性采样;通过更好的拟随机序列如蓝色噪音,以及时空累积的采样方案来改进采样 ;尝试用某种空间结构(如探针probes、辐照度缓存irradiance caches等)量化结果的 近似 技术
根据应用程序的权衡和需要,一个鲁棒的去噪器应该考虑使用所有 这些技术。
最近的研究集中在通过改进采样方案和用缓存的信息重采样像素,将降噪步骤移动到渲染早期。之前的研究集中在滤波、机器学习中的自动编码器、重要性采样和实时方法上。这些方法目前用于各种商业游戏和渲染器中。本文将讨论降噪及其实现的关键论文,重点在如何实现自己的鲁棒实时光线追踪降噪方法。
Prior Art
使用高斯 Gaussian、双边 Bilateral、多孔 A-Trous [Dammertz et al. 2010]、导向 Guided [He et al. 2012] 和中值 Median [Mara et al. 2017] 等滤波技术 对蒙特卡洛光线追踪图像进行模糊处理。特别是由特征缓冲区 feature buffers(如延迟渲染中的 common G-Buffer 附件:法线,反射率,深度/位置;以及特殊的缓冲区:首次反弹数据 first-bounce data,重投影路径长度 reprojected path length,或观察位置 view position)驱动的导向滤波器,已经在最近的论文和商业实现中使用。
虽然这些滤波技术是有效的且计算量小,但代价是有损的场景表示和高频信息如锐利边缘的损失。这种信息丢失非常严重,甚至会导致在处理带有椒盐噪声的高光或阴影图案中产生亮度水平上的差异。
机器学习 已经被广泛用于与降噪相关的领域,从一般的图像重建到通过使用降噪自编码器实现的实时光线追踪去噪[Khademi Kalantari et al. 2013] [Khademi Kalantari et al. 2015] [R. Alla Chaitanya et al. 2017] [Vogels et al. 2018],导向滤波技术[Wang et al. 2018] [Xu et al. 2019] [Meng et al. 2020],时空技术[Hasselgren et al. 2020],以及通过超分辨率/超采样来提高图像的分辨率,同时保持细节的方法 [Dong et al. 2015] [Ledig et al. 2016] [Xiao et al. 2020]。
Intel 和 NVIDIA 等行业领军企业支持了基于机器学习的去噪方法的研究,Intel Open Image Denoise 和 NVIDIA Optix Autoencoder 都使用自动编码器去噪,取得了巨大成功。NVIDIA 的深度学习超采样 (DLSS 2.0) 也被用于光追游戏中,如 Minecraft RTX,Control 等,通过深度学习提高分辨率来降低计算成本。
采样 技术在最新的论文中再度兴起。虽然 naive 版本的蒙特卡洛光线追踪只是简单地在一个不变的场景上累加样本,但是在一个移动的场景中重用样本是可能的。包括 TAA Temporal Anti-Aliasing [Korein et al. 1983] [Yang et al. 2020],时空滤波器 Spatio-Temporal Filter [Mara et al. 2017,时空方差引导滤波器 Spatio-Temporal Variance Guided Filter (SVGF) [Schied 2017],空间去噪Spatial Denoising [Abdollah-shamshir-saz 2018],自适应 SVGF (A-SVGF) [Schied 2018], 分开多阶特征回归 Blockwise Multi-Order Feature Regression (BMFR) [Koskela et al. 2019]
这些技术依赖于高频准随机序列 quasi-random sequences,如蓝噪声(与滤波结合使用)[Benyoub 2019],以及常见的工具,如 firefly rejection[Liu et al. 2019]、下一事件估计 next event estimation(NEE) 和重要性采样 importance sampling [Veach 1998]
最近,有人尝试通过 ray hashing [Pantaleoni 2020] 来减少采样的偏差或重用邻近采样数据[Bitterli et al. 2020],将降噪转移到渲染更早期的阶段中。
此外,还有 近似 技术,试图微调路径追踪器的各个方面。RTX Global Illumination 论文使用光探针 light probes 模拟全局光照,使用光线追踪来更好地确定每个探针的辐射度,并将探针定位在场景中,以避免 bleeding 或内部错误。RTXGI 最近被集成到商业游戏引擎中,如 Unreal Engine 4 和 Unity [Majercik et al. 2020]
Sampling SVGF 时空方差导向滤波 Spatio-Temporal Variance Guided Filter SVGF [Schied 2017]是一种使用时空重投影和特征缓冲驱动的双边滤波来模糊高方差区域的去噪方法。
Minecraft RTX 使用了 SVGF,并添加了辐照度 irradiance 缓存 ,使用光线长度来更好地驱动反射,以及对透光表面 (如水) 的分割渲染。SVGF 虽然非常有效,但在游戏中产生了明显的延迟。
A-SVGF 自适应时空方差导向滤波 Adaptive spatial - temporal Variance Guided Filtering, a -SVGF [Schied 2018] 改进了 SVGF,自适应的将之前的样本根据时间特征(如方差、视角等的变化)在空间上进行重新投影,在 Moment Buffer 中编码,并通过快速双边滤波器进行滤波。因此,与基于历史长度累积样本不同,采用方差的变化来决定旧样本和新样本的比例,从而减少重影 ghosting。SVGF 只使用 moment buffer 来做模糊,而 A-SVGF 则是既进行滤波有进行累积。
虽然引入一个 moment buffer 有助于消除时间延迟,但并不能完全消除它。积累样本较多的区域和新区域之间可能存在亮度差异。这在较暗的光线追踪场景,如室内尤为明显。为了缓解这个问题,与其使用 1 spp,最好在教案的区域使用 2 spp。
Quake 2 RTX 使用 A-SVGF 作为去噪解决方案。
ReSTIR 多光源光线追踪的时空重要性重采样 Spatiotemporal Importance Resampling for Many-Light Ray Tracing (ReSTIR) [Bitterli et al. 2020] 试图在渲染时将实时去噪器的时空重投影步骤提前,重用邻近采样概率的统计信息。本质上是对早期论文的结合,讨论了重采样的重要性采样 Resampled Importance Sampling,并加入了时空去噪的思想。
ReSTIR 将用于 NVIDIA 的 RTXDI SDK中。
Machine Learning 机器学习技术,如降噪自动编码器,样本图估计器驱动的样本计数或重要采样,神经双边网格滤波,超采样,虽然这些技术比其他算法如 A-SVGF 要慢,但在图像质量方面的改善最为显著。
OIDN
一个机器学习自动编码器,输入反射率 albedo,首次反弹法线,和你的输入噪声图像,输出滤波后的图像。
float * color;float * normal;float & output;unsigned width;unsigned height;oidn::DeviceRef device = oidn::newDevice (); device.commit (); oidn::FilterRef filter = device.newFilter ("RT" ); filter.setImage ("color" , color, oidn::Format::Float3, width, height); filter.setImage ("normal" , normal, oidn::Format::Float3, width, height); filter.setImage ("output" , output, oidn::Format::Float3, width, height); filter.set ("hdr" , true ); filter.commit (); filter.execute ();
Optix
NVIDIA 的 Optix 7 Denoising Autoencoder [R. Alla Chaitanya et al. 2017] 采用与 OIDN 相同的输入和输出,速度比 Intel 的解决方案快得多,但以质量要差一些。
OptixContext ctx; OptixDevice device; unsigned width;unsigned height;CUDABuffer denoiserState; CUDABuffer denoiserScratch; OptixDenoiser denoiser; OptixDenoiserOptions opt; opt.inputKind = OPTIX_DENOISER_INPUT_RGB_ALBEDO; opt.pixelFormat = OPTIX_PIXEL_FORMAT_FLOAT4; optixDenoiserCreate (ctx, &opt, &denoiser);optixDenoiserSetModel (denoiser, OPTIX_DENOISER_MODEL_KIND_HDR, nullptr , 0 );OptixDenoiserSizes denoiserReturnSizes; optixDenoiserComputeMemoryResources (denoiser, width, height, &denoiserReturnSizes);denoiserState.resize (denoiserReturnSizes.stateSizeInBytes); optixDenoiserSetup (denoiser,0 , width, height, denoiserState.d_pointer (), denoiserState.size (), denoiserScratch.d_pointer (), denoiserScratch.size ());
DLSS 深度学习超级采样(DLSS)是一种上采样技术,它使用一个小的颜色缓冲区和一个方向图来将输出的分辨率增至 2-4 倍。这是 NVIDIA 授权的开发者独有的,目前还没有办法公开使用,不过还有其他的选择,比如 DirectML’s SuperResolution Sample 。
Denoiser Design
一个理想的降噪器,结合了最新的技术论文的想法,可以是这样的:
Prepass - 计算场景的 NDC 空间速度,编写 common G-buffer attachment 如反射率,法线等。您可能还需要 first bounce 资料作为基于光线追踪的前置。 Ray Trace - 使用带有 sample map 的 AI Adaptive sampling [Hasselgren et al. 2020],以更好地确定哪些区域应该接收更多样本,一般是高光/阴影区域,以避免椒盐噪声,并能随着时间的推移保持亮度。将镜面反射和全局光照分别写入单独的附件的分离降噪器将是理想的,因为第一次反射的数据能更好的处理反射噪声,全局光照/环境光遮挡/阴影则可以使用更简单的时空积累。 Accumulation - 尽可能多地使用时空重投影,这对于全局光照/环境光遮挡这样的 lambertian data 来说比较容易,而对于像镜面反射这样的specular data 则比较困难。为了获得更好的结果,可以使用像normals/albedo/object IDs 这样的启发式数据来将以前的样本转换到当前位置,以及第一次反弹数据,如视图方向、第一次反弹法线/反照率等。任何成功的重投影都可以用于 importance sample [Bitterli et al. 2020] 或将其radiance 编码到 radiance 历史缓冲区中 [Schied 2018] Statistical Analysis 统计分析 - 估计当前光线追踪图像的方差,计算亮度/速度的方差变化,并使用它来驱动时空重投影和滤波。并用方差信息拒绝 fireflies Filtering 滤波 - 可以用一个 À-Trous bilateral filter 快速完成,根据你想要的模糊程度,重复这一步 3-5 次,每次将stepWidth
减小 2 的幂次 (所以3次迭代的序列是4,2,1)。或者,你可以使用去噪自动编码器,它慢一些,但是可以产生更好的过滤结果。然后,这个结果可以被输入一个超级采样自动编码器,这个编码器可以提升你的结果,类似于 NVIDIA 的 DLSS 2.0 History Blit - 写入当前的数据,如反射率,深度等,以便 reprojection 下一帧 Prepass 在去噪之前,重要的是使用某种 General Pass (G-Pass) 对材质信息进行编码,如法线、反射率、深度/位置、对象ID、粗糙度/金属度等。此外,速度 Velocity 信息可以将以前的样本转换到当前位置。
速度缓冲区 Velocity Buffer 可以通过顶点过去和当前的 NDC 空间坐标位置的差获得。
vec3 ndc = inPosition.xyz / inPosition.w; vec3 ndcPrev = inPositionPrev.xyz / inPositionPrev.w; outVelocity = ndc.xy - ndcPrev.xy;
Accumulation
时空重投影 Spatiotemporal reprojection 是将以前帧中的数据空间上重新投影到当前帧中。将以前的示例转换到当前帧需要您首先在视图空间中找到前一帧数据的坐标,这可以通过速度缓冲来完成。通过比较这个屏幕空间的 当前位置/法线/对象ID等 与它之前的坐标之间的差异,可以知道一个对象是否曾经被遮挡但现在在视图中,或者重用之前的样本。
在执行时空重投影时,使用一个缓冲区来描述给定样本必须积累的时间是非常有价值的,即历史缓冲区 History Buffer。它可以用来驱动滤波器模糊在样本积累较少的区域,或者用来估计当前图像的方差(历史越长,方差越小)。
outHistoryLength = successfulReprojection ? prevHistoryLength + 1.0 : 0.0 ;
Statistical Analysis const float radius = 2 ; vec2 sigmaVariancePair = vec2 (0.0 , 0.0 ); float sampCount = 0.0 ;for (int y = -radius; y <= radius; ++y){ for (int x = -radius; x <= radius; ++x) { ivec2 p = ipos + ivec2 (xx, yy); vec4 curColor = texelFetch (tColor, p, 0 ); float samp = luminance (curColor); float sampSquared = samp * samp; sigmaVariancePair += vec2 (samp, sampSquared); sampCount += 1.0 ; } } sigmaVariancePair /= sampCount; float variance = max (0.0 , sigmaVariancePair.y - sigmaVariancePair.x * sigmaVariancePair.x);
Christoph Schied 在 A-SVGF 中使用 edge avoiding guassian filter 的组合进行空间方差估计,并在一个 feedback 循环中使用它来驱动时空重投影期间的 accumulationFactor
。
float weightSum = 1.0 ;int radius = 3 ; vec2 moment = texelFetch (tMomentPrev, ipos, 0 ).rg; vec4 c = texelFetch (tColor, ipos, 0 ); float histlen = texelFetch (tHistoryLength, ipos, 0 ).r;for (int yy = -radius; yy <= radius; ++yy){ for (int xx = -radius; xx <= radius; ++xx) { if (xx != 0 && yy != 0 ) { continue ; } ivec2 p = ipos + ivec2 (xx, yy); vec4 curColor = texelFetch (tColor, p, 0 ); float curDepth = texelFetch (tDepth, p, 0 ).x; vec3 curNormal = texelFetch (tNormal, p, 0 ).xyz; float l = luminance (curColor.rgb); float weightDepth = abs (curDepth - depth.x) / (depth.y * length (vec2 (xx, yy)) + 1.0e-2 ); float weightNormal = pow (max (0 , dot (curNormal, normal)), 128.0 ); uint curMeshID = floatBitsToUint (texelFetch (tMeshID, p, 0 ).r); float w = exp (-weightDepth) * weightNormal * (meshID == curMeshID ? 1.0 : 0.0 ); if (isnan (w)) w = 0.0 ; weightSum += w; moment += vec2 (l, l * l) * w; c.rgb += curColor.rgb * w; } } moment /= weightSum; c.rgb /= weightSum; varianceSpatial = (1.0 + 2.0 * (1.0 - histlen)) * max (0.0 , moment.y - moment.x * moment.x); outFragColor = vec4 (c.rgb, (1.0 + 3.0 * (1.0 - histlen)) * max (0.0 , moment.y - moment.x * moment.x));
Firefly Rejection 可以通过多种方式实现,从调整光线追踪期间的采样方式,到使用滤波技术或启发式方法来调整输出亮度。
Increase Roughness Per Bounce
float oldRoughness = payload.roughness;payload.roughness = min (1.0 , payload.roughness + roughnessBias); roughnessBias += oldRoughness * 0.75f ;
Clamp Rejection
vec3 fireflyRejectionClamp (vec3 radiance, vec3 maxRadiance) { return min (radiance, maxRadiance); }
Variance Rejection
vec3 fireflyRejectionVariance (vec3 radiance, vec3 variance, vec3 shortMean, vec3 dev) { vec3 dev = sqrt (max (1.0e-5 , variance)); vec3 highThreshold = 0.1 + shortMean + dev * 8.0 ; vec3 overflow = max (0.0 , radiance - highThreshold); return radiance - overflow; }
Filtering A-Trous 避免了以轻微抖动的模式进行采样,以覆盖比通常 3x3 或 5x5 高斯核更大的范围,能够重复多次,并避免了由于不同输入的数量而在边缘产生的模糊。
可以与下列工作结合进行:
根据抖动模式进行子采样,从而进一步减少了模糊内核中的样本数量 用更多的信息来驱动你的模糊操作,比如表面粗糙度 [Abdollah-shamshir-saz 2018],the aproximate Specular BRDF lobe [Tokuyoshi 2015],shadow penumbras [Liu et al. 2019], etc. Limitations 所有这些算法都依赖于重用数据,因此当不可能重用数据时,比如在快速移动的对象、高度复杂的几何图形或历史信息很少的区域,这些方法的质量都会下降。有一些方法可以利用一些缓存数据来帮助避免这种情况,比如在 Minecraft RTX 中使用 irradiance 缓存来获得更好的默认颜色。
时空重投影在处理反射时也非常困难,所以通常降噪器将依赖第一次反射的数据,其中反射表面的法线和位置数据等都是基于第一次反射的。
References [Dammertz et al. 2010] Edge-Avoiding À-Trous Wavelet Transform for fast Global Illumination Filtering Holger Dammertz, Daniel Sewtz, Johannes Hanika and Hendrik P.A. LenschHigh Performance Graphics 2010
[He et al. 2012] Guided Image Filtering Kaiming He, Jian Sun and Xiaoou Tang2012
[Mara et al. 2017] An Efficient Denoising Algorithm for Global Illumination Michael Mara, Morgan McGuire, Benedikt Bitterli and Wojciech JaroszACM, High Performance Graphics 2017
[Khademi Kalantari et al. 2013] Removing the Noise in Monte Carlo Rendering with General Image Denoising Algorithms Nima Khademi Kalantari and Pradeep SenEurographics 2013
[Khademi Kalantari et al. 2015] A Machine Learning Approach for Filtering Monte Carlo Noise Nima Khademi Kalantari, Pradeep Sen and Steve BakoACM Transactions on Graphics (TOG) 2015
[R. Alla Chaitanya et al. 2017] Interactive Reconstruction of Monte Carlo Image Sequences using a Recurrent Denoising Autoencoder Chakravarty R. Alla Chaitanya, Anton S. Kaplanyan, Christoph Schied, Marco Salvi, Aaron Lefohn, Derek Nowrouzezahrai and Timo AilaACM 2017
[Vogels et al. 2018] Denoising with Kernel Prediction and Asymmetric Loss Functions Thijs Vogels, Fabrice Rousselle, Brian Mcwilliams, Gerhard Rothlin, Alex Harvill, David Adler, Mark Meyer and Jan NovakACM, ACM Transactions on Graphics 2018
[Wang et al. 2018] A Fully Progressive Approach to Single-Image Super-Resolution Yifan Wang, Federico Perazzi, Brian McWilliams, Alexander Sorkine-Hornung, Olga Sorkine-Hornung and Christopher SchroersCoRR 2018
[Xu et al. 2019] Adversarial Monte Carlo Denoising with Conditioned Auxiliary Feature Modulation Bing Xu, Junfei Zhang, Rui Wang, Kun Xu, Yong-Liang Yang, Chuan Li and Rui TangACM, ACM Transactions on Graphics 2019
[Meng et al. 2020] Real-time Monte Carlo Denoising with the Neural Bilateral Grid Xiaoxu Meng, Quan Zheng, Amitabh Varshney, Gurprit Singh and Matthias ZwickerEurographics 2020
[Hasselgren et al. 2020] Neural Temporal Adaptive Sampling and Denoising Jon Hasselgren, Jacob Munkberg, Marco Salvi, Anjul Patney and Aaron LefohnEurographics 2020
[Dong et al. 2015] Image Super-Resolution Using Deep Convolutional Networks Chao Dong, Chen Change Loy, Kaiming He and Xiaoou TangCoRR 2015
[Ledig et al. 2016] Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial Network Christian Ledig, Lucas Theis, Ferenc Huszar, Jose Caballero, Andrew P. Aitken, Alykhan Tejani, Johannes Totz, Zehan Wang and Wenzhe ShiCoRR 2016
[Korein et al. 1983] Temporal Anti-Aliasing in Computer Generated Animation Jonathan Korein and Norman BadlerACM 1983
[Yang et al. 2020] A Survey of Temporal Antialiasing Techniques Lei Yang, Shiqiu Liu and Marco SalviComputer Graphics Forum 2020
[Mara et al. 2017] Spatiotemporal Variance-Guided Filtering Christoph Schied2017
[Schied 2017] Voxel Based Hybrid Path Tracing with Spatial Denoising Baktash Abdollah-shamshir-sazi3D 2018
[Abdollah-shamshir-saz 2018] Gradient Estimation for Real-Time Adaptive Temporal Filtering Christoph Schied2018
[Schied 2018] Blockwise Multi-Order Feature Regression for Real-Time Path Tracing Reconstruction Matias Koskela and Kalle ImmonenACM Transactions on Graphics (TOG) 2019
[Koskela et al. 2019] Leveraging Ray Tracing Hardware Acceleration In Unity Anis BenyoubDigital Dragons 2019
[Benyoub 2019] Cinematic Rendering in UE4 with Real-Time Ray Tracing and Denoising Edward Liu, Ignacio Llamas, Juan Cañada and Patrick KellyRay Tracing Gems 2019
[Liu et al. 2019] Robust Monte Carlo Methods for Light Transport Simulation Eric VeachStanford University 1998
[Veach 1998] Online Path Sampling Control with Progressive Spatio-Temporal Filtering Jacopo PantaleoniNVIDIA 2020
[Pantaleoni 2020] Spatiotemporal Reservoir Resampling for Real-Time Ray Tracing With Dynamic Direct Lighting Benedikt Bitterli, Chris Wyman, Matt Pharr, Peter Shirley, Aaron Lefohn and Wojciech JaroszACM Transaction on Graphics 2020
[Bitterli et al. 2020] Scaling Probe-Based Real-Time Dynamic Global Illumination for Production Zander Majercik, Adam Marrs, Josef Spjut and Morgan McGuirearXiv 2020
[Majercik et al. 2020] Specular Lobe-Aware Filtering and Upsampling for Interactive Indirect Illumination Yusuke TokuyoshiEurographics 2015