把 WorldEnvironment 里的 glow 一开、帧率掉一截,大多数人知道是后处理的锅,但说不清锅在哪一环。Godot 4 的 Forward+ 渲染没有一条抽象的"post-processing stack"配置文件——后处理链就是 RendererSceneRenderRD::render_scene() 里一串按序执行的函数调用,读源码就能看到完整顺序。这篇按 4.4 的 servers/rendering/renderer_rd/renderer_scene_render_rd.cpp 把这张链拆一遍。
主链顺序:不是一条直线
render_scene() 的骨架大致是:
geometry pass(opaque → sky → alpha,写入 rb_color / rb_depth / rb_velocity)
→ SSS / 粗糙度限制(写入/修正 GBuffer 缺失的信息)
→ SSAO / SSIL(半分辨率,只读 depth + normal)
→ SDFGI / VoxelGI 的 cascade 处理(光源移动时逐帧推进)
→ 体积雾(雾密度 + shadow 衰减,写入独立纹理)
→ tonemap pass(bloom 链 + glow + tonemapping + 色彩校正)
→ FSR / 缩放 → resolve → 上屏
两点和直觉不一样。第一,GI 不是几何之后跑的后处理——SDFGI 的 cone trace 发生在 light 数据有变化时(相机跨 cascade、光源动、探针 dirty),gi_sdfgi 的 preprocess/direct light/integrate 三个 compute pass 插在几何 pass 和 tonemap 之间,但触发条件不是"每帧"而是"需要更新"。第二,SSAO/SSIL 只依赖 depth 和 normal,所以它们可以在几何一结束就跑,结果作为 indirect 项注入到采样阶段。
为什么 SSAO 排在 SDFGI 前面
看输入依赖就能排出序。SSAO 读 rb_depth,写自己的半分辨率 AO 纹理,不需要任何光照信息;SDFGI 的 integrate 阶段要把直接光和 AO 烘进 probe 的 octahedral 图集,其中 AO 来源之一就是 SSAO 的结果(gi_sdfgi 的 direct light shader 里会采样 ssao 输出)。所以链上 SSAO 必须先完成——这不是性能考量,是数据依赖。
tonemap pass 是链上最贵也最容易被低估的一环。它不是一个 pass:effects/tonemap.cpp 先对 rb_color 做 7 级(可配)mip 降采样链生成 bloom,再从最亮 mip 逐级上采样合成 glow,最后单次全分辨率 pass 里顺序做 tonemapping、自动曝光(配 LUT)、色彩校正、debanding。bloom 链的成本 = 半分辨率 ~ 1/128 分辨率的 7 次 blur/upsample,glow 强度开高帧时间涨,涨的就是这条 mip 链,不是最后那个全屏 pass。
用户钩子:RenderingCompositor
4.3 把这条硬编码的链上挖了洞:RenderingCompositor(servers/rendering/rendering_compositor.h)把后处理序列建模为若干 stage,第三方可以注册 RenderingEffect,在 pre opaque / post opaque / post sky / pre tonemap / post tonemap 这些点插自己的全屏 pass,拿到 RenderSceneBuffers 里当前所有 RID。这个设计的动机是解决"想往链中间塞东西只能改引擎"的老问题——位置在 tonemap 前的 effect 拿到的是 HDR 线性空间,在后的拿到的是 LDR,文档里反复强调插错位置色彩全错,原因就在这里。
一图流
实战推论
调画质选项时对着这条链看帧时间:SSAO 涨的是半分辨率双 pass + 深度感知 blur;SDFGI 涨的是 integrate 的 probe 更新(静止场景几乎为零);glow 涨的是 mip 链。如果你 profiler 里 tonemap 一项居高不下,先查 glow 的 mip 级数和强度,而不是怀疑 tonemapping 本身——它只是一个 O(像素) 的 ALU pass,bloom 才是 O(像素 × 级数) 的带宽大户。
本文基于 Godot 4.4 源码:servers/rendering/renderer_rd/renderer_scene_render_rd.cpp(render_scene 主序)、servers/rendering/renderer_rd/effects/(ss_effects、gi、sdfgi、tonemap、volumetric_fog)、servers/rendering/rendering_compositor.h(用户钩子)。