结合 SPPM 的 Path Tracing

随机渐进式光子映射(Stochastic Progressive Photon Mapping, SPPM)是光子映射系列算法的进阶算法,本文介绍如何实现 SPPM 以及如何将 SPPM 与路径追踪(Path Tracing, PT)结合。 光子映射系列算法 光子映射 光子映射(Photon Mapping, PM)是光子映射系列算法中的初代算法,是一个两阶段算法,包括光子追踪和光子映射。其思想就是首先从光源发射光子,光子在场景中不断反弹,模拟现实世界的过程,然后再使用 Path Tracing,过程中在合适的地方使用光子来估计 radiance,加速渲染。 光子的发射 光子是光源的通量/功率的载体,光源实质上是通过发射光子来实现照明。PM 中的光子与物理中的光子不同,物理学中的光子是光能传递的最小单元,即量子化的性质,单个光子的能量是 $E = h\nu$,而 PM 中的光子实际上是一堆物理中的光子,是更符合应用的模型。所以,接下来所讨论的光子都是 PM 意义下的光子。 如何计算单个光子的通量呢?发射光子的过程实际上就类似于对光源的总通量进行 Monte Carlo 估计的过程,每个光子都是一个样本,每一份通量相加就得到了总通量。所以我们就对光源表面和出射方向进行采样,按照类似的过程计算每一个光子的通量。总通量按照以下积分计算 $$ \begin{aligned} \Phi & = \int_M \int_{\Omega^+} L_e(x, \omega) (n \cdot \omega) \mathrm d\omega \mathrm dA \\ & \approx \dfrac{1}{N} \sum_{i = 1}^N \dfrac{L_e(x, \omega) (n \cdot \omega)}{p(x)p(\omega)} \end{aligned} $$所以单个光子的通量就是 $\dfrac{1}{N} \dfrac{L_e(x, \omega) (n \cdot \omega)}{p(x)p(\omega)}$,$N$ 表示被发射光子的总数。严格意义上来说,通量的定义是不考虑立体角和照明面积的,所以所谓的单个光子的通量实际上是通量的二阶差分 $\Delta^2 \Phi$。在实际实现中,我们在计算通量时并不会除以 $N$,这是因为在 SPPM 中光子数量会随着迭代次数增加而增加,因此我们也将其 $\dfrac{L_e(x, \omega) (n \cdot \omega)}{p(x)p(\omega)}$ 视为一种没有放缩的通量,直到最后再除以 $N$ 得到真正的通量。 ...

August 10, 2025 · 9 min · oosquare

光线追踪中的 Multiple Importance Sampling

本文主要介绍多重重要性采样(Multiple Importance Sampling)及其在光线追踪中的典型应用。 Multiple Importance Sampling Monte Carlo Path Tracing 在 Ray Tracing 中,最核心的技术就是 Monte Carlo Estimation。通过使用 Monte Carlo Estimation,我们可以求解 Rendering Equation。对于 Monte Carlo Estimation 来说,一个合适的采样方法可以极大提升收敛的速度,具体来说,对于以下积分及其 Estimator $$ I = \int_D f(x) \mathrm dx \approx \dfrac{1}{N} \sum_{i = 1}^N \dfrac{f(X_i)}{p(X_i)} $$$X_i$ 的最佳的采样分布应该满足 $p(X_i) \propto f(X_i)$。 然而对于 Rendering Equation 来说,这个条件难以满足,因为其被积函数包含了 cosine-weighted BSDF 和 radiance 两部分因子,后者更是需要递归求解的未知项,显然没有办法进行完美的采样。 $$ L_o(x, \omega_o) = L_e(x, \omega_o) + \int_{\Omega^+} f_s(x, \omega_o, \omega_i) L_i(x, \omega_i) (n \cdot \omega_i) \mathrm d\omega_i $$一般情况下,我们只能选择让采样分布于其中一部分因子的形状近似,也就产生了两种采样——BSDF 采样(包括了余弦项)和光源采样(光源贡献的 radiance 应该比非直接的更大)。 ...

August 7, 2025 · 7 min · oosquare