渲染方程与重要性采样
需要预先学习:
1. 渲染方程
1.1 从局部到全局的数学表达
全局光照与局部光照 把光照分为局部与全局两个层次。渲染方程(rendering equation)把"全局"写成了数学形式:一个表面点向观察方向反射的总亮度,等于它自身发出的光,加上从法线半球所有方向射来的光经 BRDF 反射后的总和:
方程中各项:
| 符号 | 含义 |
|---|---|
| 点 朝观察方向 反射的辐射亮度(radiance) | |
| 自发光项,只有光源表面非零 | |
| BRDF(双向反射分布函数),描述入射方向 的光有多少被反射到 | |
| 从方向 射入的辐射亮度 | |
| Lambert 余弦项(见 着色与渲染管线),倾斜入射时单位面积实际接收的能量减少 | |
| 法线 所在的半球,积分覆盖所有可能的入射方向 |
方程说的是:出射光 = 自发光 + 半球上所有入射方向贡献的积分。看起来只是一条方程,但它把反射过程描述为"连续方向的累加",而不是 Blinn-Phong 那种"光源逐项求和"(见 Phong模型与Blinn-Phong模型)——这是它与经验模型最根本的区别。
1.2 方程的递归性:全局的数学根源
渲染方程的"全局"藏在 里:从 射来的光,可能直接来自光源,也可能来自另一个表面点的反射——而那个点的出射光,又由同一条方程描述。所以渲染方程是递归的:把一个点的出射亮度反复展开,得到的是"光在场景中不断反弹"的路径链:
- 直接光照:光源 → 该点;
- 一次反弹:光源 → 表面 A → 该点;
- 两次反弹:光源 → 表面 A → 表面 B → 该点……
这就是路径追踪里"一条路径"的由来(光线追踪 的路径追踪部分)。阴影、间接光照、颜色溢出这些全局效果(全局光照与局部光照)全部隐含在这条递归里:
注:方程中的 天然处理遮挡——如果 方向被别的物体挡住, 就取"挡住它的那个表面"的出射光。阴影不是方程的附加项,而是递归本身的结果。
1.3 为什么无法解析求解
渲染方程是第二类 Fredholm 积分方程,且 与 都是任意函数。解析解只存在于极端简化的场景(单一均匀光源、无限大平面、朗伯表面)。真实场景只能数值求解,主流方法是蒙特卡洛:把积分当成随机变量的期望来估计。
2. 蒙特卡洛积分
2.1 基本思想
对积分 ,蒙特卡洛(Monte Carlo)估计的做法是:按概率密度函数 随机采样 个点,用样本均值估计积分:
其中 是采样点的概率密度函数(PDF,probability density function),满足 。分母上的 修正了"样本在 处出现概率不同"造成的偏差。蒙特卡洛有两个关键性质:
- 无偏:样本数趋于无穷时,估计值收敛到真实积分;
- 收敛慢:误差按 衰减——样本数翻 100 倍,误差只降到原来的 。
收敛慢是路径追踪"噪点久久不消"的根本原因:每个像素要成百上千条路径,画面才能干净(全局光照与局部光照)。
2.2 方差与噪声
单次估计 可能偏离真值很远——某条路径恰好特别亮——多次平均后逐渐收敛。方差(variance)描述估计值的波动幅度,直接体现为画面噪点。
关键观察: 的方差取决于 与 的匹配程度。若 ,这个比值恒为常数,方差为零——但 通常无法解析归一化。实用策略是让 尽量贴近 的形状,这正是重要性采样。
3. 重要性采样
3.1 均匀采样为什么不行
对半球均匀采样()实现最简单,但方差巨大。被积函数 的形状通常极不均匀:高光 lobe 只覆盖一小块方向,点光源只占天空的一个点。均匀采样时绝大多数样本落在"几乎没贡献"的方向上,偶尔一个样本撞上高光或光源,单样本值极大,画面充满亮点噪点。
重要性采样(importance sampling)的思想:让采样分布 与被积函数的形状大致一致,样本密集落在贡献大的区域,用更少的样本获得更低的方差。
对应两种常见形状:
| 被积形状 | 采样分布 | 说明 |
|---|---|---|
| 漫反射 lobe | 余弦加权采样, | 贡献与 成正比,直接按余弦分布采样 |
| 高光 lobe(GGX) | GGX 重要性采样, 取法线分布 | 贡献集中在微表面法线朝向半程向量的区域,必须按其分布采样 |
3.2 生成样本:Hammersley 序列与逆变换
重要性采样需要一个标准流程:先生成均匀随机数(或低差异序列),再通过逆变换采样(inverse transform sampling)映射到目标分布。这里给出 GLSL 实现——它在 PBR 的 Cook-Torrance 高光项和 IBL 的预计算中都会用到:
const float PI = 3.14159265359;
// 位反转:生成第 i 个 Hammersley 样本(低差异序列,比纯随机更均匀)
float radicalInverse_VdC(uint bits)
{
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10;
}
vec2 hammersley(uint i, uint N)
{
return vec2(float(i) / float(N), radicalInverse_VdC(i));
}
/*
* GGX 重要性采样
*
* 参数:
* xi (xi.x, xi.y) 均匀分布的二维随机样本(可用 Hammersley)
* N 表面法线(世界空间,已归一化)
* roughness 粗糙度
*
* 返回:
* 切线空间映射到世界空间的采样方向(半程向量)
*/
vec3 importanceSampleGGX(vec2 xi, vec3 N, float roughness)
{
float a = roughness * roughness;
// 由 GGX 法线分布的累积分布反推极角(逆变换采样)
float phi = 2.0 * PI * xi.x;
float cosTheta = sqrt((1.0 - xi.y) / (1.0 + (a * a - 1.0) * xi.y));
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
vec3 H;
H.x = cos(phi) * sinTheta;
H.y = sin(phi) * sinTheta;
H.z = cosTheta;
// 从切线空间(z 轴为法线)转到世界空间
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
vec3 tangent = normalize(cross(up, N));
vec3 bitangent = cross(N, tangent);
return normalize(tangent * H.x + bitangent * H.y + N * H.z);
}
几个要点:
- Hammersley 序列是一种低差异序列(low-discrepancy sequence):样本在单位正方形内分布更均匀,避免纯随机采样的"扎堆"现象,收敛更快——这种用确定序列替代随机数的做法叫拟蒙特卡洛(quasi-Monte Carlo);
- 逆变换采样:对 GGX 的 分布求累积分布再反解,得到 。粗糙度越小, 越趋向 1,样本越集中在法线附近——正好对应光滑表面窄而亮的高光;
- 采样得到的是半程向量 ,用它再反射出入射方向 ,因为 GGX 的 lobe 定义在半程向量空间(见 PBR 的微表面模型)。
3.3 采样策略对比
| 策略 | 采样分布 | 方差 | 适用场景 |
|---|---|---|---|
| 均匀半球采样 | 极大(高光越窄方差越大) | 几乎不用,仅作教学演示 | |
| 余弦加权采样 | 低 | 漫反射为主的积分(辐照度图,见 IBL) | |
| GGX 重要性采样 | 低 | 高光积分(IBL 预滤波、路径追踪的镜面反弹) | |
| 光源采样 | 集中在光源方向 | 低 | 直接光照(路径追踪对点光源/面光源的采样) |
注:重要性采样只是降低方差,不改变结果的期望——只要估计量无偏,任何 的采样最终都收敛到同一个积分。它的意义在于"同样数量的样本,噪声小得多"。
4. 与实时渲染的联系
渲染方程、蒙特卡洛与重要性采样构成离线渲染(路径追踪)的完整理论,实时渲染则走"绕开积分"的路线:
| 环节 | 渲染方程里的角色 | 实时做法 |
|---|---|---|
| 直接光照 | 积分中少数几个方向 | 离散光源求和,积分退化为累加(PBR) |
| 间接漫反射 | 半球积分 | 预计算成辐照度图,采样一次(IBL) |
| 间接高光 | 依赖粗糙度与视角的积分 | 预滤波 mipmap + BRDF LUT 查表(IBL) |
一句话总结:实时渲染里"积分"要么被求和替代,要么被预计算替代;重要性采样则是在必须实时采样时(比如 IBL 的离线预计算、路径追踪)用更少的样本换更低的噪声。这套"预计算换实时性"的思路,与 ShadowMap与PCF、PCSS 的阴影贴图、纹理 的 mipmap 一脉相承。


