最新要闻
- 马斯克要自建“乌托邦小镇”:员工全部搬进去 自己当“镇长”
- 拒绝投影行业亮度虚标!Vidda官宣三色激光全家桶新品
- 环球最资讯丨新一轮国内油价将于17日迎来调整:有再度搁浅可能
- 【环球聚看点】彻底解决“刹车争议”!电商平台上线特斯拉脚部专用记录仪:全程摄像
- 天天视讯!GTX 1050 Ti就能跑!顽皮狗公布《最后生还者:Part 1》PC版配置要求
- 世界看点:自称12年驾龄 特斯拉Model X车主在线维权:踩刹车没反应加速撞柱子
- 天天观察:苹果古典音乐软件已上架:Apple Music会员免费用!中国市场随后推出
- 当前资讯!明基推出首款48寸OLED电竞显示器:4K 120Hz、90W反向供电
- 《生化危机4:重制版》PS5版疑似已偷跑 小心剧透啊
- 世界百事通!illustrator学习心得体会(illustrator序列号)
- 65寸4K大屏电视不到2000元 LCD白菜价即将结束:3月价格上涨10%
- 环球微头条丨最强AI再次进化 ChatGPT下周升级GPT-4:支持视频了
- 【环球聚看点】免费玩!《生化危机4:重制版》体验版上线:不限时、不限次
- 当前滚动:德国电动空中出租车Lilium jet完成测试:时速250km/h 全机36个电风扇
- 杀疯了!长安深夜放大招 购车百亿补贴:深蓝SL03直降2.2万
- 世界观点:佳兆业成今年首家复牌出险房企
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
多光源渲染方案 - Many Lights Sampling
- Importance Sampling(IS)
- Light BVH [2018~2019]
- 预构建 BVH
- 重建 BVH
- 基于 BVH node 的 IS
- Real-time Stochastic Lightcuts [2020]
- 莫顿序排序(Morton Order Softing)
- 构建 Light Tree
- 基于 Lightcuts 的 IS
- Cut Sharing
- ReSTIR(Reservoir Spatio-Temporal Importance Resampling)[2020]
- Resampled Importance Sampling (RIS)
- Weighted Reservoir Sampling (WRS)
- 基于屏幕空间的多光源 RIS
- 预处理光源
- pixel 蓄水池
- 有偏时空复用
- 无偏时空复用
- ReGIR [2021]
- 基于 Grid 的多光源 RIS
- light slot 蓄水池
- 时序复用
- 动态光源问题
- 基于屏幕空间的多光源 RIS
- pixel 蓄水池
- light slot 蓄水池接入 pixel 蓄水池
- 时空复用
- 优化
- grid 结构
- 跳过无关 cell 的填充
- 可伸缩更新
- 扩展到其它渲染方案
- 基于 Grid 的多光源 RIS
- 参考
light culling 的方式,可以极大剔除要处理的光源数量,但是可能有以下问题:
- 实际光源的影响范围是无穷远的(通过 \(\frac{1}{\mathrm{dist}^2}\) 来实现衰减),强行设置有限影响范围(为了形成包围盒)会导致能量截断。
- 面对 rect light,emissive triangle 等不可解析光源,光源影响范围包围盒不好确定
而 many lights sampling 的解决思路是只处理众多光源中的少量光源,但是让计算结果趋于无偏结果(无偏结果即相当于处理了所有光源)。
注意:many lights sampling 和 light sampling 是不同的,后者是在需要处理某一个不可解析光源的前提下,对其面积进行采样,从而算出该光源的贡献结果。在处理多个不可解析光源时,往往需要搭配 many lights sampling 方法:先通过 many lights sampling 选择处理哪几个光源,再对每个要处理的光源分别进行 light sampling。
(资料图)
Importance Sampling(IS)
当采用蒙特卡洛积分方法计算积分时,需要对被积函数 \(f\) 进行采样。
IS:可以按照分布 \(p\) 生成样本(其实就是采样),并且分布 \(p\) 越接近实际分布,那么收敛的速度就越快(所需的样本数 \(N\) 就可以更少了):
\[I = \int f(x) dx \approx \frac{1}{N}\sum_{i=1}^{N}\frac{f(x_i)}{p(x_i)}\]当 \(N\) 趋向无穷时,最右式便会等于 \(I\)。此外,要保持 IS 的无偏,需要保证被积函数 \(f(x)>0\) 的所有位置上,\(p\) 需 \(>0\)。
对于 many lights sampling 来说,虽然累积 lights 的贡献是离散的,但是太过多的光源数量可以让我们把它看成一种积分,并且需要设计一种采样分布 \(p\) 让重要的光源更容易被采样。
最简单的方式,例如:
我们可以用各个 light 的 intensity 来作为采样分布的依据( intensity 大的光源更重要,即 pdf 应当更大)。
- total intensity:计算出所有 lights 的 intensity 总和。
- 某个 light 的 pdf:该 light 的 intensity 除于 totoal intensity
i = 0sum = 0r = rand in [0,1]for i in range lightsNum sum += pdf_i if sum > r pick i to calculate L return L
当然,更进一步的优化是:提前建立好前缀和数组,这样就不必逐个累加 cdf,而是采用二分的方式计算 cdf。
Light BVH [2018~2019]
相关 paper:
- Importance Sampling of Many Lights with Adaptive Tree Splitting [Conty, Kulla 2018]
- Importance Sampling of Many Lights on the GPU | Ray Tracing Gems [2019]
- Dynamic Many-Light Sampling for Real-Time Ray Tracing [Moreau 2019]
Light BVH 类方法需要将所有光源转化成 emissive triangles,然后针对 emissive triangles 建立 BVH 结构来方便进行多光源的 IS 。
Dynamic Many-Light Sampling for Real-Time Ray Tracing 提出采用两层 BVH 结构:bottom-level acceleration structure (BLAS) 和 top-level acceleration structure (TLAS)。
这其实就是类似于 ray tracing 里用于加速 ray-triangle 的 BVH 结构。
其中,一个 mesh instance 将对应一个 BLAS ,BLAS 的 leaf node 将存储若干个 emissive triangles;而 TLAS 的 leaf node 将存储一个 BLAS。
图中每个黄色包围盒就是一个 BLAS 的 root node。
预构建 BVH
这部分其实可以用神经网络去针对场景训练一个最佳的 BVH 划分结构。
需要预先对所有 emissive triangles 划分,构建出一棵好的两层 BVH 树。
假设现在的 node 已经划分成了 L 和 R 两边,则可以有以下两种启发式去评判这种划分的好坏:
- VH:考虑了两边子结点的 triangles 数量与形成的子包围盒体积。
\(n\) 代表了 node 的 triangles 数量,\(v\) 代表了 node 的包围盒体积。
- VOH:在 VH 的基础上额外考虑了两边的光源朝向分布和光源功率。
\(\Phi\) 代表了 node 里所有 triangles 组成的 cluster flux ,\(M_{\Omega}\) 代表了光源朝向的相似值。
更古早的方法有 SAH 和 SAHO,其实就是把包围盒体积项换成包围盒表面积项。
这样,我们就可以尝试所有的划分组合,然后根据评判启发式来选择最佳的划分组合来自底向上建立 BVH 树:
- 建立 BLASes:以对应 mesh 的所有 triangles 为 leaf node,组建出一棵 BLAS;多个 mesh 便会对应输出多棵 BLASes。
- 建立 TLAS:以 mesh 为 leaf node,组件出一棵 TLAS。
重建 BVH
预构建 BLAS 和 TLAS 之后,在运行时一旦某个 triangle 发生变化(如 triangle 发生 flux 变化,位置变化等),就需要更新它们。
- refit BLAS:每帧在 GPU 里根据 emissive triangles 来更新 BLAS 结构的各个 node 属性,但不会改变 BLAS 树的结构。
- refit TLAS:每帧在 GPU 里根据 mesh 来更新 TLAS 结构的各个 node 属性,但不会改变 TLAS 树的结构。
- rebuild TLAS:每帧在 CPU 里根据 mesh 来重新划分 node,需要改变 TLAS 树的结构,并将新的 TLAS 结构 upload 给 GPU 的 refit TLAS 阶段。
这样,一旦某个 emissive triangle 更新了,只会影响它所在的 BLAS 和 TLAS ,而不会影响其它的 BLASes,从而具有实时 rebuild BVH 的能力。
基于 BVH node 的 IS
不管是 TLAS 还是 BLAS,node 都应该额外存储以下属性:
- \(C\): node 中心坐标
- \(\Phi\): cluster flux,用于近似代表包含在内的所有 triangles 的 flux
- light orientation cone axis 和 \(\theta_o\) : 前者代表了 node 内所有光源朝向的中心朝向;后者代表了最远的光源朝向与 light orientation cone axis 的夹角。
- \(\theta_e\) : 代表了围绕光源朝向的最远发射角
例如对于单个 emssive triangle 来说,\({\theta}_o = 0\) (因为只有一个法线朝向), \({\theta_e = \frac{\pi}{2}}\) (因为在半球方向上会发射光);而对于无数个 emissive triangles 组成的发光球来说, \({\theta}_o = \pi\) (因为该球的法线朝向布满了所有方向), \({\theta_e = \frac{\pi}{2}}\) (因为每个 emissive triangle 都会在半球方向上会发射光);对于 spot light 来说,\({\theta}_o = 0\),而 \({\theta}_e\) 将取决于 spot light 的锥形半角。
再举个例子:如图右两个 spot light 组成了一个 node,那么 light orientation cone axis 便是两个 spot light 光源朝向的中心向量,\(\theta_{o}\) 为最远的光源朝向到 light orientation cone axis 的夹角(node 仅有两个光源的情况下,两个夹角其实是一样的),\(\theta_{e}\) 则等于半角最大的那个 spot light 的半角。
这样有了 BVH 结构后,我们就可以用来做 many lights sampling 的 IS 了。每次对于 shading point \(X\),我们可以自顶向下遍历 BVH 树。在遍历 node 时候往 node 中心投射一个可以刚好包住 node 包围盒的 cone,并通过以下公式判定一个 node 的 importance:
\[importance (X, C)=\frac{\Phi(C)\left|\cos \theta_i^{\prime}\right|}{\|X-C\|^2} \times \begin{cases}\cos \theta^{\prime} & \text { if } \theta^{\prime}<\theta_e, \\ 0 & \text { otherwise, }\end{cases}\]其中,\(\theta_i"=max(0,\theta_i-\theta_u)\),\(\theta"=max(0,\theta-{\theta}_o-{\theta}_u)\)
这样就可以通过遍历 node 判断左结点和右结点的 importance,来让权重高的一边 node 更容易被选中。
Real-time Stochastic Lightcuts [2020]
相关 paper:
- Lightcuts: A Scalable Approach to Illumination [Walter 2005]
- Real-Time Stochastic Lightcuts Proceedings of the ACM on computer graphics and interactive techniques. [Yuksel 2020]
莫顿序排序(Morton Order Softing)
在 view space 下,每个 light 的位置编码成 Morton code(30 bits,x/y/z 分别占 10 bits),并利用 双调排序(Bitonic Softing)来排序。
简单介绍下莫顿序:莫顿序有一个这样好的性质——序列里邻近的元素在空间上也会比较邻近。并且,莫顿序排序的结果就隐含了空间的层次,从而不需要构建真正的 BVH 结构。
2D 莫顿序:
3D 莫顿序:(序列邻近则体现出颜色相近)
再简单介绍下双调排序:通常基于比较的 CPU 排序复杂度在 \(O(n\log n)\) ;而双调排序是针对并行计算而生的算法,复杂度为 \(O(n(\log n)^2)\),然而得益于 GPU 的巨量线程数,算法复杂度中的 \(n\) 是可以独立并行的,也就是说实际复杂度为 \(O((\log n)^2)\)。关于该排序算法的细节,可参考 DirectX11 With Windows SDK--27 计算着色器:双调排序 - X_Jun - 博客园。
构建 Light Tree
为了满足 GPU 的并行化计算,论文采用完美二叉树作为 light tree 的结构,省去了指针的表示(因为索引本身就暗含了结点关系)。这样,就可以按以下流程构建 light tree:
- 一个叶结点存储一个 light id,将已经进行莫顿序排序的 light 按序一个个填入完美二叉树的最低层级,若不能填满,则加入 false lights(flux 为 0 的假灯)直至填满。
- 从最低层开始自底向上构建父结点(同一层的计算可并行化):只需要将两个子结点的 intensity 直接相加作为父结点的 intensity,和计算出能包围两个子结点的 AABB 大小。
基于 Lightcuts 的 IS
有了 light tree 后,我们就可以自顶向下遍历,并根据概率选择一个子结点往下走,直到选择的结点 light 数量小于等于 lightcuts 所限制的 light 数量。
stochastic lightcuts 的早期论文是需要预构建 light tree,并且父结点不是简单的子结点 intensity 相加,而是用复杂的算法计算出一个可以代表两子结点的表征光源(包含位置和强度等)。然后在 sampling 时也一样自顶向下往下走,但对于路径中没有走的 brother node,将直接使用它的表征光源来代表,这种方式其实是有偏的,不过收敛是很快。
而这种自顶向下的走法就像是刀往 light tree 上 cut 来 cut 去,所以称为 light cut。
不过现在这个 real-time stochastic lightcuts 只是一个纯粹的 importance sampling 方法,具有无偏的性质。
每个子结点(假设为 node \(j\) )的 importance 计算如下:
\[w_j^{\min }=\frac{F_j(\mathrm{x}, \omega)\left\|\mathbf{I}_j\right\|}{\left(d_j^{\min }(\mathrm{x})\right)^2} \quad w_j^{\max }=\frac{F_j(\mathrm{x}, \omega)\left\|\mathbf{I}_j\right\|}{\left(d_j^{\max }(\mathrm{x})\right)^2}\]\(F_j(x,\omega)\) 为反射率界限(一般就是剔除无关参数的 brdf 项),\(\mathbf{I}_j\) 为 node 的 intensity,\(d^{min}\) 和 \(d^{max}\) 分别代表 shading point x 到该 node 的 AABB 的最近距离和最远距离。
特殊地,当 shading point 在 node 的包围盒内,其 \(d^{min}\) 和 \(d^{max}\) 均为 0,这时候同时忽略两个 node importance 的 \(d\) 相关项。
然后选择 node \(j\) 的概率即为 \(p_j^{min}\) 和 \(p_j^{max}\) 的一半:
\[p_j^{\min }=\frac{w_j^{\min }}{w_j^{\min }+w_k^{\min }} \quad p_j^{\max }=\frac{w_j^{\max }}{w_j^{\max }+w_k^{\max }}\]\[p_j=\left(p_j^{\min }+p_j^{\max }\right) / 2\]使用 min 和 max 的一半是为了同时考虑最坏情况和最好情况(如包围盒可能过大,x 与 AABB 的距离可以接近于0,最远的却可以拉到无穷远),虽然个人觉得还是很 hack。
Cut Sharing
相邻的 pixel 因为距离较近,因此它们通常具有相同的 cut 法,这就造成了一些 sampling 的浪费。
我们可以用一组相邻的 pixels 去做一次包含较多 light 数量的 cut,而不是对每个 pixel 分别去做一次包含较少 light 数量的 cut。这种空间复用的思路可以极大减少 sampling 时间,但是当然也会随着组内 pixels 数量的增多而更加有偏:
ReSTIR(Reservoir Spatio-Temporal Importance Resampling)[2020]
相关 paper:
- Spatiotemporal reservoir resampling for real-time ray tracing with dynamic direct lighting [BENEDIKT 2020]
ReSTIR 是近期实时渲染的热门前沿方向,许多渲染算法都可以用到这种采样思想。ReSTIR 应用在直接光照的时候,可以很好的应对 many lights sampling 的问题。
Resampled Importance Sampling (RIS)
假设我们有一个极度贴近实际分布的好分布 \(\hat{p}\),但它不好生成样本,只适合评估样本;另一方面,我们又有另一个比较简单的分布 \(p\) ,虽然它简单地足以能够生成样本,但是这个分布又比较偏离实际分布。
RIS:先用简单分布 \(p\) 生成 \(M\) 个样本,再从这 \(M\) 个样本用复杂分布 \(\hat{p}\) 再挑出 1 个样本(要用 RIS 输出 \(N\) 个样本,也只需要独立地调用 N 次 one-sample RIS 即可)。RIS 的效果一般来说要好过纯粹用 \(p\) 来进行 IS。
\[I = \int f(x) dx \approx \frac{f(y)}{\hat{p}(y)} (\frac{1}{M}\sum_{j=1}^{M}\mathrm{w}(x_{j}))\]不过要保持 RIS 的无偏,需要保证被积函数 \(f(x)>0\) 的所有位置上,\(p\) 和 \(\hat{p}\) 都需 \(>0\)。
\[\mathrm{w(x)} = \frac{\hat{p}(x)}{p(x)}\]\(x_{j}\) 为 \(p\) 生成的第 \(j\) 个样本,\(y\) 为 \(\hat{p}\) 挑选出的样本。
当然实际上挑样本是根据权重 \(\mathrm{w}\) 来挑:因为生成的 \(M\) 个样本中每个样本生成的概率是不同的,所以需要除掉 \(p\) 抵消掉这个概率,接着便是通过乘 \(\hat{p}\) 来决定哪个样本更容易被挑中。
原论文伪代码如下:
Weighted Reservoir Sampling (WRS)
原本最原始的 RIS 算法便是先用简单分布 \(p\) 生成 M 个样本再用复杂分布 \(\hat{p}\) 去挑一个样本,但是这需要占用 M 个样本存储空间;而 WRS 聪明地将 RIS 的算法改造成了流式算法,让空间复杂度与 M 无关(只需要记录三个属性),这就意味着甚至 M 无穷大都可以容纳(精度足够的情况下)。
核心就是改造成了一个蓄水池结构(reservoir),它只需要存储:
- \(y\):一个用于输出的样本,也可以理解成经过 \(M\) 次输入后留下来的 winner 样本。
- \(\mathrm{w}_{sum}\):输入过的样本的权重 \(\mathrm{w}\) 总和。
- \(M\):输入过的样本数量。
然后可以源源不断给蓄水池输入新样本,每次输入新样本时它便会根据权重 \(\mathrm{w}\) 去决定留下旧样本还是留下新样本。
这种逐次淘汰样本的方式,和原始 RIS 先生成一堆样本再选一个 winner 样本的方式,在本质上是一致的,可以自行推理一下数学逻辑。
原论文伪代码如下:
基于屏幕空间的多光源 RIS
接下来将用 WRS 应用到直接光照着色的 many lights sampling 上,然后用于 RIS 的简单分布和复杂分布分别如下:
- source pdf \(p\) :归一化的 intensity pdf,光源强度越大的光源则越容易被挑中。
- target pdf \(\hat{p}\) :lighting pdf,即着色函数除了 visibility 的部分,更加贴合着色函数的分布(实际分布)。
预处理光源
预先将所有光源的 intensity 总和 \(I_{total}\) 计算出来和建立好 \(I\) 的前缀和数组,这样在后续通过 \(p\) 生成候选样本时就不必逐个累加 cdf,而是采用二分的方式计算 cdf。
\(p(x_i) = \frac{I(x_i)}{I_{total}}\)
pixel 蓄水池
每个 pixel \(q\) 包含一个蓄水池,然后在一帧内可以给它输入 M 次 \(p\) 生成的候选光源样本,此时蓄水池的 \(y\) 便是最终挑选的光源样本,便可以用来计算它对 pixel 的贡献:
\[I = \int f(x) dx \approx \frac{f(y)}{\hat{p}(y)} (\frac{1}{M}\sum_{j=1}^{M}\mathrm{w}(x_{j}))\]顺便需要记录一下蓄水池的当前样本权重 \(\mathrm{w}\),可见公式推导。
原论文伪代码如下:
效果图:
图中下面的方式是 Light BVH 方法,而上面的方式则是不同 \(M,N\) 的 RIS 方法。
有偏时空复用
上面我们知道, \(M\) 的数量足够多时,RIS 的效果会变得相当好,但是 pixel \(p\) 每帧生成足够多的候选样本也同样很费时,一个很自然的想法是能不能在时序上和在空间上复用样本来增加样本数:
空间复用(spatial reuse):当前 pixel \(p\) 和附近的 pixels 往往在几何和材质上是非常相似的,可以进行空间上的复用。
- 可以对周围 \(k\) 个 pixels 的蓄水池进行一次组合:这样每个 pixel 只需要耗费 \(O(k+M)\) 的时间而获得 \(O(k\cdot M)\) 个候选样本。
- 甚至这种组合是可以多次迭代的(假设迭代了 \(n\) 次),从而让 pixels 的蓄水池样本扩散到更多别的 pixels:耗费 \(O(nk+M)\) 的时间而获得 \(O(k^n M)\) 个候选样本。
时间复用(temporal reuse):将当前 pixel \(p\) 投影到上一帧,并找到投影位置附近的 previous pixels,它们往往在几何和材质上也是非常相似的,可以进行时序上的复用。
- 直接组合上一帧投影位置附近的 previous pixels 的蓄水池,随着帧数的累积(假设累积了 \(t\) 帧)便可以有 \(O(t\cdot(k^nM))\) 个候选样本。
可见性复用(visibility reuse):候选样本数接近无限多时,样本分布也基本接近 target pdf \(\hat{p}\) ,但还是无法实现无噪渲染。毕竟真正的分布是 \(\hat{p}\cdot V\),也就是说引起噪声的因素就剩下了 visibility \(V\)。
- 为了减少 visibility 噪声的传播,每个蓄水池在执行时空重用前,需要对自己的输出样本进行一次 shadow ray 检测自己的输出样本 \(y\) 是否有效,若无效,则将 \(W\) 置为 0,避免传播到相邻的蓄水池。
具体组合蓄水池的伪代码如下:
可以这么理解:假设我们要合并蓄水池 \(r\) 到 \(s\),实际上做的就是把 \(r\) 所有候选样本再次逐个输入到 \(q\),因此需要重新累积 \(q\) 的 \(\mathrm{w}_{sum}\) 和 \(M\)。
而用 \(r.W\) 乘上 \(r.M\) 就能得到 \(\frac{r.\mathrm{w}_{sum}}{\hat{p_{r}}(y)}\),即实际更新权重为 \(\hat{p}_q(r . y) \cdot r . W \cdot r . M = \frac{\hat{p_q}(r.y)}{\hat{p_r}(r.y)}\cdot r.\mathrm{w}_{sum}\) 。但毕竟输入给 \(q\) 的只有这 \(M\) 个样本中的一个而不是输入了 M 个样本,因此除 \(\hat{p_r}(r.y)\) 是为了抵消掉选这个 y 样本的概率,再用 \(\hat{p_q}(r.y)\) 评估这 M 个样本的质量。
无偏时空复用
实际上,上面的时空复用忽略了一个细节:pixel \(q\) 附近的 pixels 或者投影到上一帧的附近 pixels 在几何和材质上虽然接近,但不完全一样,也就是说这些 pixels 各自的样本空间是不同的,这就会导致偏差的诞生。
具体如何分析偏差建议可以看原论文,此处只写博主的大概理解。
前面 RIS 的理论我们知道:在某个样本空间中,被积函数 \(f(x)>0\) 的所有位置上,\(p(x)\) 和 \(\hat{p}(x)\) 都需 \(>0\)。
- 因为 \(p\) 是 intensity pdf,它在任何样本空间总是能满足 \(p>0\) 。
- 而假设我们通过了时空复用后得到了一个样本 \(y\) ,既然能选中该样本,那就说明可能会得到 \(f(y)>0\) (取决于 visibility);假设某些时候,visibility 为 1,也就是说在被复用的各个 pixel 样本空间中 \(f(y)\) 均被视为 \(>0\) 了,但是在其中某些样本空间中 \(\hat{p}(y)\) 却实际是为 0 的,这就违反了 RIS 的无偏规则。
因此,我们通过时空复用后,得到本次的样本输出 \(y\),再对被复用的 pixels 蓄水池做一遍检查,看看在它们各自的样本空间中 \(\hat{p}(y)\) 是否 \(>0\) ;若没通过检查,则该蓄水池的样本数不算入本次输出的 \(W\)。
引入无偏的时空复用后,候选样本的数量可能就不会像有偏方法那么多,因此收敛更慢;而且还引入了一些额外的计算(主要指重新检查一边蓄水池),导致更加耗性能。下面是一些效果比较:
ReGIR [2021]
相关资料:
- Rendering Many Lights with Grid-based Reservoirs [2021]
核心就是将 RIS 同时应用到 grid 和屏幕,即:用 cell 蓄水池先粗略采集一波光源样本,再让 pixel 抖动一下找到对应的 cell 并将该 cell 的蓄水池样本再输入到 pixel 蓄水池,最终选定哪个光源样本用于 pixel 的 shading。
其实思想就是空间复用,毕竟部分 pixels 是在同一个 cell 里,先在 cell 里用粗略的 target pdf 才一遍后,就可以留下了质量还可以的样本;而 pixels 就可以用精确的 target pdf 从这些样本中挑选,而不是从 IS 里生成的样本(基于 intensity 的 IS 所生成的样本质量还是挺差的)里挑选。
ReGIR 效果图:
可以看到 ReGIR 在 many lights sampling 的效果中比基础 RIS 收敛还要快。
基于 Grid 的多光源 RIS
light slot 蓄水池
每个 cell 存储若干个蓄水池(原文里称为 light slots,一个 light slot 其实就是对应一个蓄水池),原文默认是每个 cell 包含 512 个蓄水池,实际上也就隐含了有 512 个输出用的光源样本(即 \(N=512\))。
每个蓄水池都可以独立地进行 stream RIS 流程,其两个 pdf 分别为:
- source pdf \(p\) :每个光源都相同的概率,即为 \(\frac{1}{\mathrm{NumLight}}\)
- target pdf \(\hat{p}\) :\(\frac{\mathrm{I}}{r^2}\)
其中 \(\mathrm{I}\) 为光源的 intensity,\(r\) 为光源到本 cell 中心的位置。
float3 lightVector = candidate.position - gridCellCenter;float lightDistanceSquared = max(gMinDistanceSquared , dot(lightVector , lightVector));float sourcePdf =
可以看到这个 source pdf 非常简单,实现上就是随机选一个光源;而 target pdf 则是考虑了 intensity 和距离衰减因素。
原文在蓄水池中默认采 \(M=8\) 个候选样本,再增加候选样本数带来的收益会有边际效应。
个人认为,cell 没有使用一个大型蓄水池(\(M=512*8\) 个候选样本)而是分成 512 个小型蓄水池(\(M=8\))来其实是为了让算法高度并行化,代价就是额外的空间开销。
时序复用
light slot 蓄水池没有空间复用。
时序复用:对前面若干帧的历史蓄水池分别拿来复用,默认为 8 帧,也就是说需要存储 8 份历史蓄水池。
此外,为了避免每个 light slot 蓄水池的 \(M\) 增长到无穷大,再输入完样本后(包括复用的样本),需要将 \(M\) 重置为 1,当然对应的 \(\mathrm{w}_{sum}\) 也应该除掉 \(M\) 。
// Merge new reservoir with reservoirs from previous frames.for (int i = 0; i < GRIDS_HISTORY_LENGTH ; i++) {lightSlotReservoir = mergeReservoirs(lightSlotReservoir, gLightGridHistory[i][lightSlotIndex]);// Divide wSum by M after each combining "round ."lightSlotReservoir.totalWeight /= lightSlotReservoir .M;lightSlotReservoir.M = 1;}
这里我比较困惑为什么不直接复用上一帧,逐帧累积,而是复用了 8 帧的信息。可能是因为蓄水池每次重置 \(M=1\) 导致历史帧样本只有一个而不能累积,复用效果较差,因此不得不存储 8 帧的历史蓄水池。但个人觉得这块是有很大改进空间的。
有了上述介绍,我们先看看原本蓄水池的组成:
- 输出样本 \(y\)
- 总权重 \(\mathrm{w}_{sum}\)
- 总样本数 \(M\)
- 输出样本的权重 \(W=\frac{1}{\hat{p}(y)}(\frac{\mathrm{w}_{sum}}{M})\) ,实际上该权重的倒数便是输出样本 \(y\) 的概率。
而现在 light slot 蓄水池可以简化成如下形式来存储:
- 输出样本 \(y\)
- 平均权重 \(\mathrm{w_avg}\)
- (无需存储,隐含信息)\(M=1\)
- (无需存储,可低成本地立即计算 \(\hat{p(y)}\) 出来)输出样本的权重 \(W=\frac{1}{\hat{p}(y)}(\mathrm{w_avg})\) ,实际上该权重的倒数便是输出样本 \(y\) 的概率。
动态光源问题
动态光源权重发生明显变化时,然后假如历史蓄水池的输出样本刚好是那个动态光源,那么它的权重也不会发生变化(因为没有去修改历史蓄水池权重的操作),就会导致 noise。
为此解决方式有两种:
- 防止输出样本为动态光源的蓄水池参与时间重用(更推荐这个做法)。
- 为历史蓄水池重新评估动态光源的权重(更费时)。
基于屏幕空间的多光源 RIS
pixel 蓄水池
这个与 ReSTIR DI 类似,每个 pixel 蓄水池都可以独立地进行 stream RIS 流程,其两个 pdf 分别为:
- source pdf \(p\) :light slot 蓄水池输出样本的权重的倒数 \(\frac{1}{r.\mathrm{w}}\) 。
- target pdf \(\hat{p}\) :可以选择完整的 BRDF,实际上就是渲染方程刨去了 visibility 的部分。
如果评估完整 BRDF 比较费时,可以只使用部分的 BRDF 成分来评估,从而简化计算。
float sourcePdf = candidate.sampleTargetPdf / reservoirAverageWeight;float targetPdf = PartialBrdf(candidate , shadedPoint);
light slot 蓄水池接入 pixel 蓄水池
如何把 light slot 蓄水池接入 pixel 蓄水池呢?很简单,pixel 直接根据世界空间坐标位置并做一定的 jittering 然后定位到对应的 cell,遍历该 cell 的 light slots 即可(512 个 light slot 蓄水池意味着需要输入 512 个候选样本)。
jittering 是为了避免 pixel 刚好在 cell 边界而产生的 artifact,因此才给它一个 cell 范围的 jittering:
// Jitter hit point position within the size of grid cell.float3 gridLoadPosition = pointPosition +( float3(rand (), rand (), rand ()) * 2.0f - 1.0f) * gHalfGridCellSize;
时空复用
和 ReSTIR 差不多,复用空间上的 pixel 蓄水池和时序上的 pixel 蓄水池,不多阐述。
优化
grid 结构
传统的 grid 结构可能会占据过多存储空间或性能开销,可以选择以下方式改进:
- Scrolling Clipmap:利用滚动优化可以避免更新所有 cells 的蓄水池,性能较好,但对于远处的坐标可能就没有 cell 从而无法做多光源。
- Sparse Grid:大世界坐标友好,但需要解决哈希冲突,性能略低。
跳过无关 cell 的填充
对于没有几何体的空间部分,我们可以跳过对应 cell 的填充,减少大量 cells 的更新。实现这个 idea,我们需要对每个 cell 存储一个 counter(只需要几位的整数),然后每一帧:
- 要是 cell 被访问了,可以将 cell 的 counter 重置为最大值。
- 要是 cell 没有被访问,就给该 cell 的 counter 减一,最多减到 0。
这样我们就可以对那些 counter 为 0 的 cells 跳过更新 light slots 的步骤。
可伸缩更新
从上文的思路出发可以更进一步调整更新 cell 的 light slots 频率(可以改变对 light slots 输入的样本数量或者 light slots 蓄水池的数量),例如:
- counter 越少,更新频率越低。
- 距离越远,更新频率越低(LOD)。
- ...
扩展到其它渲染方案
只要把次级光源也当成光源,该方法也可以很容易推广到其它 GI 方法,例如 VPL 类方法等。
参考
- 多光绘制(Many-Lights Rendering):VPL(Instant Radiosity)、Lightcuts、Light Transport Matrix、MRCS、LightSlice | 知乎 zhiwei
- Importance Sampling of Many Lights with Adaptive Tree Splitting [Conty, Kulla 2018]
- Importance Sampling of Many Lights on the GPU | Ray Trcing Gems [2019]
- Dynamic Many-Light Sampling for Real-Time Ray Tracing [Moreau 2019]
- Lightcuts: A Scalable Approach to Illumination [Walter 2005]
- Z-order curve - Wikipedia
- Real-Time Stochastic Lightcuts Proceedings of the ACM on computer graphics and interactive techniques. [Yuksel 2020]
- DirectX11 With Windows SDK--27 计算着色器:双调排序 - X_Jun - 博客园
- Spatiotemporal reservoir resampling for real-time ray tracing with dynamic direct lighting [BENEDIKT 2020]
- Rendering Many Lights with Grid-based Reservoirs [2021]
关键词:
-
世界微动态丨在java中String类为什么要设计成final?Java面试常见问题
2023Java面试题最经典的问题之一了,非常经典的Java基础知识,一定要学会!在Java中,String类被设计成f...
来源: 面向状态机编程:复杂业务逻辑应对之道
多光源渲染方案 - Many Lights Sampling
世界微动态丨在java中String类为什么要设计成final?Java面试常见问题
报道:LoadRunner——脚本优化(二)
马斯克要自建“乌托邦小镇”:员工全部搬进去 自己当“镇长”
拒绝投影行业亮度虚标!Vidda官宣三色激光全家桶新品
环球最资讯丨新一轮国内油价将于17日迎来调整:有再度搁浅可能
【环球聚看点】彻底解决“刹车争议”!电商平台上线特斯拉脚部专用记录仪:全程摄像
当前播报:简单到复杂:C#拷贝文件的3种方法
环球热门:对LSTM应用于图像的初步理解
【数论与组合数学 1】数论简介、素数、算数基本定理
JS回调地狱
天天视讯!GTX 1050 Ti就能跑!顽皮狗公布《最后生还者:Part 1》PC版配置要求
世界看点:自称12年驾龄 特斯拉Model X车主在线维权:踩刹车没反应加速撞柱子
天天观察:苹果古典音乐软件已上架:Apple Music会员免费用!中国市场随后推出
当前资讯!明基推出首款48寸OLED电竞显示器:4K 120Hz、90W反向供电
《生化危机4:重制版》PS5版疑似已偷跑 小心剧透啊
世界百事通!illustrator学习心得体会(illustrator序列号)
工厂模式进阶用法,如何动态选择对象?
迷你天猫商城代码审计
焦点简讯:K8S 性能优化 - K8S APIServer 调优
【全球聚看点】Prompt-Engineering-Guide 学习摘要1
前端设计模式——装饰者模式
65寸4K大屏电视不到2000元 LCD白菜价即将结束:3月价格上涨10%
环球微头条丨最强AI再次进化 ChatGPT下周升级GPT-4:支持视频了
【环球聚看点】免费玩!《生化危机4:重制版》体验版上线:不限时、不限次
当前滚动:德国电动空中出租车Lilium jet完成测试:时速250km/h 全机36个电风扇
杀疯了!长安深夜放大招 购车百亿补贴:深蓝SL03直降2.2万
世界快看点丨分享几个常用的运维 shell 脚本
世界观点:佳兆业成今年首家复牌出险房企
全球球精选!一座河南小县城的全球钻石生意爆火:价格不到天然的1/3
我国再次成功发射一箭双星:天绘六号A/B星顺利进入预定轨道
当前快看:资助8年的女生毕业放弃工作 嫁给有钱人成家庭主妇 资助人:失眠好几天
天天通讯!上班族如何备考公务员_如何备考公务员
全球焦点!读Java性能权威指南(第2版)笔记12_堆内存中
怎么处理消息重发的问题?
每日热点:HEU KMS Activator 30.0.0全能系统数字许可激活工具(全新体验纪念版)
环球热议:用盆吃10袋泡面男子火了 回应月薪2万邀约:浇完家里18亩地再说
实时:第127篇:异步函数(async和await)练习题(异步,消息队列)
焦点!【LeetCode回溯算法#05】分割回文串(复习双指针判断回文以及substr函数使用记录)
今日热议:【django-vue】celery延迟任务、定时任务 django中使用celery 秒杀功能 双写一致性 首页轮播图定时更新 课程前端页面
世界热头条丨关于JAVA泛型数组类型擦除引发的问题及解决方案
环球今日讯!Mint安装MySQL
快讯:苹果iPhone 14黄色款预售:全新配色不加价 5999元起
天天微速讯:租客辞职要搬走被房东介绍工作 当事人感动
即时焦点:一辆腾势敢占两个充电桩:真不怕挨揍?
“常温超导”把A股都晃晕了!真要改变我们的生活?
《霍格沃茨之遗》渗人面部Bug:玩家看了起鸡皮疙瘩
全球短讯!美环保署署长:将在今年最终确定甲烷排放规则
21世纪20年代是几几年(21世纪20年代是几几年)
爆肝两万字,详解fastdfs分布式文件系统
初识rollup 打包、配置vue脚手架
世界热议:62.类模板
当前热文:C语言——可变参函数
陕西招聘会现3万月薪岗位学生排长龙 招聘人员:半天收简历150份
当前动态:供不应求!真我GT Neo5 1TB版真香:二手用户也抢着要
“山药成了精”?男子买到奇葩山药外形酷似人脚掌
每日视点!快速读懂Redis分布式锁的实现和原理
美少女三消游戏 《Mirror 2: Project X》开发组宣布破产解散
酒店回应到211大学招服务员:符合流程 面向所有高校毕业生
快看点丨京东CEO徐雷:百亿补贴效果超过预期、要做天天低价
【新要闻】比亚迪加入降价大军!宋Pro DM-i限时优惠:88元折扣6888元
焦点简讯:耳机煲机一般要煲多久_耳机煲机方法是什么?买回来新耳机要怎样煲?耳机要煲多久?
世界热点评!前端如何相对优雅管理api
全球速看:浙四医院官网招聘2021_浙四医院官网
环球观点:京东2022年收入超1万亿:“百亿补贴”会一直有!
简约时尚 健身备一件:361°新款轻薄速干衣39元冲量
越来越卖不动了!最畅销十款数码相机一览:索尼成赢家 第一性价比绝
全球通讯!Intel的大小核CPU架构:最终还是把一些老游戏坑了
往返近1000元!景区回应坐滑竿上山按斤收费:网友力挺明码标价
天天实时:【翻译】发布 .NET 8 Preview 1
前沿资讯!海洋风筝爆火 一周暴涨498%超过秋裤!网友:春天的信号
天天消息!甜香丝滑 旺旺邦德低脂轻乳咖啡官方狂促:合2元一瓶
《银河护卫队3》导演回击网友言论:确定选角不因其是黑人
世界热议:东风系引发车市价格大战!纯电宝马i3终端大促销:最大降幅超10万
每日热点:日本原药温和驱蚊配方:超威电热蚊香液3瓶1器14.9元发车
快讯:uni-popup 遮不住头部标题的解决办法
环球焦点!网友晒空荡新房 各大品牌疯狂随份子 开局一套房其他全靠送
快播:女子在地铁上脱鞋抠脚死皮掉一地 杭州地铁回应:列车到站会打扫
世界速递!为拯救者Y9000P 2023量身打造:联想推出新140W氮化镓适配器
每日看点!富士康否认清退临时工拆除流水线:运转正常
全球即时:美国一特斯拉撞上消防车造成一死一伤 现场惨烈!调查结果让人心痛
Envisics获得5000万美元C轮融资
当前滚动:(数据库系统概论|王珊)第十一章并发控制-第二、三、四节:封锁、封锁协议活锁和死锁
每日焦点!「中华田园敏捷开发」,是老板无能还是程序员无力?
【世界聚看点】探究SMC局部代码加密技术以及在CTF中的运用
记录--Vue自定义指令实现加载中效果v-load(不使用Vue.extend)
【焦点热闻】十分钟读懂火山引擎 DataLeap 数据治理实践
老头环壶头哥:击败女武神超4千次 期待DLC到来
天天资讯:儿子沉迷手机爸爸帮请假“逼”他连玩17小时:效果很好
焦点消息!供应iPhone 15的OLED屏幕漏光?国产面板一哥京东方回应:不予评价
当前关注:纵享丝滑 回味愉悦:德芙巧克力37.5元/斤(官价5折)
每日速看!成龙进组20天把半年的封闭用完了!新电影《龙马精神》4月上映:有吴京参演
每日视点!通过案例讲解python循环语句
【全球独家】基于应用理解的协议栈优化
关注:串口登录提示"Login incorrect"
热推荐:节能降耗 | AIRIOT智慧电力综合管理解决方案
实时:C++笔记--函数、预处理
【天天播资讯】为啥人一上车就爱睡觉?原来是被“催眠”了
全球观察:95后大厂女生裸辞开麻将馆当保洁:很享受自由和成就感