[{"content":"Real-time NRC for Path Tracing 一、导言 离线渲染的时候，一条 Ray 可以 bounce 多次，如 64；而实时光追中，往往只能 bounce 一次。或者说，离线渲染里的 path 是很长的，实时光追里的 path 是很短的。\n那如果说一条光线已经完成 bounce 了，但没有 hit 到 light source 或者 skybox，没法计算能量，那就只能抛弃了，这就导致渲染图上的黑像素，当然，使用一些重要性采样算法，比如ReSTIR 可以很好地改善。\nRadiance Caching 主要就是把一个点辐射出的 Radiance 编码成 Spherical Harmonics，然后在实时渲染中帮助做 shading。可以作为 precomputation 算法，也可以用来加速实时光追。但如果有 Radiance Cache 的加持的话，那些没有得到能量的 ray，可以直接查找最后一次交点在 Radiance Cache 上的值，就知道能量是多少了。因此 Radiance Cache 可以改善实时光追质量。但是传统的Radiance Caching往往很难控制，需要人为干预或者需要用启发式的方法来减少渲染失真的现象。\n在这篇文章中，创新性地使用了神经网络来存储Radiance，而不是使用球谐函数。文中的系统基于以下几个准则设计：\n动态内容 鲁棒性 可预测的性能和资源消耗 前两个原则——动态内容和鲁棒性——对预训练网络提出了重大挑战：训练后的模型必须推广到新的配置，甚至是可能从未观察到的内容。\n该文章的另外一个创新点在于，网络不需要预训练，而是在渲染的过程中实时训练。\n二、理论与实现 NRC的目标是缓存scattered radiance，即下面这项。通俗理解为x点向w发出的光。\n$$ L_s(x,\\omega) = \\int_{\\Omega^+}L_i(x,\\omega_i)f_r(p, \\omega, \\omega_o)(n\\cdot\\omega_i)d\\omega_i $$\n$L_S$是一个相当复杂的函数，直接计算相当复杂，但是我们可以知道$L_s$和许多参数有关，如$x,\\omega,n,albedo, roughness, specular$ 等，那么就可以把这些参数输入到我们的网络里面：\n$$ L_s = NRC(x,\\omega,n,albedo, roughness, specular ) $$\nNRC是一个是通过一个8层64x64的MLP实现。输入的坐标 法线以及view dir都经过了position encoding，使得输入特征与输出尽可能持线性关系。\n在单帧的渲染中包括计算像素颜色和更新神经辐射缓存。\n这里假设渲染用到了三条 ray（三条橙色线），我们只取其中最下面那一条 ray（实际上选取比例远小于三分之一）作为训练集。之后把所有用作训练集的 ray 延长一小段，也就是比之前增加几次 bounce。论文中管增加的这一段叫 training suffix。\n图中橙色的线段就是第一阶段已经 trace 过的 path，蓝色阶段就是训练阶段增加的 path，也就是 training suffix。\n我们利用末端的那个新交点（图中粉色箭头处）查找 Radiance Cache，得到了一个 Radiance 值。我们再把这个 Radiance 值沿着光路反向传递回去，按照 path tracing 的算法计算出之前的三个 bounce 点处的能量值，就可以得到三个 training data，也就是图中的白圈 / 蓝色箭头。它们就是三个标签数据！\nPath Termination:\n所有路径都根据基于路径顶点的area-spread终止，一旦area-spread变得足够大，足以模糊缓存的小范围不准确性，我们就会终止该路径。可以通过下面这个式子估算area-spread:\n$$ a(x_1 \u0026hellip;x_n) = (\\sum_{i=2}^{n}\\sqrt{\\frac{||x_{i-1}-x_{i}||^2}{p(\\omega_i|x_{i-1},\\omega)|cos \\theta_i|}})^2 $$\n$$ a_0 = \\frac{||x_0-x_1||^2}{4\\pi |cos\\theta_0|} $$\n当满足$a(x_1\u0026hellip;x_n)\u0026gt;c\\cdot a_0$时，终止路径。\n当光线被选为training ray时，$a(x_n\u0026hellip;x_m) \u0026gt; c \\cdot a_0$，终止路径。\n闪烁问题\n文章还提到整个训练过程很不稳定，导致输出图像不停地闪烁。于是他们还对神经网络的 weight 做了 temporal filtering，使用 exponential moving average (EMA)：\n$$ \\overline{W_t} = \\frac{1-\\alpha}{\\eta_t} \\cdot W_t + \\alpha \\cdot \\eta_{t-1} \\cdot \\overline{W_{t-1}}, where \\ \\eta_t = 1 - \\alpha^t $$\n当$\\alpha = 0.99$ 时，有最佳结果。\n","permalink":"https://pipiyu1037.github.io/posts/tech/nrcforpt/","summary":"Real-time NRC for Path Tracing 一、导言 离线渲染的时候，一条 Ray 可以 bounce 多次，如 64；而实时光追中，往往只能 bounce 一次。或者说，离线渲染里的 path 是很长的，实时光追里的 path 是很","title":"Real-time NRC for Path Tracing"},{"content":"路径追踪中的多重重要性采样 前言 在GAMES101课程中，介绍了使用蒙特卡洛方法来求解路径追踪问题，为了简化求解过程，当光线打到物体表面发生反射时，我们对表面法线半球进行均匀随机采样来获取反射光线。由于半球上各个方向光线对该物体表面的radiance贡献不同，因此，如果使用随机采样的方法，往往会伴随着非常明显的噪声。因此，使用重要性采样的方法可以帮助我们降噪。\n一、光源重要性采样 1. 重要性采样 首先回顾一下蒙特卡洛积分的基本形式：\n$$ \\int_{a}^{b}f(x)dx = \\frac{1}{N} \\sum_{i = 1}^{N} \\frac{f(X_i)}{pdf(X_i)} $$\n对任意的$f(x)$都可以使用蒙特卡洛方法来近似，通过对指定的概率密度分布进行采样，最终代入求均值即可。但是使用的采样策略（$pdf$）往往会对近似结果的误差和收敛速度产生巨大影响。\n那么采用什么样的采样策略$(pdf)$，可以得到一个误差较小且收敛速度较快的结果呢？\n当$pdf(x)$ 图像和$f(x)$图像越相似时，我们得到的结果会越好，在极端情况下，$pdf(x) = cf(x)$，即$pdf(x)$完全正比于$f(x)$，这个时候方差为0，我们只需采样一次就能得到积分的正确结果。证明如下:\n$$ V(\\frac{1}{N}\\sum_{i=1}^{N}\\frac{f(X_i)}{pdf(X_i)}) = V(\\frac{1}{N}\\sum_{i=1}^{N}\\frac{f(X_i)}{cf(X_i)}) = V(\\frac{1}{N}\\sum_{i=1}^{N}\\frac{1}{c}) = V(\\frac{1}{c}) = 0 $$\n从直观上也很好理解，某一区域函数值较大时，该区域对最终积分值的贡献也越大，因此在该区域采样密度更大时，可以有效加快收敛速度，同时减小误差。\n2. 对光源采样 回到路径追踪的问题中，我们需要求解的方程：\n$$ L_o(p,\\omega_o) = L_e(p,\\omega_o) + \\int_{\\Omega^+}L_i(p,\\omega_i)f_r(p, \\omega_i, \\omega_o)(n\\cdot\\omega_i)d\\omega_i $$\n其中方程的$L_e(p,\\omega_o)$可以直接查询，而后面的积分部分则用蒙特卡洛方法求解，因此，暂不考虑物体的自发光，我们可以求解渲染方程：\n$$ L_o(p,\\omega_o) =\\frac{1}{N}\\sum_{i = 1}^{N} \\frac{L_i(p,\\omega_i)f_r(p, \\omega_i, \\omega_o)(n\\cdot\\omega_i)}{pdf(\\omega_i)} $$\n当$\\omega_i$指向光源时，$L_i(p,\\omega_i)$的值较大，如果暂不考虑$f_r$项，显然，为了减少误差、加快收敛速度，我们应该集中在指向光源的$\\omega_i$处采样。由于光源在场景中的位置是已知的，因此可以直接采样到光源的位置，将对$\\omega_i$的采样转变为对光源面积$A$的采样，我们先改写渲染方程：\n有了渲染方程和求解方法，写出伪代码也很简单：\n二、brdf采样 在对光源重要性采样时，我们只考虑到$L_i(x,\\omega_i)$，而没有考虑$f_r$项的影响，实际上，$f_r(p,\\omega_i,\\omega_o)$也是被积函数的一部分，它决定了光线打到物体上时折射光线的比例、反射光线的比例和分布等信息。如果brdf比较difusse，那么反射光线就会比较均匀地分布在法线半球上，这个时候使用均匀随机采样的策略并没有什么问题，但是如果brdf比较glossy，那么反射光线就会比较集中，只会有一个区域的radiance会对着色点有较大贡献，其他区域的贡献相对小很多，这个时候如果使用均匀随机采样，会产生较大噪声，且不易收敛。相反，重要性采样理论告诉我们，我们需要在反射光线密集的区域采样，这样就会减小噪声，且更易收敛。\n要对brdf进行采样，首先要确定brdf的形式，我们采用Microfacet BRDF：\n$$ f(i,o) = \\frac{F(i,h)G(i,h,o)D(h)}{4(n,i)(n,o)} $$\n其中，i为入射方向，o为出射方向，h为normalize(i+o)，F为菲涅尔项，G为几何函数，D为法线分布函数。菲涅尔项定义了当入射光从不同角度打向平面时，反射光的比例。\n几何函数定义了当入射光从接近平行于表面的方向集中表面时，微表面的自遮蔽。\n法线分布函数为每单位面积,每单位立体角所有法向为$h$的微平面的面积。\n所以这里最后需要的$pdf$是怎么样的呢？\n$$ pdf(\\omega_i) = \\frac{cos \\theta_h}{4\\omega_i \\cdot \\omega_h} D(\\omega_h) $$\n三、多重重要性采样（MIS） 场景中有4个大小不一，颜色不同的光源，悬挂在半空中，还有四块长板子，这4块长板有着不同的光滑程度，最底端的最为粗糙，最顶端的最为光滑。\n在这样一个设置之下直接对光源采样来计算直接光照得到的就是上图中的结果，可以看到在图片的右上角部分十分的noisy。造成这种现象的原因是长板十分光滑，意味着它的BRDF接近delta函数（只有一个小范围才可能对计算结果有贡献），而光源又比较大，在这么大一个光源上进行均匀采样的时候，很难恰好找到那一个有贡献的小的范围，而这就造成了越靠近右上角越noise的现象。\n当我们使用BRDF采样，难看到在图片的左下角依然出现了非常noise的现象，造成这样的结果的原因是长板十分粗糙，所以用BRDF采样的时候其实也就有点接近均匀采样了，那么对于很小的光源几乎就是不可能碰撞到的了。\n不难发现，BRDF采样和光源采样的方法正好互补，使用MIS（Multiple Importance Sampling）可以把这两种方法的优点结合起来。\nMIS提供了一种将多种采样分布结合起来的无偏估计的方法，假设现在有$N$种采样分布，每种采样分布采样了$n_i$个点，则最后的估计为：\n$$ F = \\sum_{i=1}^{N}\\frac{1}{n_i}\\sum_{j = 1}^{n_i}\\omega_i(X_{i,j})\\frac{f(X_{i,j})}{pdf_i(X_{i,j})} $$\n其中，\n$$ \\sum_{i = 1}^{n}\\omega_i(x) = 1 \\ whenever\\ f(x)\\neq 0, \\ \\omega_i(x)=0\\ whenever\\ pdf_i(x) = 0 $$\n在路径追踪问题中，我们的$\\omega(x)$函数定义为： $$ \\omega_i(x) = \\frac{pdf_i(x)}{\\sum_{j}pdf_j(x)} $$\n这种设置方法的目的很直接，倘若在一个点你采样的$pdf$越大，其实也就说明了这个重要性采样分布更加擅长这个区域，理应给它更高的权重，而如果$pdf$小，意味着该重要性采样分布对这个区域没有什么自信，当然应该减小权重，来降低误差。可能这样说比较抽象，=以=开始的场景为例子，假设$pdf_1$为光源采样，$pdf_2$为BRDF采样。\n当在右上角使用光源采样的时候，由于光源较大，那么$pdf_1$自然就会比较小，而BRDF采样由于长板比较光滑，所以$pdf_2$会相对较大，综合下来$\\omega_1$就会比较小，降低了在右上角使用光源采样从而造成的误差(想想第一张图的那些右上角noise，现在都会被乘一个小的权重) 当在左下角使用BRDF采样的时候，由于光源较小，那么$pdf_1$自然就会比较大，而此时长板十分粗糙，所以$pdf_1$就比较小，因此就会比较小，降低了在左上角使用BRDF采样从而造成的误差(想想第二张图的那些左下角noise，现在都会被乘一个小的权重) 在使用了多重重要性采样后，得到最终的效果:\n","permalink":"https://pipiyu1037.github.io/posts/tech/misinpt/","summary":"路径追踪中的多重重要性采样 前言 在GAMES101课程中，介绍了使用蒙特卡洛方法来求解路径追踪问题，为了简化求解过程，当光线打到物体表面发生反","title":"路径追踪中的多重重要性采样"},{"content":"ReSTIR RIS(Resampled Importance Sampling) 工作流程 从一个易于采样的分布 $ p\\ (e.g.\\ p\\propto L_e) $中生成M个candidate samples $\\mathbf{x} = {x_1,\u0026hellip;,x_M }$\n用离散概率分布$p(z|\\mathbf{x})$从candidate samples中随机选择索引$z \\in {1,\u0026hellip;,M }$\n$$ p(z|\\mathbf{x}) = \\frac{\\mathrm{w}(x_z)}{\\sum_{i=1}^{M}\\mathrm{w}(x_i)}\\ \\ with\\ \\ \\mathrm{w}(x) = \\frac{\\hat{p}(x)}{p(x)} $$\n$\\hat{p}(x)\\ (e.g.\\ \\ \\hat{p} \\propto L_e \\cdot f_r \\cdot cosine)$是目标分布(target pdf)。\n挑选出一个样本 $y= x_z$ ,用于单样本的蒙特卡洛估计。\n$$ I_{ris}^{1,M} = \\frac{f(y)}{\\hat{p}(y)}\\cdot(\\frac{1}{M}\\sum_{j=1}^{M}\\mathrm{w}(x_j)) $$\n重复采样，采样出多个$y$ ，用于N样本的蒙特卡洛估计。\n$$ I_{ris}^{N,M} = \\frac{1}{N}\\sum_{i=1}^{N} \\Bigl( \\frac{f(y_i)}{\\hat{p}(y_i)}\\cdot \\bigl(\\frac{1}{M}\\sum_{j=1}^{M}\\mathrm{w}(x_{ij})\\bigl)\\Bigl) $$\n注意事项 $M,N \\geqslant 1$ 当$f(x)$非0时，$p,\\hat{p}$也非0 MIS和RIS 从多个分布$p_i$中，生成M个candidate samples $\\mathbf{x} = {x_1,\u0026hellip;,x_M }$\n使用重要性权重\n$$ \\mathrm{w}i(x) = \\omega{i,mis}(x)\\cdot \\frac{\\hat{p}(x)}{p_i(x)} $$\n$$ W = \\sum_{i=1}^{M}\\mathrm{w}_i(x_i) $$\n蒙特卡洛估计\n$$ I^1 = \\frac{f(y)}{\\hat{p}(y)} \\cdot W \\ I^N = \\frac{1}{N}\\sum_{i=1}^{N}(\\frac{f(y_i)}{\\hat{p}(y_i)}W) $$\nWRS(Weighted Reservoir Sampling) WRS是在一次遍历中从$\\mathbf{x} = {x_1,\u0026hellip;,x_M }$ 中采样出N个元素的一类方法。每个元素$x_i$被选取的概率为：\n$$ P_i = \\frac{\\mathrm{w}(x_i)}{\\sum_{j=1}^{M}\\mathrm{w}(x_j)} $$\n伪代码：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Class Reservoir{ y = 0; W_sum = 0; M = 0; W = 0; update(x,w_i){ w_sum = w_sum + w_i; M = M + 1; if(rand() \u0026lt; (w_i/w_sum)) y = x_i } } reservoirSampling(Samples){ Reservoir r; for i = 1 to M r.update(Samples[i], weight[Samples[i]]) return r } 结合WRS和RIS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 foreach pixel in Image: Image[q] = shadePixel(RIS(q),q) RIS(q){ Reservior r; for i = 1 to M: generate x_i ~ p; r.update(x_i, P(x_i)/p(x_i)); r.W = r.W_sum/(P(r.y) * r.M); return r; } shadePixel(Reservior r, q){ return f(r.y) * r.W; } 其中：\n$$ r.W = \\frac{1}{\\hat{p}(r.y)}(\\frac{1}{M}\\sum_{i = 1}^{M}\\mathrm{w}_i(x_i)) $$\n样本时空复用 空域复用 需要用到两个pass，第一个pass记录当前像素的reservoir，第二个pass复用邻近像素的reservoir。\n第一步： 在每个像素上使用RIS(q)生成M个candidate samples，然后在一个图像大小的的缓冲中存错每个像素的reservoir的结果。\n第二步： 每个像素挑选出k个相邻像素，并将这些像素上的reservoir与自身reservoir结合。\n这样，在每个像素上的开销位O(k+M),但是每个像素使用的candidate samples有k*M个。迭代多次这个过程，开销位O(nk+M), 每个像素使用的candidate samples$k^nM$个。\n时域复用 重用上一帧的reservoir。\n多分布RIS中的Bias 首先把蒙特卡洛估计器改写为：\n$$ L_{ris}^{1,M} = f(y)\\cdot \\Bigl( \\frac{1}{\\hat{p}(y)} \\cdot \\frac{1}{M} \\cdot \\sum_{j = 1}^{M} \\mathrm{w}(x_j) \\Bigr) = f(y)\\cdot W(\\mathbf{x},z) $$\n$$ W(\\mathbf{x},z) = \\frac{1}{\\hat{p}(x_z)} \\cdot \\Bigl(\\frac{1}{M} \\cdot \\sum_{i = 1}^{M}\\mathrm{w}_i(x_i) \\Bigr) $$\n在这个估计器中，用$W$去替代了1/$p(y)$。\n在多分布的RIS中，由于candidate samples $\\mathbf{x}$中的样本$x_i$可以来源于不同的采样$p_i(x_i)$，有：\n$$ p(\\mathbf{x}) = \\prod_{i = 1}^{M}p_i(x_i) $$\n在前面已经提到，从candidate samples中选择样本的策略：\n$$ p(z|\\mathbf{x}) = \\frac{\\mathrm{w}z(x_z)}{\\sum{i=1}^{M}\\mathrm{w}_i(x_i)}\\ \\ with\\ \\ \\mathrm{w}_i(x_i) = \\frac{\\hat{p}(x_i)}{p_i(x_i)} $$\n因此，\n$$ p(\\mathbf{x},z) = p(z|\\mathbf{x})\\cdot p(\\mathbf{x}) = (\\prod_{i = 1}^{M}p_i(x_i)) \\frac{\\mathrm{w}z(x_z)}{\\sum{i=1}^{M}\\mathrm{w}_i(x_i)}\\ \\ with\\ \\ \\mathrm{w}_i(x_i) = \\frac{\\hat{p}(x_i)}{p_i(x_i)} $$\n记集合：\n$$ Z(y) = {i|1 \\leqslant i \\leqslant M\\ \\wedge \\ p_i(y) \u0026gt; 0 } $$\n则$p(y)$可以写作：\n$$ p(y) = \\sum_{i \\in Z(y)} \\underbrace{\\int \u0026hellip;\\int}{M-1 \\ times}p(\\mathbf{x}^{i \\to y},i)\\underbrace{dx_1\u0026hellip;dx_M}{M-1 \\ times} $$\n其中 $\\mathbf{x}^{i \\to y} = {x_1,\u0026hellip;,x_{i-1}, y, x_{i+1},\u0026hellip;x_M }$。\n条件期望：\n$$ E_{x_z = y}(W(\\mathbf{x},z))= \\sum_{i \\in Z(y)} \\frac{ \\int \u0026hellip;\\int W(\\mathbf{x}^{i \\to y},i)p(\\mathbf{x}^{i \\to y},i)dx_1\u0026hellip;dx_M}{p(y)} $$\n最终可计算出:\n$$ E_{x_z = y}(W(\\mathbf{x},z))= \\frac{1}{p(y)} \\cdot (\\frac{|Z(y)|}{M}) $$\n所以，在目标pdf非0处，任何candidate pdf也非0时，则$|Z(y)| = M$,此时RIS就是无偏的，反之则$|Z(y)| \u0026lt; M$。导致$E_{x_z = y}(W(\\mathbf{x},z)) \u0026lt; \\frac{1}{p(y)}$ ，，图像会偏暗。\n无偏RIS 为了达到无偏的RIS，可以对权重因子进行修改，不再使用$\\frac{1}{M}$作为权重因子，而是取一个权重$m(x_z)$\n$$ W(\\mathbf{x},z) = \\frac{1}{\\hat{p}(x_z)} \\cdot \\Bigl(m(x_z)\\cdot \\sum_{i = 1}^{M}\\mathrm{w}_i(x_i) \\Bigr) $$\n则计算条件期望：\n$$ E_{x_z = y}(W(\\mathbf{x},z))= \\frac{1}{p(y)} \\cdot (\\sum_{i \\in Z(y)}m(x_i)) $$\n因此只要$\\sum_{i \\in Z(y)}m(x_i) =1$，就可以得到一个无偏的结果。\n显然，当$m(x_z) = \\frac{1}{|Z(x_z)|}$时，满足条件。\n这里也可以结合MIS：\n$$ m(x_z) = \\frac{p_z(x_z)}{\\sum_{i = 0}^{M}p_i(x_z)} $$\n","permalink":"https://pipiyu1037.github.io/posts/tech/restir/","summary":"ReSTIR RIS(Resampled Importance Sampling) 工作流程 从一个易于采样的分布 $ p\\ (e.g.\\ p\\propto L_e) $中生成M个candidate samples $\\mathbf{x} = {x_1,\u0026hellip;,x_M }$ 用离散概率分布$p(z|\\mathbf{x})$从ca","title":"ReSTIR"},{"content":"","permalink":"https://pipiyu1037.github.io/links/","summary":"","title":"🤝友链"},{"content":"关于我\nName: pipiyu Edu: BEng in HUST, Msc inHKUST hobby: Guitar, Football ","permalink":"https://pipiyu1037.github.io/about/","summary":"关于我 Name: pipiyu Edu: BEng in HUST, Msc inHKUST hobby: Guitar, Football","title":"🙋🏻‍♂️关于"}]