计算机图形学:【Games101】学习笔记07------光线追踪(基本原理、加速结构)
- 前言
- 一、光线追踪(辐射度量学、渲染方程与全局光照)
-
- [1.1 辐射度量学概念复习 (Reviewing Radiometry Concepts)](#1.1 辐射度量学概念复习 (Reviewing Radiometry Concepts))
- [1.2 辐照度 (Irradiance)](#1.2 辐照度 (Irradiance))
-
- [1.2.1 兰伯特余弦定律 (Lambert's Cosine Law)](#1.2.1 兰伯特余弦定律 (Lambert's Cosine Law))
- [1.2.2 辐照度随距离的衰减 (Irradiance Falloff)](#1.2.2 辐照度随距离的衰减 (Irradiance Falloff))
- [1.3 辐射度 (Radiance)](#1.3 辐射度 (Radiance))
-
- [1.3.1 辐射度与其他量的关系](#1.3.1 辐射度与其他量的关系)
- [1.3.2 入射与出射辐射度(Incident Radiance & Exiting Radiance)](#1.3.2 入射与出射辐射度(Incident Radiance & Exiting Radiance))
- [1.3.3 辐照度与辐射度对比(Irradiance vs. Radiance)](#1.3.3 辐照度与辐射度对比(Irradiance vs. Radiance))
- [1.4 双向反射分布函数(BRDF)](#1.4 双向反射分布函数(BRDF))
-
- [1.4.1 点上的反射现象(Reflection at a Point)](#1.4.1 点上的反射现象(Reflection at a Point))
- [1.4.2 双向反射分布函数(BRDF)](#1.4.2 双向反射分布函数(BRDF))
- [1.5 光线传输:反射方程与渲染方程](#1.5 光线传输:反射方程与渲染方程)
-
- [1.5.1 反射方程(The Reflection Equation)](#1.5.1 反射方程(The Reflection Equation))
- [1.5.2 渲染方程(The Rendering Equation)](#1.5.2 渲染方程(The Rendering Equation))
- [1.5.3 理解渲染方程(Understanding the rendering equation)](#1.5.3 理解渲染方程(Understanding the rendering equation))
- 二、光线追踪(蒙特卡洛积分与路径追踪)
-
- [2.1 蒙特卡洛积分 (Monte Carlo Integration)](#2.1 蒙特卡洛积分 (Monte Carlo Integration))
-
- [2.1.1 为什么需要蒙特卡洛积分?](#2.1.1 为什么需要蒙特卡洛积分?)
- [2.1.2 什么是蒙特卡洛积分?](#2.1.2 什么是蒙特卡洛积分?)
- [2.1.3 均匀采样示例 (Uniform Monte Carlo Estimator)](#2.1.3 均匀采样示例 (Uniform Monte Carlo Estimator))
- [2.2 路径追踪 (Path Tracing)](#2.2 路径追踪 (Path Tracing))
-
- [2.2.1 动机:Whitted-Style 光线追踪的局限性(Motivation: Whitted-Style Ray Tracing)](#2.2.1 动机:Whitted-Style 光线追踪的局限性(Motivation: Whitted-Style Ray Tracing))
- [2.2.2 简单的蒙特卡洛解决方案 (A Simple Monte Carlo Solution)](#2.2.2 简单的蒙特卡洛解决方案 (A Simple Monte Carlo Solution))
- [2.2.3 引入全局光照 (Global Illumination)](#2.2.3 引入全局光照 (Global Illumination))
- [2.2.4 路径追踪的两大难题与解决方案](#2.2.4 路径追踪的两大难题与解决方案)
- [2.2.5 提升效率:直接对光源采样 (Sampling the Light)](#2.2.5 提升效率:直接对光源采样 (Sampling the Light))
- [2.2.6 最终的路径追踪算法结构](#2.2.6 最终的路径追踪算法结构)
- [2.3 补充与总结 (Side Notes)](#2.3 补充与总结 (Side Notes))
前言
- 🎮 GAMES101 是国内相当有名的图形学公开课。项目相关资源在:https://sites.cs.ucsb.edu/~lingqi/teaching/games101.html。
- 本 📒笔记为 🖊️笔者在自学过程中整理的 🇨🇳中文版笔记,供各位 📖读者阅读 😼~
一、光线追踪(辐射度量学、渲染方程与全局光照)
1.1 辐射度量学概念复习 (Reviewing Radiometry Concepts)
辐射能量 (Radiant energy) Q Q Q:电磁辐射的总能量,单位是焦耳 J = J o u l e J = Joule J=Joule。在计算机图形学中极少直接使用。
辐射通量/功率 (Radiant flux / power) Φ \Phi Φ:单位时间内的能量。 Φ ≡ d Q d t \Phi \equiv \frac{dQ}{dt} Φ≡dtdQ,单位是瓦特 W = W a t t W = Watt W=Watt 或流明 l m = l u m e n lm = lumen lm=lumen。
辐射强度 (Radiant intensity) I ( ω ) I(\omega) I(ω):每单位立体角的功率。 I ( ω ) ≡ d Φ d ω I(\omega) \equiv \frac{d\Phi}{d\omega} I(ω)≡dωdΦ。
立体角 (Solid Angle) Ω \Omega Ω:球面上截取的面积与半径平方的比值。 Ω = A r 2 \Omega = \frac{A}{r^2} Ω=r2A
微分立体角 (Differential Solid Angles) :在极坐标下推导,面积微元 d A = ( r d θ ) ( r sin θ d ϕ ) = r 2 sin θ d θ d ϕ dA = (r d\theta)(r \sin\theta d\phi) = r^2 \sin\theta d\theta d\phi dA=(rdθ)(rsinθdϕ)=r2sinθdθdϕ。因此微分立体角 d ω = d A r 2 = sin θ d θ d ϕ d\omega = \frac{dA}{r^2} = \sin\theta d\theta d\phi dω=r2dA=sinθdθdϕ。

1.2 辐照度 (Irradiance)
定义:入射到一个表面点上的每单位面积的功率 (power per unit area)。
E ( x ) ≡ d Φ ( x ) d A E(x) \equiv \frac{d\Phi(x)}{dA} E(x)≡dAdΦ(x)
单位: W / m 2 W / m\^2 W/m2 或 l m / m 2 = l u x lm / m\^2 = lux lm/m2=lux。

1.2.1 兰伯特余弦定律 (Lambert's Cosine Law)
表面接收到的辐照度与"光线方向和表面法线之间夹角的余弦值"成正比。
E = Φ A cos θ E = \frac{\Phi}{A} \cos\theta E=AΦcosθ

注意:总是使用单位面积,余弦项作用于夹角 θ \theta θ。
物理意义解释 :如果是垂直照射,表面接收全部功率;如果表面旋转了 60 ∘ 60^{\circ} 60∘,接收到的功率减半。这也是地球上出现四季变化的原因(地球自转轴倾斜了约 23.5 ∘ 23.5^{\circ} 23.5∘,导致不同季节北半球接收太阳光的夹角发生变化,从而影响辐照度)。

1.2.2 辐照度随距离的衰减 (Irradiance Falloff)
假设一个点光源向周围均匀地发射功率 Φ \Phi Φ,在半径为 r r r 的球面上,总表面积为 4 π r 2 4\pi r^2 4πr2。
该球面上的辐照度为 E ′ = Φ 4 π r 2 = E r 2 E' = \frac{\Phi}{4\pi r^2} = \frac{E}{r^2} E′=4πr2Φ=r2E。这说明辐照度随着距离的平方呈反比衰减。

1.3 辐射度 (Radiance)
Radiance 是描述环境中光线分布的最基础的场量。它是与一条光线 (Ray) 相关联的物理量,而渲染的核心就是计算 Radiance。

定义:每单位立体角、每投影单位面积表面发射、反射、透射或接收的功率。
L ( p , ω ) ≡ d 2 Φ ( p , ω ) d ω d A cos θ L(p, \omega) \equiv \frac{d^2\Phi(p, \omega)}{d\omega dA \cos\theta} L(p,ω)≡dωdAcosθd2Φ(p,ω)
单位: W s r ⋅ m 2 \\frac{W}{sr \\cdot m\^2} sr⋅m2W 或 c d m 2 = l m s r ⋅ m 2 = n i t \\frac{cd}{m\^2} = \\frac{lm}{sr \\cdot m\^2} = nit m2cd=sr⋅m2lm=nit。其中 cos θ \cos\theta cosθ 用于计算投影面积。

1.3.1 辐射度与其他量的关系
Irradiance 是每投影单位面积的功率。Intensity 是每立体角的功率。
因此,Radiance 可以理解为每立体角的 Irradiance,或者 每投影单位面积的 Intensity。
1.3.2 入射与出射辐射度(Incident Radiance & Exiting Radiance)
1️⃣ 入射辐射度 (Incident Radiance) :到达表面的每单位立体角的 Irradiance。公式表示为 L ( p , ω ) = d E ( p ) d ω cos θ L(p, \omega) = \frac{dE(p)}{d\omega \cos\theta} L(p,ω)=dωcosθdE(p)。它描述的是沿着某条特定光线(特定方向 ω \omega ω)到达表面点 p p p 的光。

2️⃣ 出射辐射度 (Exiting Radiance) :离开表面的每单位投影面积的 Intensity。公式表示为 L ( p , ω ) = d I ( p , ω ) d A cos θ L(p, \omega) = \frac{dI(p, \omega)}{dA \cos\theta} L(p,ω)=dAcosθdI(p,ω)。例如,对于一个面光源,它描述了沿着某条特定光线离开表面的光。

1.3.3 辐照度与辐射度对比(Irradiance vs. Radiance)
Irradiance 是区域 d A dA dA 接收到的总功率。
Radiance 是区域 d A dA dA 从单一方向 d ω d\omega dω 接收到的功率。
关系 :计算某一点的 Irradiance,相当于把来自半球 H 2 H^2 H2 内所有方向的 Radiance 积分起来。公式为:
E ( p ) = ∫ H 2 L i ( p , ω ) cos θ d ω E(p) = \int_{H^2} L_i(p, \omega) \cos\theta d\omega E(p)=∫H2Li(p,ω)cosθdω

1.4 双向反射分布函数(BRDF)
1.4.1 点上的反射现象(Reflection at a Point)
光线在一个点发生反射可以分解为两步:
1️⃣ 从入射方向 ω i \omega_i ωi 射来的 Radiance,变成了表面微元 d A dA dA 接收到的 Irradiance 功率 E E E:
d E ( ω i ) = L ( ω i ) cos θ i d ω i dE(\omega_i) = L(\omega_i) \cos\theta_i d\omega_i dE(ωi)=L(ωi)cosθidωi
2️⃣ 接收到的能量 E E E 随后转化为向各个出射方向 ω r \omega_r ωr 辐射的 Radiance d L r ( ω r ) dL_r(\omega_r) dLr(ωr)。

1.4.2 双向反射分布函数(BRDF)
Bidirectional Reflectance Distribution Function (BRDF) 描述了:从每一个特定的入射方向 ω i \omega_i ωi,有多少比例的光被反射到了特定的出射方向 ω r \omega_r ωr(单位是 1 s r \\frac{1}{sr} sr1)。
f r ( ω i → ω r ) = d L r ( ω r ) d E i ( ω i ) = d L r ( ω r ) L i ( ω i ) cos θ i d ω i f_r(\omega_i \rightarrow \omega_r) = \frac{dL_r(\omega_r)}{dE_i(\omega_i)} = \frac{dL_r(\omega_r)}{L_i(\omega_i) \cos\theta_i d\omega_i} fr(ωi→ωr)=dEi(ωi)dLr(ωr)=Li(ωi)cosθidωidLr(ωr)

1.5 光线传输:反射方程与渲染方程
1.5.1 反射方程(The Reflection Equation)
通过在整个半球上对所有入射光线的贡献进行积分,就能得到某个固定观察方向 ω r \omega_r ωr 上的总反射 Radiance。
L r ( p , ω r ) = ∫ H 2 f r ( p , ω i → ω r ) L i ( p , ω i ) cos θ i d ω i L_r(p, \omega_r) = \int_{H^2} f_r(p, \omega_i \rightarrow \omega_r) L_i(p, \omega_i) \cos\theta_i d\omega_i Lr(p,ωr)=∫H2fr(p,ωi→ωr)Li(p,ωi)cosθidωi

挑战(递归性) :反射方程中,反射出去的 Radiance L r L_r Lr 依赖于入射的 Radiance L i L_i Li;但这个入射的 Radiance L i L_i Li,实质上又是场景中其他某个表面反射出来的 Radiance。

1.5.2 渲染方程(The Rendering Equation)
由 Kajiya 在 1986 年提出。在反射方程的基础上,加入了一个自发光项 (Emission term) L e L_e Le,使其成为一个完全通用的方程。
渲染方程公式:
L o ( p , ω o ) = L e ( p , ω o ) + ∫ Ω + L i ( p , ω i ) f r ( p , ω i , ω o ) ( n ⋅ ω i ) d ω i 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 Lo(p,ωo)=Le(p,ωo)+∫Ω+Li(p,ωi)fr(p,ωi,ωo)(n⋅ωi)dωi
注意:在这里,我们规定所有的方向矢量(无论是入射 ω i \omega_i ωi 还是出射 ω o \omega_o ωo)都是从表面向外指的。 ( n ⋅ ω i ) (n \cdot \omega_i) (n⋅ωi) 也就是 cos θ i \cos\theta_i cosθi。
1.5.3 理解渲染方程(Understanding the rendering equation)
渲染方程是一个第二类 Fredholm 积分方程,其规范形式可以写为:
l ( u ) = e ( u ) + ∫ l ( v ) K ( u , v ) d v l(u) = e(u) + \int l(v) K(u, v) dv l(u)=e(u)+∫l(v)K(u,v)dv
可以将其抽象为线性算子方程:
L = E + K L L = E + K L L=E+KL
- L L L 是光照(Radiance)。
- E E E 是光源发出的光。
- K K K 是光线传输算子 (Light Transport Operator),包含了 BRDF 和余弦项的积分。


- E E E:光源直接发出的光 (Emission)。
- K E KE KE:一次弹射,即光源打在物体上被我们看见。这就是直接光照 (Direct Illumination),也是传统光栅化着色主要计算的部分。
- K 2 E K^2E K2E:两次弹射(一跳间接光照,如镜面反射、折射)。
- K 3 E K^3E K3E及以后:多次弹射的间接光照。
- 全局光照 = 直接光照 + 所有的间接光照。
课程中展示了同一场景在不同弹射次数(Direct, 1-bounce, 2-bounce, 4-bounce, 8-bounce, 16-bounce)下的渲染效果,展现了间接光照带来的色彩溢出 (Color Bleeding) 和更加真实的明暗过渡。





二、光线追踪(蒙特卡洛积分与路径追踪)
2.1 蒙特卡洛积分 (Monte Carlo Integration)
2.1.1 为什么需要蒙特卡洛积分?
渲染方程包含在半球上的积分,但通常这些积分太难,无法求出解析解。

2.1.2 什么是蒙特卡洛积分?
核心思想:通过对函数值进行随机采样,并求其平均值,来估算函数的定积分。
数学公式 :对于定积分 ∫ a b f ( x ) d x \int_a^b f(x) dx ∫abf(x)dx,给定随机变量 X i ∼ p ( x ) X_i \sim p(x) Xi∼p(x),其蒙特卡洛估计量为:
F N = 1 N ∑ i = 1 N f ( X i ) p ( X i ) F_N = \frac{1}{N} \sum_{i=1}^{N} \frac{f(X_i)}{p(X_i)} FN=N1i=1∑Np(Xi)f(Xi)
2.1.3 均匀采样示例 (Uniform Monte Carlo Estimator)
如果我们在区间 a , b a, b a,b 上进行均匀采样,概率密度函数为常数 C C C。因为 ∫ a b C d x = 1 \int_a^b C dx = 1 ∫abCdx=1,所以 p ( x ) = 1 b − a p(x) = \frac{1}{b-a} p(x)=b−a1。
将其代入通用公式,均匀蒙特卡洛估计量变为:
F N = b − a N ∑ i = 1 N f ( X i ) F_N = \frac{b-a}{N} \sum_{i=1}^{N} f(X_i) FN=Nb−ai=1∑Nf(Xi)

- 样本数量 N N N 越多,方差越小(结果越准确)。
- 必须在要积分的同一个域上进行采样(例如对 x x x 采样,就对 x x x 积分)。
2.2 路径追踪 (Path Tracing)
2.2.1 动机:Whitted-Style 光线追踪的局限性(Motivation: Whitted-Style Ray Tracing)
Whitted-Style 光线追踪有两个重大简化:只计算镜面反射/折射,并且光线碰到漫反射表面就停止弹射。
问题1:无法正确处理 Glossy(光泽)材质。光泽材质的反射方向并不是唯一的镜面反射方向。

问题2:忽略了漫反射材质之间的光线反弹(Color Bleeding 现象)。例如 Cornell Box 中,红墙会把红光反射到白箱子上,这就是全局光照,而 Whitted-Style 无法渲染出来。

结论:Whitted-Style 是错误的,渲染方程才是正确的。但求解渲染方程需要计算半球积分以及处理递归。
2.2.2 简单的蒙特卡洛解决方案 (A Simple Monte Carlo Solution)
直接应用蒙特卡洛积分来解渲染方程。我们假设在半球上均匀采样,即 p ( ω i ) = 1 2 π p(\omega_i) = \frac{1}{2\pi} p(ωi)=2π1。

估算公式:
L o ( p , ω o ) ≈ 1 N ∑ i = 1 N L i ( p , ω i ) f r ( p , ω i , ω o ) ( n ⋅ ω i ) p ( ω i ) L_o(p, \omega_o) \approx \frac{1}{N} \sum_{i=1}^{N} \frac{L_i(p,\omega_i) f_r(p,\omega_i,\omega_o) (n \cdot \omega_i)}{p(\omega_i)} Lo(p,ωo)≈N1i=1∑Np(ωi)Li(p,ωi)fr(p,ωi,ωo)(n⋅ωi)
算法逻辑 (shade(p, wo)):随机选 N N N 个方向发射光线;如果光线击中光源,则将其贡献累加并平均。这就得到了一个正确的直接光照着色算法。

2.2.3 引入全局光照 (Global Illumination)
当光线从 P P P 点射出,击中另一个物体 Q Q Q 时, Q Q Q 也会把光反射到 P P P 点。这部分光的强度等于 Q Q Q 点接收到的直接光照。
因此,在算法中加入递归:如果光线击中物体 Q Q Q,则调用 shade(q, -wi) 作为入射光 L i L_i Li 继续计算。

2.2.4 路径追踪的两大难题与解决方案
难题一:光线数量爆炸 (Explosion of #rays)

假设每次反射发射 100 条光线,那么反弹两次就是 10 , 000 10,000 10,000 条,反弹三次就是 1 , 000 , 000 1,000,000 1,000,000 条,计算量呈指数级爆炸。
解决方案 :只要令每次反弹的采样数 N = 1 N = 1 N=1,光线数量就不会爆炸!这就是路径追踪 (Path Tracing) 的精髓。(注:如果 N ≠ 1 N \neq 1 N=1,则被称为分布式光线追踪)。

光线生成 (Ray Generation):只用 1 根光线计算会产生极大的噪点。为了消除噪点,我们可以在每个像素 (pixel) 范围内均匀选取多个采样点,对每个采样点发射一条路径追踪光线,最后求像素辐射度的平均值。


难题二:递归永远不会停止 (Infinite Recursion)
光线在真实世界中会不断弹射。如果在代码中强行限制弹射次数,就会损失能量(图像变暗)。


解决方案:俄罗斯轮盘赌 (Russian Roulette, RR)。
- 手动设定一个生存概率 P P P ( 0 < P < 1 0 < P < 1 0<P<1)。
- 以概率 P P P 发射光线,并将返回的着色结果除以 P P P(即 L o / P L_o / P Lo/P)。
- 以概率 1 − P 1-P 1−P 终止光线,结果记为 0 0 0。
数学证明 :其期望值 E = P × ( L o / P ) + ( 1 − P ) × 0 = L o E = P \times (L_o / P) + (1-P) \times 0 = L_o E=P×(Lo/P)+(1−P)×0=Lo,保证了结果在统计上的正确性。

2.2.5 提升效率:直接对光源采样 (Sampling the Light)
低效率的原因:如果光源很小,在着色点上半球均匀采样时,绝大部分光线都打不到光源被"浪费"了,导致结果充满噪点。

解决方案 :既然蒙特卡洛积分允许任何采样方式,我们可以直接在光源表面积上进行采样(这样没有光线会被浪费)。光源面积为 A A A,则均匀采样的 PDF 为 1 / A 1/A 1/A。

变量替换 :渲染方程原本是对立体角 d ω d\omega dω 积分,我们需要将其转换为对光源面积 d A dA dA 的积分。根据立体角的定义:
d ω = d A cos θ ′ ∣ ∣ x ′ − x ∣ ∣ 2 d\omega = \frac{dA \cos\theta'}{||x' - x||^2} dω=∣∣x′−x∣∣2dAcosθ′
其中 θ ′ \theta' θ′ 是光源法线与光线方向的夹角, ∣ ∣ x ′ − x ∣ ∣ 2 ||x' - x||^2 ∣∣x′−x∣∣2 是两点距离的平方。
将其代入渲染方程,即可将针对立体角的积分改写为针对光源面积的积分。

2.2.6 最终的路径追踪算法结构
为了兼顾效率与物理正确性,最终的算法将着色分为两部分求和:
-
直接光照 (来自光源):在光源表面均匀采样。不需要俄罗斯轮盘赌。只需从着色点向光源采样点发射一条射线,如果中间没有被遮挡(Not blocked),则计算其贡献。
-
间接光照 (来自其他反射物):使用俄罗斯轮盘赌决定是否继续。如果在半球上按概率采样发出的射线击中了非发光物体,则递归调用着色函数。
二者相加即为最终结果。


2.3 补充与总结 (Side Notes)
学习门槛:路径追踪由于融合了物理、概率论、微积分和代码实现,难度较高。
渲染质量:路径追踪生成的图像极其逼真,几乎是 100% 物理正确的(达到了照片级写实 Photo-realistic)。
概念区分:
-
以前说的"光线追踪"通常指 Whitted-style 光线追踪。
-
现代图形学中的"光线追踪"指的是光线传输的通用求解方案集合,包含了:单向/双向路径追踪 (PT/BDPT)、光子映射 (Photon Mapping)、Metropolis 光线传输 (MLT)、VCM 等等。
课程未涵盖的主题(图形学进阶领域):
-
如何非均匀采样(重要性采样 Importance Sampling)?
-
伪随机数的作用(低差异序列 Low discrepancy sequences)。
-
如何结合半球采样与光源采样(多重重要性采样 MIS)?
-
像素重建滤波 (Pixel reconstruction filter) 与 伽马校正 (Gamma correction) / 色彩空间等知识。