你有没有试过用一把豆子去估算一块不规则土地的面积?把豆子随机撒下去,数数落在土地里的比例,再乘以总面积——这就是蒙特卡洛积分的基本思路。但问题来了:如果只撒 100 颗豆子,估算结果可能偏差极大;撒 10000 颗,结果才开始稳定。在光线追踪渲染中,每一颗“豆子”就是一条光线采样,而每一条光线的计算都要付出真金白银的时间成本。想要画面干净,就得撒无数颗豆子;想要渲染够快,就得尽量少撒——这就是蒙特卡洛积分降噪要解决的终极矛盾。 不过别担心,聪明的人早就找到了办法:与其一次撒上百万颗豆子慢慢数,不如先撒稀疏的几把,再用“时间换空间”——把相邻几帧的豆子合并起来看,再把空间上邻近的豆子互相借力。这就是时域滤波和空域滤波的朴素思想,也是当今影视级降噪工具 SVGF、OIDN 的看家本领。这篇文章,我们就从一把豆子讲起,带你彻底搞懂蒙特卡洛积分降噪的原理、方法与落地实践。
对 AI 从业者的价值:降噪是渲染器中决定画质与性能平衡的关键环节,理解 SVGF/OIDN 的时域与空域滤波原理,能让你在渲染器优化、画质调校和 GPU 管线设计中做出更有依据的工程决策。
目录
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
降噪流水线:噪声\u2192时域\u2192空域\u2192干净 降噪流水线降噪流水线降噪流水线降噪流水线 降噪流水线降噪流水线降噪流水线降噪流水线
噪声来源——豆子撒太少,面积当然估不准
想象你在一张大草地上画了一个不规则的湖,想估算湖的面积。你手里只有一把豆子,撒出去数一数,落进湖里的有多少颗,用这个比例乘以草地面积——这就是蒙特卡洛积分。但问题在于,豆子每次撒的位置都是随机的,这次可能撒得很密,下次可能都落在同一个角落。于是估算结果就像喝醉了一样东倒西歪,忽高忽低。这种“忽高忽低”的程度,在数学上叫方差(Variance),而它正是蒙特卡洛积分产生噪声的根本来源。
在光线追踪里,每个像素的亮度就是那片“草地面积”,每一条从摄像机出发射向场景的光线就是一颗“豆子”。光线太少,豆子稀疏,像素间亮度差异巨大——有的像素恰好多采了几条亮光源的路径,有的像素则全是暗路径。反映到画面上,就是密密麻麻的颗粒噪点。这正是蒙特卡洛积分降噪要面对的第一性问题:噪声源于采样不足导致的方差。
这里的关键是:高斯光洁面的反射路径、边缘高频几何,都是“方差特别大”的积分函数。函数越“暴躁”,同数量豆子下的噪声就越明显。所以,想真正降噪,光靠加采样永远只是杯水车薪——我们得从“复用”中找答案。
---
- 估计量$\hat{I}$ 表示用 N 个随机样本对真实积分值的估计,就像用 N 颗豆子估算湖面积。
- 加权求和$f(X_i)$ 是第 i 颗豆子贡献的亮度值,$p(X_i)$ 是豆子落在该位置的概率密度。用概率加权,是为了让“不均匀撒豆子”也能得到无偏估计。
- 方差公式$ \operatorname{Var}[\hat{I}] = \frac{1}{N} \operatorname{Var}\left[\frac{f(X)}{p(X)}\right]$ 告诉我们——估计值的方差等于单次随机变量的方差除以 N。这就像全班平均分:单个人的成绩波动很大,但 100 个人的平均分就稳定得多。
时域累积——连拍照片叠起来,噪声自己就消了
假设你要拍一张夜景照片,但相机 ISO 太高,单张照片噪点如同雪花。聪明摄影师会做一件事:把相机稳稳架在三脚架上,连续拍 10 张,然后在电脑里把这 10 张照片逐像素相加再取平均。你会发现,噪点像被施了魔法一样大幅消失——因为每张照片的噪点都是独立随机出现的,10 张一平均,随机性相互抵消,而真实画面内容始终一致,于是轮廓就凸显出来了。
这正是时域累积(Temporal Accumulation)的核心思想:在动画渲染中,相邻两帧的画面往往只有微小变化。我们为什么不把上一帧已经算好的“豆子”拿过来,和当前帧的豆子一起计数呢?在静态场景里,这个方法几乎没有副作用——上一帧的豆子和这一帧的豆子都落在同一个“湖”里,累积起来的有效采样数 N 迅速变大,方差随之按 1/N 下降。
时域累积最怕一件事——画面动了。如果相机在移动,上一帧像素记录的是场景 A 点的颜色,这一帧像素对应的却是 B 点。如果硬把两个不同世界的豆子混在一起计数,画面就会出现“鬼影”(Ghosting),像曝光过度的残影。这时候,就需要运动矢量登场了。
---
- 当前帧原始值$C_i$ 是第 i 帧当前像素的原始蒙特卡洛估计值,即刚撒完豆子的粗糙结果。
- 历史累积值$\hat{C}_{i-1}$ 是上一帧经过滤波和累积后的结果,它代表了“过去所有帧的智慧沉淀”。
- 指数加权混合$\alpha$ 通常在 0.05 到 0.2 之间。$\alpha$ 越小,历史帧占比越高,降噪越彻底,但画面更新越迟钝;$\alpha$ 越大,响应越快,但降噪效果越弱。这就像调鸡尾酒——旧酒比例越高,口感越醇厚,但新调味的占比就少了。
运动矢量——给豆子们装上定位导航
想象你在火车上拍窗外的风景,远处的山峦缓慢移动。如果要把多张照片叠起来降噪,你不能简单地像素对齐像素——因为山的位置在每帧里都变了。聪明的做法是:先用某种技术算出“山在这一帧里向右移动了几个像素”,然后把上一帧的照片按这个偏移量平移之后再叠加。这就是“运动估计 + 补偿”的思路,在视频压缩中叫运动矢量,在渲染中叫重投影(Reprojection)。
在渲染器里,运动矢量的计算通常不需要额外的智能算法——因为场景的三维几何和相机参数都是已知的。我们可以把上一帧像素对应的三维点,重新投影到当前帧的相机坐标系中,看看它会落在哪个新像素位置。只要知道当前的相机视角和物体的运动状态,这个投影过程就是纯几何计算,像做一道精确的解析几何题。这就是“几何投影法”估计运动矢量的过程,远比计算机视觉中的光流法更精确。
但运动矢量并非万无一失。物体遮挡会让某些区域的前一帧豆子直接消失,边缘处的几何预估也可能偏差一两个像素。因此成熟的渲染器会给每个像素计算运动矢量的置信度——置信度低的区域就减少历史帧的权重,甚至完全放弃累积。这就像导航信号不稳定时,你会降低对导航的信任转而靠自己的眼睛观察路况。
---
- 上一帧像素坐标$\mathbf{p}_{t-1}$ 是上一帧中某个像素的坐标(x, y)。
- 逆投影到世界空间$P_{t-1}^{-1}$ 将像素坐标还原为三维世界坐标点,就像从照片反推实物位置。
- 重投影到当前帧$P_t$ 将世界坐标点投影到当前帧的像素平面,得到新的像素坐标 $\mathbf{p}_t$。这样我们就知道“上一帧的这一撮豆子,现在应该归到哪个新像素名下”。
空域滤波——邻居豆子互相借力,边缘还得守规矩
如果时域累积是“用时间换降噪”,那空域滤波就是“用空间换降噪”。在一张含噪图片里,一个像素的亮度通常和它周围的像素高度相关——墙壁是平的,颜色应该均匀;即便是复杂纹理,邻近像素的亮度变化也不会过于剧烈。所以最朴素的想法是:把每个像素周围一圈邻居的亮度值加权平均,噪声不就自然被“抹平”了吗?
但这里有个致命陷阱:如果对所有邻居一视同仁地平均,就会把物体的边缘糊掉。墙壁和桌子的交界处,左边是白色,右边是黑色,一平均就成了灰色——边缘被“洗”没了。所以专业的降噪滤波必须是边缘感知的:它不只考虑“距离上离得近不近”,还要看“这个邻居和我是否来自同一个表面”。判断依据通常是法线方向(Normal)和深度值(Depth):如果邻居像素的法线方向差异很大,说明它们来自不同的几何表面,权重就应该大幅降低。
有了这套权重体系,空域滤波就能在“平滑噪声”和“保留边缘”之间取得精细的平衡。邻居豆子可以借力,但只有“信得过”的邻居才有资格参与投票。这就像邻里互助:你可以借用邻居家的面粉,但首先得确认邻居和你住在同一栋楼、同一层、朝向一致,否则借来的面粉可能并不适合你的配方。
---
- 空间距离权重$w_{\text{dist}}$ 表示像素 $\mathbf{q}$ 离中心像素 $\mathbf{p}$ 越远,权重越低,通常用高斯核实现。
- 法线一致性权重$w_{\text{normal}}$ 衡量两个像素的法线夹角大小,夹角越大越不可能是同一表面。它像一面照妖镜,让滤波不会跨过边缘。
- 深度一致性权重$w_{\text{depth}}$ 比较两个像素的深度值差异,防止前景物体和背景物体发生颜色串扰。
SVGF架构——把时域和空域组装成一条降噪流水线
前面讲的都是零部件:时域累积负责“吃老本”,运动矢量负责“对齐过往”,空域滤波负责“向左邻右舍借力”。真正的工程大师会把它们组合成一条完整的流水线——这就是 SVGF(Spatio-Temporal Variance-Guided Filtering,时空方差引导滤波) 的诞生逻辑。SVGF 是 2017 年由 Schied 等人提出的实时降噪算法,至今仍是游戏引擎和实时渲染器中使用最广泛的降噪方案之一。
SVGF 的聪明之处在于一个关键洞察:哪里噪声大,哪里就多滤波;哪里噪声小,哪里就少滤波。它先用一小组额外光线样本估计出每个像素的亮度方差,把“噪声地图”绘制出来。然后基于方差图,动态调整空域滤波的强度——方差大的区域加大滤波半径,方差小的区域保持锐利。这个“方差引导”机制让滤波不再是盲人摸象,而是带着听诊器的精准医生。
在具体实现上,SVGF 使用 ATrous 小波变换做多尺度迭代滤波:第一轮小半径滤波去除高频噪声,第二轮扩大半径去除中频噪声,如此迭代几次,噪声从细到粗层层剥离。每轮迭代之间还穿插一次时域累积,让时间维度的信息持续注入。这个“多尺度剥洋葱”的过程,就是 SVGF 能在 1 样本/像素的低采样率下产出高质量画面的秘密武器。
---
- 滤波窗口$\Omega$ 表示以像素 $\mathbf{p}$ 为中心、半径为 r 的邻居像素集合。
- 双边权重$w(\mathbf{p}, \mathbf{q})$ 是上节提到的多维权重乘积,但 SVGF 还额外加入了颜色权重——中心像素和邻居像素的颜色差异越大,权重越低,进一步保护纹理细节。
- 归一化加权平均分母归一化保证滤波前后整体亮度不变,不会让画面越滤越暗。
工程落地——从论文到生产线,OIDN 与性能预算
理论再漂亮,也要落地到工程才算数。在实际的渲染器与游戏引擎中,SVGF 已经展现出惊人效果,但工程人员还需要考虑两个现实问题:一是 GPU 计算资源有限,二是不同硬件平台的适配。这时,OIDN(Open Image Denoise) 作为 Intel 开源的降噪库走进了视野。OIDN 基于深度学习——它用大量含噪与干净图像对训练了一个卷积神经网络,推理时只需将含噪图像、法线图、深度图和反照率图喂给网络,就能直接输出去噪结果。
OIDN 与 SVGF 的定位不同:SVGF 是实时的、逐帧递推的,适合交互式渲染;OIDN 是离线的、单帧独立的,适合最终帧的精品渲染(如电影特效)。OIDN 的优势在于——它利用 GPU/CPU 的硬件加速指令(如 AVX-512),推理速度极快,而且对动态场景毫无压力(因为它不做帧间累积)。很多生产级渲染器(如 Blender Cycles)的默认降噪方案就是 OIDN。
工程实践中有几个普适的调优经验:降采样预处理——把大分辨率图缩小到 1/4 再滤波,效率翻倍,细节损失可用后处理锐化弥补;逐项调参——α(时域权重)调低减少鬼影、σ_s(空域半径)调大增强平滑、方差引导强度调中避免过度模糊;性能预算——在实时光线追踪中,通常给降噪分配每帧总时间的 10%~15%,超过就不值得了。这些经验像厨师的“火候控制”——配方一样,手法不同,成品天差地别。
---
输入 → 含噪颜色图 + 反照率图 + 法线图 + 深度图 → OIDN 推理 → 干净输出AI 应用场景
影视离线渲染的画质提升
阶段:渲染后期降噪处理
解决的问题:电影特效的路径追踪渲染中,每帧需要数千次采样才能达到电影级画质,单帧渲染几十小时。借助降噪技术可以大幅降低采样数,但传统滤波容易丢失细节。OIDN 的深度学习降噪可以在极低采样(如每像素 64 样本)下产出干净画面,将渲染时间从 50 小时压缩到 3 小时。
具体案例:某动画电影工作室在渲染以毛发为主的角色镜头时,传统蒙特卡洛采样在毛发区域产生严重噪点。引入 OIDN 后,配合法线和深度辅助通道输入,在降低 70% 采样量的同时保持了毛发的纤维级细节,单帧渲染时间从 12 小时降至 2.5 小时。
实时光线追踪游戏的帧率平衡
阶段:实时渲染管线中的去噪环节
解决的问题:NVIDIA RTX 系列 GPU 支持实时光线追踪,但如果完整追踪每像素 4 条光线,帧率会跌到不可玩的程度。SVGF 类时域降噪方案允许渲染器只用每像素 1 条光线完成追踪,然后通过时域累积和空域滤波补足质量,让 1080p/60fps 成为可能。
具体案例:《地铁:离去》增强版的实时全局光照场景中,工程师在动态天气和日夜循环条件下调整 SVGF 的时域权重 α。当角色快速转动视角时,动态降低 α 值以减少鬼影;在静态场景探索时,升高 α 值获取最干净的反射效果。
建筑可视化中的交互式预览
阶段:实时预览渲染
解决的问题:建筑设计师在调整材质和灯光时,希望能即时看到效果,但离线渲染器每调整一次参数要数分钟。使用降噪技术后,可以用极低采样数快速预览,让设计师获得接近最终质量的即时反馈,大幅提升迭代效率。
具体案例:某建筑可视化公司的设计平台上,集成了 Intel OIDN 作为预览渲染器降噪核心。设计师拖动灯光亮度滑块时,渲染器以每像素 128 个样本快速出图,OIDN 在 V-Ray 基准测试中标称的 Dalai 模型降到 30 毫秒内完成推理,预览帧率达到 12fps。
Python 演示
import numpy as np def generate_noisy_image(height=64, width=64, base_color=0.5, noise_level=0.4): """用蒙特卡洛方式生成一张含噪图像:真实值 + 随机噪声""" true_image = np.full((height, width), base_color) true_image[:, width // 3:] = 0.3 # 右侧是暗区域 true_image[height // 4: height // 2, width // 4: width // 2] = 0.8 noise = np.random.normal(0, noise_level, size=(height, width)) return true_image, true_image + noise def variance_guided_filter(image, guide, radius=2, sigma_color=0.1, sigma_spatial=2.0): """方差引导的加权滤波:在平滑噪声时保留边缘""" h, w = image.shape result = np.zeros_like(image) weight_sum = np.zeros_like(image) # 以 guide 作为边缘信息,计算细节权重 guide_grad = np.abs(np.gradient(guide)) detail_weight = 1.0 / (1.0 + 10.0 * (guide_grad[0] + guide_grad[1])) for dy in range(-radius, radius + 1): for dx in range(-radius, radius + 1): if dx * dx + dy * dy > radius * radius: continue shift_image = np.roll(np.roll(image, dy, axis=0), dx, axis=1) shift_guide = np.roll(np.roll(guide, dy, axis=0), dx, axis=1) spatial_w = np.exp(-(dx * dx + dy * dy) / (2 * sigma_spatial * sigma_spatial)) color_w = np.exp(-((image - shift_image) / sigma_color) ** 2) w = spatial_w * color_w * detail_weight result += w * shift_image weight_sum += w return np.where(weight_sum > 0, result / weight_sum, image) def estimate_variance(image, patch_size=5): """估计局部方差,用于构建噪声地图""" from numpy.lib.stride_tricks import sliding_window_view h, w = image.shape pad = patch_size // 2 padded = np.pad(image, pad, mode='reflect') patches = sliding_window_view(padded, (patch_size, patch_size)) return patches.reshape(h, w, -1).var(axis=2) def main(): h, w = 64, 64 true_img, noisy_img = generate_noisy_image(h, w, noise_level=0.35) # 简单均值滤波:与方差引导滤波形成对比 kernel = np.ones((3, 3)) / 9.0 from scipy.ndimage import convolve try: mean_filtered = convolve(noisy_img, kernel, mode='reflect') except ImportError: # 若没有 scipy,则手动实现 3x3 均值 mean_filtered = np.zeros_like(noisy_img) for dy in (-1, 0, 1): for dx in (-1, 0, 1): mean_filtered += np.roll(np.roll(noisy_img, dy, axis=0), dx, axis=1) mean_filtered /= 9.0 # 方差引导滤波:用自己的含噪图作为 guide sigma_v = estimated_var = estimate_variance(noisy_img) guide = noisy_img - 0.5 * estimated_var / (estimated_var.max() + 1e-6) vgf_result = variance_guided_filter(noisy_img, guide, radius=2) def psnr(img1, img2): mse = np.mean((img1 - img2) ** 2) if mse == 0: return float('inf') return 10 * np.log10(1.0 / mse) print('含噪图像 PSNR: {:.2f} dB'.format(psnr(noisy_img, true_img))) print('均值滤波 PSNR: {:.2f} dB'.format(psnr(mean_filtered, true_img))) print('方差引导滤波 PSNR: {:.2f} dB'.format(psnr(vgf_result, true_img))) print('演示结束:方差引导的加权滤波在保留边缘的同时更有效地去除了噪声。') if __name__ == '__main__': main()
true_image[:, width // 3:] = 0.3构造包含清晰边缘的测试图像,方便对比滤波效果noise = np.random.normal(0, noise_level, ...)模拟蒙特卡洛采样产生的随机噪声guide_grad = np.abs(np.gradient(guide))计算引导图的梯度,梯度大的位置是边缘,应降低滤波权重color_w = np.exp(-((image - shift_image) / sigma_color) ** 2)颜色差异权重,邻居与中心差异越大权重越低w = spatial_w * color_w * detail_weight三步权重相乘,完整模拟双边滤波的边缘感知机制estimate_variance估算局部方差,用方差图反过来修正引导信息,模拟 SVGF 的“方差引导”思路psnr(noisy_img, true_img)计算峰值信噪比,定量评估降噪效果
常见误区
误区我刚学渲染的时候觉得降噪不就是把图片变模糊吗?噪点不也是高频信息吗,模糊掉不就行了?
正解直接模糊确实能去噪,但会把边缘、纹理细节一起抹掉,画面变成“油乎乎”的一片。专业的降噪是一个“选择性模糊”的过程:在平坦区域放心大胆地模糊,在边缘和细节区域谨慎处理。这就像修图时用蒙版保护主体——摄影师只会对天空等区域做磨皮,绝不会把人的五官也磨掉。
为何常见:因为噪声确实是高频成分,而模糊也是滤除高频信号,人们很自然地联想到“以毒攻毒”。
误区蒙特卡洛误差不是和样本数 N 有关吗?那我把采样数从 100 提高到 200,噪声应该减少一半吧?
正解方差与 N 成反比,但噪声的量级(标准差)与 $1/\sqrt{N}$ 成正比。所以采样数从 100 翻倍到 200,噪声只降为原来的约 0.7 倍。要把噪声降到一半,需要把采样数提高到原来的 4 倍。这个“边际收益递减”规律决定了堆采样的性价比极低——这也是为什么降噪技术如此重要。
为何常见:直觉上线性思维很容易联想到“采样翻倍、质量翻倍”,但方差的平方根关系打破了这种线性直觉。
误区SVGF 这么聪明,连方差都会利用,它肯定是用神经网络训练出来的吧?
正解SVGF 完全是手工设计的传统滤波算法,没有任何神经网络组件。它利用的是 ATrous 小波多尺度分解加上漂亮的数学推导。而 OIDN 才是基于深度学习(卷积神经网络)的方案。两者是“老匠人手艺”与“AI 学徒”的差异——SVGF 的每个权重因子都有明确的物理含义,OIDN 的权重则隐式地学在了网络参数里。
为何常见:近年来 AI 降噪(如 OIDN、OptiX)很火,人们容易把所有智能降噪都归功于深度学习。
误区要处理物体运动,肯定得用 OpenCV 的光流算法来算像素移动方向吧?
正解在渲染器中,运动矢量通常不需要光流法——因为场景的 3D 几何是已知的,可以直接用正投影/逆投影的几何计算精确得到每像素的运动矢量。光流法是在没有几何信息时(比如对真实视频)的无奈之举。渲染器有“作弊神器”—— 几何投影法又快又准,还不需要复杂的特征匹配。
为何常见:计算机视觉的知识先入为主,让人忽视了渲染器场景中“几何已知”这个重要前提。
误区时域累积不是把历史帧都平均起来吗?那我一直积累不就无限接近真实值了?
正解无限累积会导致两个问题:一是动态场景下的鬼影会越来越重,因为历史帧里包含的是“过去位置的内容”,一旦物体移动,旧像素就会拖出残影;二是数值精度的累积误差。所以工程中一般用指数加权平均(旧帧权重按指数衰减),而非均匀平均。同时需要运动矢量对齐,否则“平均”的对象根本不对位。
为何常见:从“平均降噪”的直觉出发,自然认为平均越多越准确,忽略了画面内容变化这个前提。
面试题
Q1. 蒙特卡洛积分的方差随采样数 N 如何变化?
- A.与 N 成正比,采样越多噪声越大
- B.与 N 成反比,采样越多噪声越小← 正确答案
- C.与 N 的平方成反比,效果极佳
- D.与 N 无关,噪声恒定不变
答案:B。蒙特卡洛估计的方差公式为 Var = σ²/N,即方差与 N 成反比。但噪声的量级(标准差)与 1/√N 成正比,因此要让噪声减半需要 4 倍采样量,这正是降噪技术存在的原因。
Q2. SVGF 的全称是什么?
- A.Spatial Visual Gradient Filtering
- B.Spatio-Temporal Variance-Guided Filtering← 正确答案
- C.Super Vector Graphics Framework
- D.Standard Variance Gradient Function
答案:B。SVGF 是 Spatio-Temporal Variance-Guided Filtering(时空方差引导滤波)的缩写。它的核心思想是用方差图引导滤波强度——方差大的区域多滤波,方差小的区域保细节。其他选项均为混淆项。
Q3. 时域累积中的指数加权参数 α 取值较小时,会产生什么效果?
- A.当前帧权重高,画面响应快但噪声多
- B.历史帧权重高,降噪彻底但画面更新慢← 正确答案
- C.噪声与历史帧无关,完全取决于当前帧
- D.画面会出现色彩偏移,无法正常渲染
答案:B。α 是当前帧的权重,α 越小则 (1-α) 越大,历史帧占比越高。这会带来更强的降噪效果,但在动态场景中响应变慢,容易产生鬼影。调参就是在这两者间寻找平衡。
Q4. 渲染器中计算运动矢量通常使用什么方法?
- A.基于深度学习的卷积神经网络
- B.几何投影法,利用已知的 3D 场景信息← 正确答案
- C.基于颜色直方图的特征匹配
- D.随机采样并统计像素位移
答案:B。渲染器拥有完整的三维场景几何信息,因此可以直接用逆投影+重投影的纯几何方法计算运动矢量,比光流法更精确。光流法和特征匹配通常用于没有几何信息的真实视频场景。
Q5. 空域滤波中,法线权重的作用是什么?
- A.增加边缘像素的亮度值
- B.防止滤波跨越几何边缘产生模糊← 正确答案
- C.提高场景中光线的反射强度
- D.降低噪声像素的颜色饱和度
答案:B。法线权重比较邻居像素与中心像素的法线方向。法线方向差异大说明它们属于不同表面(比如墙壁和地板),此时权重降低,防止边缘被平均成灰色。这是边缘感知滤波的关键机制。
Q6. OIDN 与 SVGF 在定位上的主要差异是什么?
- A.OIDN 是实时算法,SVGF 是离线算法
- B.OIDN 是深度学习方案,SVGF 是传统滤波方案← 正确答案
- C.OIDN 不做空域滤波,SVGF 不做时域滤波
- D.OIDN 仅支持 CPU,SVGF 仅支持 GPU
答案:B。OIDN 基于卷积神经网络推理(深度学习),适合离线高质量渲染;SVGF 是手工设计的多尺度双边滤波,适合实时渲染。两者都能用 CPU 或 GPU 加速,也都结合了时域和空域信息。
Q7. 在极端低采样率(如每像素 1 条光线)下,SVGF 仍能工作的关键机制是什么?
- A.提前计算好的全局光照贴图
- B.时域累积叠加方差引导的滤波权重← 正确答案
- C.使用更高精度的浮点数运算
- D.强制将所有像素设为同一颜色
答案:B。SVGF 在每像素 1 次采样下通过两条腿走路:时域上不断累积历史帧有效样本量,空域上用方差图引导滤波强度。二者结合使有效采样数迅速增长,即便原始采样极稀疏也能收敛到干净画面。
Q8. 以下哪些因素会影响空域滤波中邻居像素的权重?
- A.邻居像素与中心像素的空间距离← 正确答案
- B.邻居像素的法线方向是否一致← 正确答案
- C.邻居像素的深度值是否接近← 正确答案
- D.邻居像素的磁盘存储位置
答案:ABC。空间距离(高斯核)、法线方向一致性、深度一致性共同决定空域滤波的权重。磁盘存储位置与画面内容无关,不影响滤波权重。这三个权重因子相乘,确保滤波在平滑噪声的同时不破坏几何边缘。
Q9. 时域累积可能产生哪些问题?
- A.物体快速移动时出现鬼影残影← 正确答案
- B.场景突然变化时画面迟钝缓慢← 正确答案
- C.运动矢量估计错误导致错位叠影← 正确答案
- D.静态场景下噪声反而更加严重
答案:ABC。时域累积把历史帧内容混入当前画面,当物体移动时旧位置信息拖出残影(鬼影);场景切换时旧信息来不及消失导致迟钝;运动矢量错误时历史帧对齐失败产生叠影。但静态场景中时域累积非常有效,噪声不会加重。
Q10. 关于方差引导滤波,以下说法正确的是?
- A.方差越大表示该区域噪声越严重← 正确答案
- B.方差大的区域应增强滤波强度← 正确答案
- C.方差小的区域应保持画面锐利← 正确答案
- D.方差图只能通过额外光线计算得到
答案:ABC。局部方差是衡量噪声程度的良好指标——方差大噪声重,方差小噪声轻。SVGF 据此动态调整滤波强度,噪声大的地方多平滑,噪声小的地方保细节。方差图除额外采样外还可从历史帧差异中估计,并非只能靠额外光线。