光谱渲染
Spectral Rendering
光谱渲染 (Spectral Rendering) 在光传输中直接处理波长,而不是 RGB 三元组。pbrt 第 4 版在每条相机光线上随机采样少数几个波长(默认 4 个),把光谱积分并入渲染本来就在做的蒙特卡洛积分;最后用颜色匹配函数估计像素的 XYZ/RGB。输入端的 RGB 颜色则通过"sigmoid 二次多项式"转换成平滑光谱。本页按 PBRT 4e 4.5、4.6.4–4.6.6 节整理。
为什么要光谱渲染(PBRT 4.6.4)
色彩空间对加法封闭,但分量相乘的结果取决于所选色彩空间。PBRT 的例子:反射率和光照都是 sRGB 绿 ,在 sRGB 里相乘仍是 ;同一颜色在 ACES2065-1 中约为 ,相乘得 ,不但变暗,饱和度还高到超出可实现颜色的马蹄形。本页用标准原色与白点矩阵复算:sRGB 绿在 ACES2065-1(不做色适应)中为 ,平方为 ,与书一致。 另外,光谱表示能自然地处理色散、薄膜虹彩和表面微结构衍射等依赖波长的效果。
| 观点 | 来源 |
|---|---|
| RGB 渲染在多数情况下够用,只在特殊情况失败 | RTR4 第 8 章(见 色度学与色彩空间"用 RGB 渲染") |
| RGB 相乘的结果随色彩空间任意变化,即使最终输出 RGB 也应做光谱渲染 | PBRT 4e 4.6.4 |
游戏引擎几乎都在线性 RGB(常是 sRGB/Rec.709 原色,或 ACEScg)中做光照;了解 PBRT 的论证有助于理解为什么换工作色彩空间会让同一材质的多次反弹颜色发生变化。
光谱的表示(PBRT 4.5.1–4.5.3)
pbrt 的波长单位是 nm。Spectrum 接口用 TaggedPointer 实现运行时多态:指针里带类型标签,Dispatch() 根据标签调用具体类型的方法,接口是隐式的(实现类并不继承 Spectrum),这样 CPU 与 GPU 代码都能用,又避免虚函数表(细节在附录 B.4.4)。必须实现 operator()(λ) 和 MaxValue()(后者用于给光源功率求上界,以便按贡献采样光源)。
| 实现 | 作用 |
|---|---|
ConstantSpectrum | 常值光谱,常用于表示"没有这类散射"的零光谱 |
DenselySampledSpectrum | 在整数波长区间上每 1 nm 存一个值,求值只需一次查表;覆盖可见光约需 2 kB |
PiecewiseLinearSpectrum | 对之间线性插值,变化快的区域可加密;区间外为 0 |
BlackbodySpectrum | 归一化黑体光谱:用维恩定律求峰值波长,除以峰值使最大值为 1(总功率随 增长太快) |
RGBAlbedoSpectrum / RGBUnboundedSpectrum / RGBIlluminantSpectrum | 由 RGB 转来的反射率、无界、光源光谱(见下文) |
pbrt 二进制里内嵌了常用光谱(光源发射谱、导体的复折射率、各种玻璃的色散折射率),用 GetNamedSpectrum() 按名称取;Spectra::X/Y/Z() 返回 CIE 匹配曲线,Spectra::D() 返回给定色温的 D 光源。
点采样光谱:SampledSpectrum 与 SampledWavelengths(PBRT 4.5.4)
直接对光谱函数做运算会失控:两个分段线性光谱相乘变成分段二次,再乘次数继续升高,不同表示两两组合还要各写实现。pbrt 的做法是把波长也当作蒙特卡洛的一个积分维度。例如某波段的辐照度
只需在采样到的离散波长上求被积函数。
SampledSpectrum:NSpectrumSamples个值(默认 4,改动需重新编译),逐分量的加减乘除、SafeDiv(除数为 0 时得 0)、Lerp/Sqrt/Clamp/Pow/Exp、Min/MaxComponentValue、Average;可隐式转成 bool 判断是否全零,以便反射率为 0 时跳过追踪。SampledWavelengths:存波长及其 PDF。SampleUniform()只用一个随机数:第一个波长均匀取,其余按等间距 递增并在越界时回绕,得到分层的波长样本,且改变样本数不必改调用方代码。- 色散时只留一个波长:折射方向依赖波长时,一条光线无法再同时携带多个波长。
TerminateSecondary()把除lambda[0]外的 PDF 置 0,并把幸存者的 PDF 乘以 ,原理同俄罗斯轮盘赌(见 蒙特卡洛积分与重要性采样)。总让lambda[0]幸存之所以正确,是因为每个波长都来自同一分布;因此SampleUniform()不能把lambda[0]固定放在第一个分层里。 - 为什么两个类分开:把波长存进每个
SampledSpectrum可以在运行时发现"混用不同波长"的 bug,但临时对象极多,GPU 路径同时存几百万个,所以要尽量小;实践中波长在路径开始时采样并沿路径不变,混用的 bug 很少见。pbrt 早期在调试版里带过检查,几个月没发现 bug 后删掉了。
每条光线带几个波长(PBRT 4.6.5)
每条光线只带一个波长时,要用一个光谱值估计 R、G、B 三个值,颜色噪声很大。光线路径通常与波长无关、而多算几个波长的光照很便宜,所以每条光线带多个波长是有效的分裂(splitting)。PBRT 的实验(只有点光源直接光照、散射项零方差、误差全部来自颜色匹配积分的场景):
- 32 个波长比 1 个波长慢约 1.6 倍;独立采样时 MSE 按 下降,分层采样误差低几个数量级且收敛更快;32 个分层波长的效率比 1 个高一百万倍以上,曲线还没走平。
- 默认仍取 4 的三个理由:8 到 32 个波长误差虽差约 500 倍,但图像已无法分辨;每像素本来就要取多条路径,像素内的总波长数随之增加;最重要的是,真实场景里其他蒙特卡洛误差源占主导——在一个光照复杂的场景中,6 个以后 MSE 收益有限,8 个时效率最高。
从 RGB 到光谱(PBRT 4.6.6)
由于同色异谱,RGB→光谱是欠定问题;这也意味着可以挑一个简单高效的解。要区分三类光谱:光源光谱(非负、无界,从平滑到尖峰)、反射率光谱(在 内,通常平滑)、无界光谱(非负、无界但不发光,如折射率、介质系数)。目标:
- 恒等:RGB→光谱→RGB 回到原值;
- 平滑:光谱本身平滑,且 RGB 的微小变化只引起光谱的微小变化(否则换光源时纹理上会出现接缝);
- 能量守恒: 的 RGB 得到 的光谱。
sigmoid 多项式模型(Jakob & Hanika 2019):
二次多项式能表示常数、线性、中间单峰或两端高的曲线,覆盖真实反射率的常见形状(白/黑、近线性、单峰的绿黄、双峰的蓝紫);sigmoid 严格单调、把值压进 保证能量守恒。全吸收/全反射需要多项式趋于 ,会出现 的 NaN,代码单独处理。MaxValue() 只需比较 360/830 nm 两端与多项式驻点(sigmoid 单调)。
- 系数求解:最小化往返误差 , 为白点(因而灰色 RGB 映射到常数光谱);在 sRGB 这类紧凑色域内可达零误差,ACES2065-1 等含虚色的色域做不到,所以误差用感知均匀的 CIE76 (在 CIELAB 中算 距离);求解用 Gauss–Newton,每次约几微秒,太慢,不能逐纹素现算。
- 预计算表:编译 pbrt 时对 sRGB、DCI-P3、Rec2020、ACES2065-1 各算一张覆盖 的系数表(
cmd/rgb2spec_opt.cpp)。不只按二维色度表(把 的光谱缩放给 ),因为高饱和色光谱必须窄峰,低饱和色可以更平滑,三维表能保住平滑性。系数在最大分量切换处突变,所以按 r/g/b 哪个最大分成三块分别列表;以 r 最大为例,坐标 ,最大分量总映射到 ,使三个坐标都落在 ; 等距, 用在 0 和 1 附近加密的非线性节点(二分查找),再做三线性插值( 方向虽非线性也按线性插值,误差很小)。表是五维数组:[最大分量][z][y][x][3 个系数]。三个分量相等时直接返回 的常数光谱(反解 sigmoid 得 ),避免插值带来的轻微色偏。 - 无界 RGB:先按最大分量缩放,但缩放到最大值 1/2 而不是 1:高饱和颜色在 1 附近会被能量守恒约束逼出怪异形状(书中 的例子短波端能量偏多),留出余量后拟合更规整,再乘回比例。
- RGB 光源:不去猜复杂的发射谱,而是用平滑光谱乘色彩空间白点的光谱(像透过彩色滤光片看白光源),保证白光照白物体得到白像素。等能光谱转到 RGB 通常不是中性白,因为色彩空间假定观察者适应了某种环境光(如 D65)。
在游戏开发中的取舍
- 实时渲染很少做全光谱,但 PBRT 的结论可用于:选择工作色彩空间时意识到多次反弹的颜色会变;需要色散、薄膜、黑体色温光源时局部使用光谱计算再投影回 RGB(色温→RGB 本质是黑体光谱的 XYZ 积分)。
- 离线烘焙器/路径追踪参考渲染若要与游戏画面对齐,必须与引擎使用同一工作色彩空间和白点。
原书问题(PBRT 4.6.5–4.7)
| 位置 | 原书说法 | 核对结果 |
|---|---|---|
| 4.6.5 | "图 4.26(a) 显示 8 到 32 个波长误差降低近 500 倍" | 按图注,4.26(a) 是渲染时间,MSE 在 4.26(b);应指 (b) |
| 4.6.6 | "locating the maximum of the quadratic polynomial from Equation (4.25)" | 按 HTML 中的公式标签,式 4.25 是 sigmoid ,二次多项式在式 4.26 中;应引用式 4.26(来源:https://pbr-book.org/4ed/Radiometry,_Spectra,_and_Color/Color ) |
| 4.7 参考文献 | "Walter, B., P. M. Hubbard, P. Shirley, and D. F. Greenberg. 1997" | 第四作者是 Donald P. Greenberg,应为 D. P. Greenberg(来源:ACM DL doi 10.1145/256157.256158 作者列表;书中 Meyer and Greenberg 1980 等条目也写作 D. P. Greenberg) |
PBRT 的视角:胶片、传感器与可见光波长采样(PBRT 4e 5.4)
相机测量方程(5.4.1)
胶片上一点的辐照度可从辐亮度定义出发、把立体角换成后透镜切平面上的面积 ;胶片与透镜平行,,( 为轴向距离),于是
胶片相对 较大时 明显降低边缘亮度,也是暗角 (vignetting) 的成因之一,数码相机通常用预设系数补偿。对快门时间积分得辐射曝光量 (J/m²,式 5.4),再对像素面积积分得到像素接收的焦耳数,称为相机测量方程(式 5.5)。pbrt 只在 RealisticCamera 中计入这些因子,简单相机不计入,以便与其他渲染器对比。
传感器响应(5.4.2)
像素红色分量 (式 5.6)。真实传感器是绿色像素数量为红蓝两倍的马赛克,需要去马赛克;主要噪声是服从泊松分布的散粒噪声;ISO 在数码相机里就是读出增益,会放大噪声。pbrt 不模拟马赛克、噪声、溢出 (blooming) 和卷帘快门,所以 ISO 可以随意设置以得到想要的曝光。PixelSensor 模拟三件事:曝光控制(快门时间与 ISO 合成"成像比")、基于实测相机光谱响应曲线的 RGB 响应(书中用 Canon EOS 5D 曲线渲染,色调比 XYZ 匹配函数更冷)、白平衡。传感器 RGB 到 XYZ 的 3×3 矩阵由二十多个标准色卡色块用线性最小二乘拟合(式 5.7),亮度按第二个匹配函数对光源的积分归一化,相当于按视觉重要性加权;由于两边用各自的光源计算,这个矩阵同时完成白平衡。传感器响应用蒙特卡洛估计:(式 5.8)。
白平衡(5.4.2)
人眼的色适应让物体颜色在不同光照下看起来不变,相机对应的处理叫白平衡。pbrt 实现 von Kries 变换:在与三种视锥细胞响应匹配的 LMS 空间中,除以场景光源的颜色、乘以目标白点的颜色(一个对角矩阵),前后各乘 XYZ↔LMS 矩阵。书中用 3000 K 色温给白炽灯照明的场景做白平衡。默认的 XYZ 传感器不做白平衡,留给后期(色彩空间与白点见 色度学与色彩空间)。
按传感器响应采样波长(5.4.2)
只按 CIE 采样会有过多色噪;按 之和采样又在视觉上不重要的 400–500 nm 浪费样本。pbrt 用参数化分布
本页验算:,在 360–830 nm 上的归一化常数为 0.0039398,与代码中的 0.0039398042f 一致;逆变换采样 中的三个常数分别是 、 和 ,也都对得上(逆变换采样见 随机变量变换与逆变换采样)。SampleVisible() 用一个随机数在 上等间距地生成全部波长样本。与均匀采样相比色噪大幅降低,运行时间只增加约 1%。
RGBFilm 的工程细节(5.4.6–5.4.7)
- 像素累加和用双精度:书中用每像素 400 万样本渲染参考图,32 位浮点的参考图在约 1000 spp 后 MSE 就不再下降(本应是斜率 −1 的直线),64 位则正常。用低精度参考图评估采样算法会得出错误结论。
- 萤火虫钳制:
maxComponentValue把每个样本的传感器 RGB 钳到上限(默认无穷大)。能明显改善有太阳等难采样光路的图像,但损失能量、引入偏差;习题指出直接看到太阳的像素不该被钳,建议用 Zirr 等 (2018) 的方法。 AddSplat()可能被多个线程同时写同一像素,必须用原子操作或互斥;浮点加法不满足结合律,因此 splat 结果不再确定性可重现(习题)。GBufferFilm另存位置、法线、反照率、深度对光栅坐标的偏导及颜色方差,供降噪或机器学习使用。
原书问题(PBRT 第 5 章,在线版)
| 位置 | 原书说法 | 核对结果 |
|---|---|---|
| 5.4.2 | "silver halide crystals produce silver bromide when they are exposed to light" | 溴化银本身就是卤化银的一种(胶片乳剂常用的卤化银正是溴化银或溴碘化银);曝光只在晶体中形成潜影,显影时被曝光的卤化银还原为金属银。应为"卤化银晶体曝光后(经显影)生成金属银"(来源:Wikipedia "Photographic film" 乳剂与显影部分,引 Fujita《Organic Chemistry of Photography》2004) |
| 5.4.4 | "Light transport algorithms that sample paths starting from the light sources (such as bidirectional path require the ability to 'splat'…" | 括号未闭合且漏词,应为"(such as bidirectional path tracing) require…"(https://pbr-book.org/4ed/Cameras_and_Film/Film_and_Imaging ;读者已在 pbr-book-website issue #22 报告:https://github.com/mmp/pbr-book-website/issues/22 ) |
出处
- PBRT 4e source excerpt: chapter 04 (Radiometry, Spectra, and Color)
- Pharr, Jakob, Humphreys《Physically Based Rendering: From Theory to Implementation》第 4 版(MIT Press, 2023)第 4 章 4.5、4.6.4–4.6.6 节,pbr-book.org/4ed/Radiometry,_Spectra,_and_Color
- PBRT 4e source excerpt: chapter 05 (Cameras and Film)
- Pharr, Jakob, Humphreys《Physically Based Rendering: From Theory to Implementation》第 4 版(MIT Press, 2023)第 5 章 5.4 节,pbr-book.org/4ed/Cameras_and_Film