ReSTIR
全库目录221
本文目录21
光源很多时,一个像素只看几次候选,容易漏掉重要贡献。ReSTIR 用一个蓄水池保存代表样本及统计量,再把附近像素和历史帧的代表样本拿到当前像素重新评价。它压缩的是候选集合;要得到正确亮度,还必须补回选择概率和样本计数。
单像素的重要性重采样
先讨论固定像素的直接光积分 。 表示光源及光源表面位置, 包含颜色贡献与最终可见性。候选按密度 产生,所有密度使用相同测度,例如光源面积与光源选择概率的联合测度。若改用立体角密度,需要同时转换几何项,不能混用数值。
以N个非退化发光三角形为一条可实现的候选路线:先以1/N选光源ID,再取两个独立均匀随机数u、v,令a=√u,重心坐标为(1-a,a*(1-v),a*v)。这在三角形面积上均匀,面积为Ai时,联合密度是p(y)=1/(N*Ai)。光源ID与重心坐标一起保存,时空重用不依赖已移动的世界坐标。退化三角形在建立光列表时排除,其ID版本同步保存;面积不同却一律填1/N,只包含选灯概率、遗漏了面内面积密度。
面积测度下,RGB贡献为Le * BRDF * max(Nx·L,0) * max(Nlight·(-L),0) / distance² * visibility,距离以米计;光源出射辐亮度Le、两端余弦和面积密度配套使用。重采样目标可以取这份未遮挡RGB的非负线性亮度,最终乘数才作用到含当前可见性的完整RGB。相交、自发光几何与有限距离阴影射线按实时光追采样的起点偏移和最大距离处理。点光等离散光类型采用带类型标签的独立测度,选择概率与其离散贡献成套计算,不能把点光的概率直接当成三角形面积密度。
为便宜地比较候选,选取非负标量目标函数 ,例如未遮挡贡献的亮度。它不必归一化,但应在实际贡献非零的位置为正。每个候选的重采样权重是 。依次累计 ,第 个候选以 的概率替换当前代表,最终样本的选择概率就与其权重成正比。
以下是算法伪代码。random01给出独立的随机数;实际抽到的候选提议密度为正,输入权重非负,权重和、计数与最终乘数必须在工作精度下可表示为有限值。宿主按预算和动态范围验证这些前提,数值失效时报告错误;任意截断大权重会改变估计,不能以稳定数值为由宣称仍无偏。零权重仍计入候选总数;全零流保持无有效样本。
M = 0; S = 0; selected = invalid
for candidate in candidates:
M += 1
w = target(candidate) / proposalPdf(candidate)
S += w
if w > 0 and random01() * S < w:
selected = candidate
if S > 0:
W = S / (M * target(selected))
estimate = contributionWithVisibility(selected) * W
else:
estimate = 0是最终贡献的乘数,与更新期间的权重和 不同。若只输出代表样本的颜色,亮光因为更常被选中,会被重复放大。条件在已生成候选集合上,最后估计的期望为:
=\frac1M\sum_i\frac{f(y_i)}{p(y_i)}$$ 右侧正是原候选的 Monte Carlo 估计。因此固定像素、有效支持和正确密度下,选择一个代表仍能保持期望。目标函数忽略遮挡并不自动造成偏差:最后重新计算正确可见性仍可无偏,但若代表经常被遮住,方差会很高。 ### 面积测度与参数测度的交接 前面的单像素推导可以直接使用世界面积测度。跨帧面光源会变形时,本页的时空数据流统一存成`y=(稳定光ID,u,v)`参数测度,其中u、v是生成重心坐标时的两个[0,1)均匀随机数。这个平方参数域经过`a=√u`映射到三角形,面积雅可比恰好是该帧三角形面积A;单位参数面积映射成A平方米,而不是重心二维单纯形上的另一套常量。 进入初始蓄水池以前,面积域的贡献、目标和提议密度全部转换为参数域:`f_param=A*f_area`、`target_param=A*target_area`、`p_param=A*p_area=1/N`。于是候选权重`target/p`保持不变,而已归一化的贡献乘数变为`W_param=W_area/A`。若已有实现先建面积域池,就在写出初始A缓冲之前按该代表样本的源面积转换W;不能只改最终贡献,却把旧面积域W原样写入历史。下文A、B、C、H的W、当前目标与源h全部采用这份参数测度,池记录的面积版本用于重新评价来源目标。 只有一个光源、面积2平方米、面积域贡献恒为1时,均匀候选密度为1/2,单样本W_area为2。转成参数域后f为2、密度为1、W为1,估计仍为2。下一帧面积变为6平方米且对应各点贡献仍为1,当前参数贡献为6,历史参数W仍为1,得到6;直接拿旧W_area=2乘当前面积域贡献1,只会得到2,错误地保留旧面积。若光源只是刚体移动、面积没变,仍用当前位置重新算距离与两端余弦,面积不变也不代表贡献不变。 来源h同样使用来源时刻面积与几何,当前目标和最终f则使用当前面积与几何。整份光源ID被不兼容地重新编号、或来源的参数化规则整体失效时,才按预定版本规则拒绝该来源。单个光被删除或当前退化时,将其当前目标置零,该代表不进入选择,仍按后文保留来源集合、M和历史支持评价;不能看到随机选中光失效就删整池。面积变化且仍非退化时正常映射。新增ID在旧来源支持外,其h为零,由本帧候选补足。这样测度转换、动态支持与池合并使用同一份样本身份。 ## 蓄水池合并与目标重评估 源蓄水池 $j$ 保存样本 $y_j$、乘数 $W_j$ 和代表的候选数 $M_j$。拿到目标像素 $x$ 时,需要重新计算这个光样本在目标表面的重要性,而不是沿用邻居的亮度。基础合并权重为: $$w_j=\hat p_x(y_j)W_jM_j$$ 将这些权重送进同一替换过程,累计候选数为 $M=\sum_jM_j$,最终仍按 $W=S/[M\hat p_x(y)]$ 归一化。这条以总计数归一化的形式要求各源覆盖相同支持。跨表面背向、可见性筛除或光源集合变化会改变支持。先把这种失配补进归一化,再把完整合并过程用于每帧的数据流。 一个离散算例可以检查“换像素就重算”的必要性。光域只有两点,提议概率各为 1/2,两个源池各生成一个候选,因而 $W_j=2$。假设这次两个源池恰好分别保留这两点。目标像素的目标值为 4 和 1,合并权重为 8 和 2;实际贡献为 2 和 5。选择概率为 0.8 和 0.2,归一化后的输出分别为 2.5 和 25,期望为 7,恰好等于两点贡献之和。较大的单次输出是低概率样本的补偿,并非一定是数值错误。 ## 支持域修正与归一化 同支持时可按总M归一化;支持不同则分别评价源函数h_j:它在来源可贡献的区域为正,在域外为零。本页帧流程采用连续目标权重,先以`a_j=targetCurrent(Yj)*Wj*M_j`选样,记权重和S和真正被选中的来源s,再计算`W=S*h_s(Y)/(targetCurrent(Y)*sum_j(M_j*h_j(Y)))`。源集合、计数与h的定义由候选之外的场景与调度条件确定。完整推导、两遍实现及自适应取舍的反例见[ReSTIR支持域与归一化](/knowledge/12_%E5%85%89%E7%BA%BF%E8%BF%BD%E8%B8%AA/ReSTIR%E6%94%AF%E6%8C%81%E5%9F%9F%E4%B8%8E%E5%BD%92%E4%B8%80%E5%8C%96)。 详见[ReSTIR支持域与归一化](/knowledge/12_%E5%85%89%E7%BA%BF%E8%BF%BD%E8%B8%AA/ReSTIR%E6%94%AF%E6%8C%81%E5%9F%9F%E4%B8%8E%E5%BD%92%E4%B8%80%E5%8C%96#%E6%94%AF%E6%8C%81%E5%9F%9F%E4%BF%AE%E6%AD%A3%E4%B8%8E%E5%BD%92%E4%B8%80%E5%8C%96)。 ### 支持失配的能量损失 详见[ReSTIR支持域与归一化](/knowledge/12_%E5%85%89%E7%BA%BF%E8%BF%BD%E8%B8%AA/ReSTIR%E6%94%AF%E6%8C%81%E5%9F%9F%E4%B8%8E%E5%BD%92%E4%B8%80%E5%8C%96#%E6%94%AF%E6%8C%81%E5%A4%B1%E9%85%8D%E7%9A%84%E8%83%BD%E9%87%8F%E6%8D%9F%E5%A4%B1)。 ### 支持分区归一化 详见[ReSTIR支持域与归一化](/knowledge/12_%E5%85%89%E7%BA%BF%E8%BF%BD%E8%B8%AA/ReSTIR%E6%94%AF%E6%8C%81%E5%9F%9F%E4%B8%8E%E5%BD%92%E4%B8%80%E5%8C%96#%E6%94%AF%E6%8C%81%E5%88%86%E5%8C%BA%E5%BD%92%E4%B8%80%E5%8C%96)。 ### 连续目标权重与来源身份 详见[ReSTIR支持域与归一化](/knowledge/12_%E5%85%89%E7%BA%BF%E8%BF%BD%E8%B8%AA/ReSTIR%E6%94%AF%E6%8C%81%E5%9F%9F%E4%B8%8E%E5%BD%92%E4%B8%80%E5%8C%96#%E8%BF%9E%E7%BB%AD%E7%9B%AE%E6%A0%87%E6%9D%83%E9%87%8D%E4%B8%8E%E6%9D%A5%E6%BA%90%E8%BA%AB%E4%BB%BD)。 ### 两遍合并实现 详见[ReSTIR支持域与归一化](/knowledge/12_%E5%85%89%E7%BA%BF%E8%BF%BD%E8%B8%AA/ReSTIR%E6%94%AF%E6%8C%81%E5%9F%9F%E4%B8%8E%E5%BD%92%E4%B8%80%E5%8C%96#%E4%B8%A4%E9%81%8D%E5%90%88%E5%B9%B6%E5%AE%9E%E7%8E%B0)。 ### 递归合并的成立条件 详见[ReSTIR支持域与归一化](/knowledge/12_%E5%85%89%E7%BA%BF%E8%BF%BD%E8%B8%AA/ReSTIR%E6%94%AF%E6%8C%81%E5%9F%9F%E4%B8%8E%E5%BD%92%E4%B8%80%E5%8C%96#%E9%80%92%E5%BD%92%E5%90%88%E5%B9%B6%E7%9A%84%E6%88%90%E7%AB%8B%E6%9D%A1%E4%BB%B6)。 ### 自适应取舍的偏差 详见[ReSTIR支持域与归一化](/knowledge/12_%E5%85%89%E7%BA%BF%E8%BF%BD%E8%B8%AA/ReSTIR%E6%94%AF%E6%8C%81%E5%9F%9F%E4%B8%8E%E5%BD%92%E4%B8%80%E5%8C%96#%E8%87%AA%E9%80%82%E5%BA%94%E5%8F%96%E8%88%8D%E7%9A%84%E5%81%8F%E5%B7%AE)。 ### 历史支持与场景版本 详见[ReSTIR支持域与归一化](/knowledge/12_%E5%85%89%E7%BA%BF%E8%BF%BD%E8%B8%AA/ReSTIR%E6%94%AF%E6%8C%81%E5%9F%9F%E4%B8%8E%E5%BD%92%E4%B8%80%E5%8C%96#%E5%8E%86%E5%8F%B2%E6%94%AF%E6%8C%81%E4%B8%8E%E5%9C%BA%E6%99%AF%E7%89%88%E6%9C%AC)。 ## 一帧的时空复用 合并的计算、支持和递归条件确定以后,下一步是把它们接到一帧的数据流。下面采用一轮时域加一轮空间的完整数据流:当前候选写入A,时域结果写入B,空间结果写入C,最终着色读取C,帧结束后把C保存为下一帧的历史H。每次读取的池保存光源稳定ID、平方参数u/v(也可保存能还原它们的重心坐标)、选中参数域目标值、W_param和M,并关联产生该池的表面与目标函数版本;流式更新期间另用局部S。S和W职责不同,序列化时不能混为同一个尚未归一化的值。 ### 历史数据的联合寿命 历史H与评价它的前帧GBuffer、材质参数、光源表和变换组成同一份不可变版本。版本号只能识别数据,不能代替保存数据:若H仍指向前帧而光源表已被原地写成本帧,第二遍计算的源h就改变了,归一化将使用错误的支持与面积。发布历史时一起发布这些资源引用;当前调度在两遍评价结束前持续持有它们,直到最后一个读者所在队列完成才回收。 A、B、C采用分别可读写的资源版本,各阶段通过写后读依赖连接。C成为下一帧H后,其存储也不能立即作为当前新帧的C覆盖。帧环需要按实际在途读者完成条件取得可写槽位;图形与计算队列交错执行时,保存全部最后读取条件或汇合到一个完成点。场景变化先生成新版本,再决定历史来源是否可映射;整份版本无法保留时,在来源选择前按版本规则使相关历史失效,并由覆盖当前支持的新鲜候选接续估计。 ### 当前候选与历史接受 像素x先从当前光源提议分布产生K个候选,按单像素重采样得到A[x]。即使历史被拒绝,这条路径也提供当前帧的估计。时域查询使用当前表面的运动向量定位H中的对应像素。教学实现采用最近像素读取,禁止线性插值池字段;光源ID和代表样本并不是可连续混合的颜色。 历史接受可以写成明确的条件链:重投影坐标在图内;对应位置保存相同的稳定表面身份;前帧表面重建到当前空间后,与当前位置相差不超过场景长度阈值;法线点积高于阈值;源材质和光源参数化版本仍可重建并映射。失败任一项,B[x]=A[x]。通过时,先把历史光源ID映射到当前光源,再由表面参数重建当前光源位置,重新计算当前像素的目标值。若某历史代表的光源已删除,本帧目标置零,该候选不参与替换,但来源的M与可评价支持仍保留在第二遍归一化;不能仅因随机选中的代表被删除,就把整份历史从来源集合中移除。整个参数化版本无法重建时,才按预先确定的版本规则拒绝该来源。相机切换使所有历史失效,物体运动则通过对象变换和运动向量跟踪对应表面。 这些条件检验的是表面对应关系,并不能证明估计器的支持域一致。比如两个法线几乎相同的表面,中间仍可能隔着一堵遮挡墙;已定义的两遍归一化仍要在通过几何接受以后执行。阈值以场景尺度和法线误差设定,本文没有用一个固定数值替代不同工程的输入契约。 ### 历史计数与时域输出 以下数例始终采用连续目标归一化。当前目标在a、b上为4、1,历史源目标在两点均为1;两源支持相同,但来源目标数值不同,第二遍仍分别评价。 历史多次复用以后,M可能远大于当前K,过时统计会压过新候选。这里明确选择一种计数限制:先令m=min(M历史,20K),将它作为本次分配给历史来源的计数,已归一化的W历史保持不变。接收历史时使用权重目标当前(y历史)·W历史·m,第二遍归一化也用同一个m;当前池使用目标当前(y当前)·W当前·K。旧池内部流式S不作为本次输入,尤其经过支持修正的W不能简单反推成统一的S/(M·目标)。在共同支持的基础池中,S与M同比缩放能保持W,这只是上述处理的一种特例。 取K=2,当前池代表a、W=2;历史代表b、W=1、M=100。本像素的目标值为目标(a)=4、目标(b)=1。历史限为40以后,两项权重分别为16和40,总计数42。第二项进入时以40/56的概率替换当前代表;若随机数0.6令历史替换当前代表,则B选b,S=56,W=56/(42·1)=4/3。若登记的M限为40,候选权重却仍按100计算,历史在选择阶段会被错误放大2.5倍,第二遍分母也与之失配。 限制后的M是重采样质量的记账量,并非独立样本数。按外生规则执行的截断降低旧信息支配程度,并满足[ReSTIR支持域与归一化](/knowledge/12_%E5%85%89%E7%BA%BF%E8%BF%BD%E8%B8%AA/ReSTIR%E6%94%AF%E6%8C%81%E5%9F%9F%E4%B8%8E%E5%BD%92%E4%B8%80%E5%8C%96#%E9%80%92%E5%BD%92%E5%90%88%E5%B9%B6%E7%9A%84%E6%88%90%E7%AB%8B%E6%9D%A1%E4%BB%B6);它不能恢复独立性。动态光源仍要采用参数映射与支持修正,样本驱动的自适应计数则不属于这份证明。 ### 空间读取与最终着色 空间阶段读取冻结的B[x]和相容邻居B[n],重复目标重评估与池合并,输出到C[x]。假设上例B[x]保留b、M=42、W=4/3,另一个邻居B[n]保留a、M=2、W=2,则当前像素收到的权重仍是56和16,总M=44。设邻居的源目标在a、b上都为1。最终若选a,选中来源是邻居,第二遍分子为1;本地B所属表面在a的目标为4,因此分母为42×4+2×1=170,C.W=72/(4×170)=9/85。若选b,来源是本地B,分子为1、分母为44,C.W=72/44=18/11。这里总M仍登记44,但它不能代替实际的目标加权分母。每个数字都来自源池的W、分配计数以及本次代表在各源表面的目标。 使用两个空间输出位置演示原地写回的问题:像素0先把像素1合入自己,像素1随后又读取更新后的像素0,就会间接拿回自己的候选。反过来执行则是另一个结果,单轮采样模型已经改变。因此B在整个空间调度中只读,C只写;多轮空间传播每轮交换两份缓冲,并按轮数记录额外相关性。GPU端在阶段之间建立写后读可见性,不能仅依靠不同调度命令的书写顺序。 最终在当前表面重建选中的光源点,计算完整BRDF、几何项、辐射和当前可见性,再乘C.W。只有代表样本发阴影射线时,未遮挡目标负责选择、当前可见性负责最终贡献,两者职责明确。若墙在这一帧移到光源前,继续使用历史可见值1就会输出亮光;重新追踪得到0才会形成当前阴影。历史可见性缓存是额外质量取舍,需要另设年龄和距离限制。 ### 动态支持的跨帧例子 设前帧表面只能接收a,历史H的支持是{a};当前表面转向后可以接收a和新加入的b。本帧A均匀采样{a,b},K=1、W=2,H始终选a、W=1,本次分配给两源的m都为1。取当前目标在a、b上均为1,历史目标在a为1、b为0。 如果A选a,两项流式权重为2和1。最终样本只能是a,第二遍分母为2、来源分子均为1,所以B.W=3/2。如果A选b,权重仍是2和1:以2/3选b,分母为1,W=3;以1/3选a,分母为2,W=3/2。合并两种等概率的A结果,B在a上的加权质量为1,在b上的加权质量也为1。因此B可以用当前支持{a,b}和当前h继续进入空间阶段,而不是继续标为历史的{a}。 空间邻居若仍只支持a,就再次执行相同的源目标评价和分配,不会把缺失的b算进它的分母。帧末C保存当前表面上下文。下一帧删除a时,代表恰好为a的池产生零选择权重,但它的调度计数和旧支持上下文保留;本帧新鲜池覆盖仍存在的b。把“本次选到已删除光”改成“删除整个来源”,会形成前述样本驱动的接受,不能再用这条递归推导。 ## 可见性与成本 每个候选都发阴影射线,成本随候选数增加。先按未遮挡贡献重采样、只对最后代表发射线,可以把昂贵的可见性查询集中到少数样本。运动遮挡物出现时,重新求可见性仍有必要;直接沿用历史遮挡会使阴影滞后。 ReSTIR 额外保存池数据,执行重投影、邻域读取与目标重评估。复杂 BRDF 或大量邻居会让这些成本超过节省的射线工作。比较时分别记录候选生成、时域、空间、最终阴影和命中着色,使用未降噪结果检查估计均值,再检查降噪后的稳定性。 ## 实现与验证 基础标量检查见 retained_review/restir/check.py,运行 `python -B 知识库/examples/retained_review/restir/check.py`。它保留共同支持且按总M归一化的基线计算,包括空间乘数9/22、支持失配的期望和保守回退。本文连续h路线的空间数例按来源分子与加权分母得到9/85,不能用基线空间结果代替。缓冲顺序和表面接受按正文的数据流推演,尚未执行图像级GPU实现。 CPU参考程序保留 `ris_estimate` 和 `merge_weight` 的独立标量实现。运行 `python 知识库/examples/revision_09_15/test_reference.py`,2026-10-22 的 14 项检查通过,其中四项覆盖离散域期望、全零池、合并权重和目标改变。有限域测试穷举提议组合与最终选择概率,不以随机碰巧接近均值作为通过依据。 支持修正参考实际枚举来源、选择概率和最终乘数;`python -B 知识库/examples/mechanism_chain/restir/test_reference.py`的10项检查覆盖支持缺失、零候选源、不同M、来源分子与面积/参数测度转换。它既复现朴素估计的1.5,也验证两种归一化恢复2。完整图像管线的GPU运行、捕获与计时尚未执行;这些运行状态与正文的完整计算规则分别记录。 ## 相关主题 - [Monte Carlo采样](/knowledge/01_%E6%95%B0%E5%AD%A6%E4%B8%8E%E9%87%87%E6%A0%B7/Monte%20Carlo%E9%87%87%E6%A0%B7) - [实时光追采样](/knowledge/12_%E5%85%89%E7%BA%BF%E8%BF%BD%E8%B8%AA/%E5%AE%9E%E6%97%B6%E5%85%89%E8%BF%BD%E9%87%87%E6%A0%B7) - [光追降噪](/knowledge/12_%E5%85%89%E7%BA%BF%E8%BF%BD%E8%B8%AA/%E5%85%89%E8%BF%BD%E9%99%8D%E5%99%AA) ## 参考资料 - Bitterli 等,[Spatiotemporal Reservoir Resampling](https://research.nvidia.com/labs/rtr/publication/bitterli2020spatiotemporal/),SIGGRAPH 2020:直接光候选和时空复用的原始研究;性能数字属于论文场景,不移作本库测试结果。 - NVIDIA,[RTXDI Reservoir.hlsli](https://github.com/NVIDIA-RTX/RTXDI-Library/blob/main/Include/Rtxdi/DI/Reservoir.hlsli),`RTXDI_DIReservoir`、`RTXDI_CombineDIReservoirs`、`RTXDI_FinalizeResampling`:2026-10-22 核对字段与合并、归一化职责;可变分支仅作核对入口,本文代码为独立推导的算法伪代码。 - [原论文补充材料](https://benedikt-bitterli.me/restir/bitterli20restir-supplemental.pdf),第1节与Algorithm 1:来源目标、可见性与两遍MIS归一化;2026-10-23核读。 - [RTXDI SpatialResampling.hlsli](https://github.com/NVIDIA-RTX/RTXDI-Library/blob/main/Include/Rtxdi/DI/SpatialResampling.hlsli),`RTXDI_DISpatialResampling`的来源记录与第二遍目标重评估;2026-10-23核读可变分支,实际接入锁定提交与修正模式。 - Lin 等,[Generalized Resampled Importance Sampling](https://cwyman.org/papers/sig22_foundationsOfReSTIR.pdf),SIGGRAPH 2022,第4.2—4.3节、公式8与16—18,第4.4—5节:贡献乘数、相关输入、分区条件与收敛的区别;2026-10-23核读。本文外生调度和动态直接光的递归说明是这些条件下的具体构造。