Chapter 38: Radiosity Methods
Radiosity 讨论的是静态 diffuse 场景中表面之间怎样交换能量。读完本章后,读者应能追踪一个室内 frame 中的能量路径:天花板灯具把能量发到墙面,墙面把一部分能量按自身反射率重新发出,地板、箱体和角落继续接收这些能量,最终形成颜色渗透、柔和间接光和局部能量积累。
本章贯穿一个固定场景:一个封闭房间,天花板有一块面光源,左墙为红色 diffuse 材质,右墙为灰白 diffuse 材质,地板和两个箱体也使用 diffuse 材质。这个场景接近经典 Cornell Box 的观察目标,相关历史和测试场景可从 Cornell Box 条目 追溯到早期 diffuse interreflection 研究;Radiosity 的基本算法关系也可从 Radiosity in computer graphics 追到 finite element 形式的渲染方程近似。
Radiosity 的核心结论很具体:当场景主要由静态 diffuse 表面构成时,可以把连续表面切成 patch,把每个 patch 离开的总能量写成未知量,再用 form factor 表达 patch 之间的可见、距离、朝向和面积关系。求解完成后,结果可以 bake 到 lightmap 或顶点颜色中,运行时 rasterization 只负责采样这些预计算结果。
这条路径把全局光照从逐像素射线积分转成一个离线线性系统。它的收益是视角无关、运行时成本稳定、间接 diffuse 结果平滑;它的代价是前处理计算量、patch 或 lightmap 存储、动态场景更新和非 diffuse 材质表达能力。
38.1 Radiosity 算法的数学基础
Radiosity 在图形学中的工作定义是:某个表面单位面积向外离开的总光能量,来源包括自身 emission 和从其他表面接收后按 diffuse 反射率重新散射出去的能量。它关心的是“表面离开多少能量”,因此结果与相机位置无关。只要场景几何、材质和光源保持固定,同一份 radiosity 解可以服务多个观察视角。
贯穿场景中,天花板灯具 patch 的 emission 较高,红墙 patch 的 reflectance 在红色通道高、绿色和蓝色通道低,灰白墙面三个通道比较接近。灯具先把能量送到墙面和地板,红墙接收后重新发出的能量在红色通道更强,于是地板和灰墙会出现红色渗透。这个结果来自能量方程,和相机看到哪一面没有直接关系。
把房间表面切成 个 patch 后,每个 patch 有面积 、diffuse 反射率 、自身发光项 和未知 radiosity 。若 表示从 sender patch 对 receiver patch 的几何传输比例,简化 radiosity 方程可以写成 。这个式子在 RGB 渲染中通常按通道分别求解,红墙的颜色渗透来自 在不同颜色通道上的差异。
这条方程包含三个层次。第一层是 emission,灯具 patch 即使没有其他表面也会向外发光。第二层是几何传输,form factor 把 sender 的能量按面积、朝向、距离和遮挡分配给 receiver。第三层是材质反射,receiver 收到能量后按 diffuse reflectance 把其中一部分重新贡献到自己的 outgoing radiosity 中。
写成矩阵形式时,所有 patch 的 radiosity 组成向量 ,emission 组成向量 ,diffuse 反射率形成对角矩阵 ,form factor 形成矩阵 ,关系为 。求解对象是整组 patch 的稳定能量分布。只要场景中材质反射率整体低于能量守恒边界,反复传播能量会收敛到稳定结果。
在工程实现中,直接求逆 对大型场景通常开销过高。更常见的做法是迭代:先把 初始化为 emission,再反复计算所有 patch 接收的间接能量并更新 。每轮迭代可以理解为多传播一层 diffuse bounce;若增量低于阈值,当前结果已经足够稳定。
下面的简化代码只表达 gather 迭代的关键数据路径。form_factors 负责把上一轮 sender radiosity 变成 receiver incoming energy,reflectance 负责材质吸收和反射,emission 保留光源项。
radiosity = emission.copy()
for bounce in range(max_bounces):
incoming = form_factors @ radiosity
updated = emission + reflectance * incoming
delta = max_abs(updated - radiosity)
radiosity = updated
if delta < convergence_threshold:
break
这段代码省略了 patch 面积、RGB 通道布局和稀疏矩阵存储,但保留了 radiosity 的工程骨架:输入是 patch 材质、emission 和 form factor,处理过程是迭代能量传播,输出是每个 patch 的稳定离面能量。后续 bake 阶段会把这些 patch 结果投射到 lightmap texel 或顶点上。
在贯穿场景中,第一轮主要产生直接照明:灯具能量到达地板、墙和箱体。第二轮开始,红墙把红色能量重新贡献给地板和灰墙。继续迭代后,角落处多表面互相可见,能量多次交换,暗部会被间接光抬起。这个过程给出了判断顺序:先看 emission,再看 form factor,再看 reflectance,最后看迭代残差。
38.2 Form Factors 的计算与近似方法
Form factor 是 radiosity 中最关键的几何项。它回答一个具体问题:sender patch 上离开的 diffuse 能量,有多少比例能到达 receiver patch。这个比例由四类因素共同决定:两个 patch 的面积、两个法线之间的夹角、中心或积分点之间的距离,以及中间是否被其他几何遮挡。
对两个微小面积元素,几何项可以近似写成 。这里 是可见性, 是两点距离, 和 是连线方向与两个法线的夹角。这个式子解释了室内画面中的常见结果:相互正对、距离近、无遮挡的墙角 patch 交换强;背向、远距离或被箱体挡住的 patch 交换弱。
Form factor 具有两个工程检查性质。第一,封闭 diffuse 场景中,一个 patch 向外发出的能量会被其他表面接收,行和接近 1;有开口或能量逃逸时,行和小于 1。第二,面积互易关系 可以用来检查成对 patch 的传输矩阵是否出现明显错误。若互易关系大面积失真,后续求解会产生能量偏色或局部过亮。
计算 form factor 有多种路径,选择取决于场景规模、几何复杂度和期望误差形态。
| 方法 | 输入 | 输出误差形态 | 适用判断 |
|---|---|---|---|
| 解析公式 | 简单矩形、平面、规则几何 | 误差低,覆盖范围窄 | 小型测试、单元校验、基准结果 |
| 数值积分 | patch 采样点、可见性查询 | 采样密度决定平滑度 | 中小场景、精度可控离线 bake |
| Hemicube | patch 中心、五面投影、深度测试 | 分辨率和投影离散导致锯齿 | 多边形场景、可复用 rasterization 能力 |
| Monte Carlo | 随机方向、射线命中、概率权重 | 噪声随样本数下降 | 复杂遮挡、大场景、可并行预计算 |
解析公式适合验证算法方向。若两个矩形 patch 大小、距离和朝向固定,可以用解析值检查程序中的面积单位、法线方向和颜色通道是否正确。工程中常把一个两面墙或盒子角落作为最小测试,先确认 form factor 的方向和数量级,再放入完整房间。
Hemicube 方法把 receiver 或 sender 附近的半球可见性转成五个 rasterization 视图。每个像素携带预计算的 delta form factor,深度测试给出该方向最近的可见 patch,累加像素贡献后得到一组 form factor。这个方法的价值在于把可见性问题交给图形管线处理,经典 hemicube 思路可追溯到 Cohen 和 Greenberg 的 1985 年工作,相关条目可见 Hemicube in computer graphics。
Hemicube 的误差主要来自离散分辨率和 patch 投影。分辨率过低时,小物体遮挡会漏掉,墙角阴影边界会变钝;分辨率过高时,form factor 计算和内存累加成本上升。对于室内 bake,常见做法是把大 patch 先按光照变化切细,再给 hemicube 或采样器提供更合理的几何单元。
Monte Carlo 估计把每个 patch 的半球方向随机采样,发射射线查找第一个命中表面,再用采样概率和几何权重累加贡献。它与路径追踪共享“用样本估计积分”的思想,但 radiosity 的目标仍是求每个 surface element 的视角无关 outgoing energy。样本数低时结果会出现 blotchy 间接光;样本数增加、分层采样和低差异序列能改善噪声形态。
Form factor 排查应按固定顺序进行。先检查 patch 法线是否朝向场景内部,再检查面积单位和尺度是否统一,再检查行和与互易关系,之后观察遮挡项。若红墙背面的 patch 仍向房间内部贡献红光,首要问题通常是法线或可见性;若整个房间偏暗,常见问题是反射率、行和或单位比例过低。
38.3 离线 Radiosity 场景实现
离线 radiosity 管线的目标是把静态场景中的 diffuse 间接光提前算好,并把结果转成运行时容易采样的数据。它通常位于 asset build、lighting bake 或场景发布流程中,而运行时 draw call 只读取 lightmap、顶点颜色或 probe 数据。
下面的流程图描述本章贯穿场景从几何输入到运行时采样的路径。图中的每个节点都对应一类可检查数据:mesh patch、form factor 矩阵、迭代残差、lightmap texel 和最终 frame。
第一步是 mesh patching。墙面、地板和箱体需要切成能承载光照变化的 surface element。平整白墙可以使用较大的 patch;靠近红墙、箱体接触边和灯具附近的区域需要更细的 patch。切分粒度决定了能量分布的空间分辨率,后续 lightmap 再高也无法恢复 patch 阶段已经丢失的变化。
第二步是材质和 emission 数据准备。每个 patch 至少需要 diffuse reflectance、emission、面积、法线、位置和 lightmap UV 映射。反射率应使用线性颜色空间参与能量计算,sRGB 贴图需要在线性化后进入求解器。若直接用 gamma 编码颜色做能量传播,红墙颜色渗透和暗部抬升都会偏离物理尺度。
第三步是 form factor 计算。小型场景可以使用完整矩阵,patch 数量增加后应使用稀疏表示、分块计算或阈值裁剪。室内房间大多数 patch 存在远距离弱贡献,稀疏化可以减少内存和矩阵乘法成本。稀疏阈值需要和能量守恒检查一起使用,阈值过高会削弱多次 bounce 后的低频间接光。
第四步是迭代求解。工程中常见停止条件包括最大 bounce 数、全局能量增量、局部最大增量和可见误差阈值。对于 diffuse 室内场景,前几轮 bounce 决定主要视觉变化,后续迭代主要抬高暗部和补充角落能量。求解日志应记录每轮总能量和最大 patch 增量,用来判断收敛状态。
第五步是 bake 到 lightmap。Patch radiosity 可以先插值到 lightmap texel,再经过 seam dilation、mipmap 生成和压缩。Lightmap 分辨率应跟几何光照变化匹配:大面积平墙需要稳定低频,箱体接触边、红墙附近和灯具投影区域需要更多 texel。若 UV chart 间距不足,mipmap 会把亮区颜色扩散到相邻 chart,形成漏光。
第六步是运行时采样。最终 shader 通常把直接光、材质 albedo、baked indirect light 和可选阴影项组合起来。Radiosity bake 结果已经包含 diffuse 间接光,运行时再叠加强 ambient 会抬高暗部并削弱墙角层次。更稳的做法是把 direct lighting、baked indirect 和后处理曝光分开观察。
一个最小实现可以把 patch 结果直接写成顶点颜色,用于验证能量传播链路;正式资产通常写成 lightmap,因为 texel 分辨率能独立于 mesh 拓扑。顶点颜色适合粗糙 blockout 或低多边形资产,lightmap 适合室内建筑、静态道具和需要明确阴影接触关系的空间。
离线管线的失败情况也有固定迹象。Patch 太大时,红墙颜色渗透会变成大块均匀染色;form factor 可见性错误时,箱体背面会收到穿透光;lightmap UV 间距不足时,阴影边缘会在 mipmap 中向外扩散;颜色空间错误时,整体能量分布会偏灰、偏暗或过饱和。排查时先锁定几何与法线,再看 form factor debug,再看求解残差,最后检查 lightmap 写入和运行时采样。
38.4 Radiosity 与其他 GI 算法对比
Radiosity 的定位是“把 diffuse interreflection 预计算成视角无关的表面能量分布”。这个定位决定了它和其他 global illumination 方法的差异。比较时应使用同一组维度:支持的光路、是否依赖视角、动态更新成本、存储形态、噪声形态和运行时开销。
| 方法 | 主要表达对象 | 视角关系 | 运行时成本 | 典型优势 | 典型边界 |
|---|---|---|---|---|---|
| Radiosity | 静态 diffuse 表面间能量交换 | 视角无关 | 低,主要采样 bake 结果 | 室内 diffuse 间接光、颜色渗透、稳定 lightmap | 动态几何和 glossy/specular 表达弱 |
| Path Tracing | 从相机出发的多 bounce 路径积分 | 视角相关 | 高,样本数决定噪声 | 统一表达 diffuse、specular、透明和复杂光路 | 实时低样本需要积累和降噪 |
| Photon Mapping | 光源发射光子后密度估计 | 渲染阶段相关 | 中到高,依赖查询和半径 | 焦散、小光源、多 bounce 能量缓存 | 半径和光子密度影响 bias |
| Irradiance Probe / Light Probe | 空间点上的低频间接光 | 采样位置相关 | 低到中 | 动态物体接收间接光 | 几何接触和遮挡细节弱 |
| Screen Space GI | 屏幕可见信息近似间接光 | 强视角相关 | 中,依赖屏幕采样 | 易接入实时后处理 | 屏幕外信息缺失 |
在本章贯穿场景中,Radiosity 对墙面颜色渗透和角落柔和间接光很合适,因为场景静态、材质以 diffuse 为主、最终结果可以 bake。Path tracing 能覆盖更广的材质和光路,尤其适合镜面反射、透明折射和高精度参考图;但它在实时低样本下会产生噪声,需要 temporal accumulation 和 denoiser。Photon mapping 对焦散和小光源聚焦有优势,适合水杯、玻璃、金属聚光等现象。
Radiosity 的视角无关性带来两个工程结果。第一,玩家或相机移动时,墙面间接光稳定,lightmap 采样成本接近普通纹理读取。第二,场景中灯光、墙体颜色或大块几何改变后,预计算结果需要局部或全局更新。若游戏需要开关灯、破墙、移动大型家具,传统离线 radiosity 的更新成本会进入设计约束。
和实时 GI 近似相比,Radiosity 的存储从“每帧计算”转成“离线 bake 和运行时读取”。这使它适合建筑可视化、静态关卡、移动端室内场景和高质量预烘焙流程。它对运行时 GPU 压力友好,但资产管线需要管理 lightmap UV、chart padding、压缩格式、mipmap 和不同质量等级。
在图形工程中,选择 GI 方法时可以按三步判断。先看场景是否静态和 diffuse 占比是否高;再看需要表达的视觉现象是颜色渗透、暗部抬升、焦散、镜面多 bounce 还是动态遮挡;最后看预算落在离线构建、运行时 GPU、内存还是内容制作。Radiosity 适合把预算前移到 bake 阶段,用存储换取稳定运行时表现。
38.5 室内照明 Radiosity 效果展示
室内 radiosity 的效果应通过可观察证据判断。对贯穿场景而言,直接光版本通常只有灯具照到的墙面、地板和箱体明亮,遮挡区快速变暗;radiosity bake 后,红墙附近的地板和灰墙带有红色间接光,箱体背光面得到柔和补光,墙角暗部仍保留接触层次。
颜色渗透是最容易检查的现象。红墙接收天花板灯具能量后,按红色高反射率重新发出能量;靠近红墙的地板和箱体侧面会变暖。若颜色渗透覆盖整个房间且强度均匀,patch 过大或 form factor 稀疏阈值可能过高;若红色完全没有传到相邻表面,常见原因是反射率通道、法线方向、可见性或 bounce 次数设置错误。
间接光柔化来自多次 diffuse 传播。箱体背面没有直接看到灯具,但它能看到被照亮的墙面和地板,因此会得到低频补光。这个补光通常平滑、低对比、无高频噪声。若背面出现随机斑块,问题多半在 Monte Carlo form factor 样本数、lightmap texel 插值或迭代结果过滤;若背面被整体抬得过亮,应检查 albedo、额外 ambient 和曝光。
角落能量积累需要同时看亮度和遮挡。墙面、地板和箱体形成的凹角会接收周围多个 patch 的反射,但几何遮挡也限制可见方向。正确结果通常是暗部被抬起,同时接触线附近仍有层次。若角落完全发灰,可能把 baked indirect 与 ambient 重复相加;若角落出现锐利漏光,优先检查 lightmap UV padding、chart dilation 和背面几何封闭性。
Lightmap 分辨率会改变 radiosity 的空间表达。低分辨率 lightmap 会把箱体接触阴影、灯具边界和红墙渗透边缘压成大块颜色;高分辨率能保留局部变化,但会增加内存、构建时间和 streaming 压力。分辨率选择应跟可见光照变化匹配,平坦墙面用低频 texel,接触边和颜色边界给更多密度。
实际调试时,建议准备四个视图:albedo-only、direct-only、baked indirect-only 和 final composite。Albedo-only 检查材质输入;direct-only 检查灯具和阴影;baked indirect-only 检查 radiosity 的颜色渗透和多 bounce;final composite 检查 tone mapping、曝光和材质叠加。这个拆分能把视觉问题定位到管线阶段,防止把 lightmap、材质和后处理混成一个模糊结论。
Radiosity 展示的判断终点是:画面中的红色渗透、暗部抬升和墙角层次,都应能追溯到 patch emission、form factor、reflectance、迭代求解和 lightmap 采样中的某一环。若无法从最终 frame 回推到这些数据,效果展示就缺少工程可复查性。
最小自检任务
给定一个静态室内盒子:天花板有白色面光源,左墙为红色 diffuse 材质,右墙和地板为灰白 diffuse 材质,中间有一个灰色箱体。渲染时发现地板靠近红墙处没有任何红色渗透,箱体背光面也接近全黑。请按 radiosity 管线给出排查顺序,并说明每一步要验证什么证据。
答案要点
先检查输入材质和颜色空间。左墙 diffuse reflectance 应在线性空间中保留红色高反射率,灯具 patch 应具有 emission。若红墙 reflectance 被写成灰色或 sRGB 值直接进入能量求解,颜色渗透会失真。
再检查 patch 法线和几何封闭。红墙、地板和箱体 patch 的法线应朝向房间内部,箱体背面应能看见被照亮的墙面或地板。若法线朝外,form factor 会把能量发到房间外;若房间存在几何缝隙,能量会从开口逃逸。
接着检查 form factor 矩阵。红墙到相邻地板、地板到箱体背光面的传输项应为非零,互易关系和行和应在合理范围内。若相邻 patch 的 form factor 为零,问题通常在可见性、采样方向、hemicube 分辨率或遮挡测试。
然后检查迭代求解。第一轮主要是直接光,第二轮以后才会产生明显红色渗透和背面补光。若 bounce 数设置过低或收敛阈值过粗,间接光不足;若总能量每轮快速归零,应检查 reflectance 和矩阵乘法方向。
最后检查 bake 和运行时合成。Baked indirect-only 视图应能单独看到红墙贡献和暗部补光;final composite 应把这份结果和 direct lighting 按线性空间组合。若 bake 视图正确但最终画面仍全黑,问题在 lightmap UV、纹理采样、压缩、shader 绑定或曝光。
本章知识点总结
- Radiosity 定义:Radiosity 表达单位面积表面向外离开的总能量,包含自身发光和 diffuse 反射后的能量。
- Patch 建模:连续表面需要切成 patch,patch 的面积、法线、反射率和 emission 构成 radiosity 求解输入。
- 能量方程: 把发光、几何传输和材质反射合成一个稳定能量系统。
- 视角无关:Radiosity 解绑定在表面上,相机移动后可以复用同一份静态 diffuse 间接光结果。
- Form Factor:Form factor 由面积、朝向、距离和遮挡决定,是 patch 之间传输能量的几何权重。
- 互易检查: 可作为 form factor 方向、面积和单位的一类工程校验。
- Hemicube 路径:Hemicube 把半球可见性转成 rasterization 视图,用深度测试和 delta form factor 累加几何传输。
- 迭代求解:每轮迭代增加一层 diffuse bounce,残差和总能量变化用于判断求解是否稳定。
- Lightmap Bake:离线求解结果常写入 lightmap,运行时通过纹理采样获得稳定间接光。
- 方法边界:Radiosity 适合静态 diffuse 室内空间,动态几何、动态灯光和 glossy/specular 光路需要其他 GI 技术补充。
- 效果证据:颜色渗透、背光面柔和补光、角落层次和 lightmap 分辨率变化是室内 radiosity 的主要观察证据。
- 排查顺序:Radiosity 问题应按材质颜色空间、法线和几何、form factor、迭代残差、bake 写入和 shader 采样逐层定位。