Core Class Structure核心类结构

The deferred renderer is implemented by FDeferredShadingSceneRenderer, which inherits from FSceneRenderer (defined in SceneRendering.h). This class orchestrates the entire frame rendering pipeline.

延迟渲染器由 FDeferredShadingSceneRenderer 实现,继承自 FSceneRenderer(定义于 SceneRendering.h)。该类负责编排整个帧的渲染管线。

FSceneRenderer                      // Base class
  └── FDeferredShadingSceneRenderer   // DeferredShadingRenderer.h/.cpp

The per-frame top-level entry point is Render(FRDGBuilder&, const FSceneRenderUpdateInputs*) at DeferredShadingRenderer.cpp:1442, invoked from the render thread. The function is approximately 2300 lines long and registers all rendering passes into the Render Dependency Graph (RDG).

每帧顶层入口是 Render(FRDGBuilder&, const FSceneRenderUpdateInputs*),位于 DeferredShadingRenderer.cpp:1442,由渲染线程调用。该函数约 2300 行,将所有渲染 Pass 注册到 Render Dependency Graph(RDG)中。

What is RDG? The Render Dependency Graph is UE's frame-level task graph for GPU work. Instead of issuing draw calls immediately, code registers "passes" that declare their resource inputs/outputs. At the end, the RDG compiler sorts passes by dependency, inserts barriers, manages resource lifetimes, and can overlap async compute work automatically. This means the C++ call order you see in Render() is the registration order, not necessarily the GPU execution order. 什么是 RDG? Render Dependency Graph 是 UE 的帧级 GPU 任务图。代码不立即发出绘制命令,而是注册声明输入/输出资源的"Pass"。最后由 RDG 编译器根据依赖排序、插入屏障、管理资源生命周期,并自动重叠异步计算工作。因此 Render() 中的 C++ 调用顺序是注册顺序,不一定是 GPU 执行顺序。

Pipeline State Decisions — CommitFinalPipelineState()管线状态决策 — CommitFinalPipelineState()

Before any rendering work begins, CommitFinalPipelineState() (line 1125) locks every pipeline dimension into an immutable final value. Internally it uses the TPipelineState template which enforces that each dimension is written exactly once, in memory-offset order. This prevents circular dependencies between pipeline stages — once committed, any further write triggers a runtime assertion failure.

在任何渲染工作开始前,CommitFinalPipelineState()(line 1125)将每个管线维度锁定为不可变的最终值。内部通过 TPipelineState 模板按内存偏移顺序强制每个维度只写入一次,防止管线阶段间产生循环依赖——提交后任何写操作都会触发运行时断言失败。

Dimension状态维度 Options可选值 Description说明
DiffuseIndirectMethodDisabled / SSGI / Lumen / PluginDiffuse indirect lighting approach漫反射间接光照方案
AmbientOcclusionMethodDisabled / SSAO / SSGI / RTAOAmbient occlusion technique环境遮蔽方案
ReflectionsMethodDisabled / SSR / LumenReflections (water has its own setting)反射方案(水面有独立配置)
bNanitetrue / falseWhether Nanite virtual geometry is active是否启用 Nanite 虚拟几何
bFurthestHZB / bClosestHZBtrue / falseGenerate Hierarchical Z-Buffer (needed by SSAO, SSR, Nanite, Lumen)是否生成层次 Z 缓冲(SSAO/SSR/Nanite/Lumen 均需要)
// CommitFinalPipelineState() — line 1125
FamilyPipelineState.Set(&FFamilyPipelineState::bNanite, UseNanite(ShaderPlatform));
FamilyPipelineState.Set(&FFamilyPipelineState::bHZBOcclusion, ICVarHZBOcc->GetInt() != 0);

CommitIndirectLightingState();  // Sets DiffuseIndirect / AO / Reflections

// After Commit(), any write triggers check() failure
GetViewPipelineStateWritable(View).Commit();
FamilyPipelineState.Commit();

Render() Main Loop OverviewRender() 主循环概览

The Render() function unfolds across 12 sequential stages. Resource access ordering between stages is enforced via RDG pass dependencies and ExternalAccessQueue. Stages like Lumen GI and volumetric cloud can run on the Async Compute queue, overlapping with subsequent Graphics queue work.

Render() 函数按 12 个阶段顺序展开。阶段间的资源访问顺序通过 RDG Pass 依赖和 ExternalAccessQueue 保证。Lumen GI 和体积云等阶段可运行在异步计算队列上,与后续图形队列工作重叠。

00Frame Initialization帧初始化

line 1442–1600 CPU

Sets up the frame: processes pending ray tracing geometry builds, commits pipeline state, initializes system textures, prepares sun light proxy for atmosphere, kicks off Lumen scene update and light gathering tasks asynchronously, begins Nanite visibility, and starts virtual texture streaming.

帧准备工作:处理待定光追几何构建请求、提交管线状态、初始化系统贴图、为大气准备太阳光代理、异步启动 Lumen 场景更新与灯光收集任务、开始 Nanite 可见性帧、启动虚拟贴图流送。

01Visibility Computation可见性计算

line 1729–1837 Async CPU

Determines which objects are visible. BeginInitViews() dispatches parallel CPU tasks for frustum culling, relevance computation, and dynamic shadow setup. GPUScene uploads per-primitive shader data. EndInitViews() waits for all tasks and generates MeshDrawCommands — the pre-built GPU command packets that avoid per-draw CPU overhead.

确定哪些物体可见。BeginInitViews() 派发并行 CPU 任务进行视锥裁剪、相关性计算和动态阴影设置。GPUScene 上传每图元着色器数据。EndInitViews() 等待所有任务并生成 MeshDrawCommands——预构建的 GPU 命令包,避免逐绘制的 CPU 开销。

02Early Z PrePass + Nanite RasterizationEarly Z 预通道 + Nanite 光栅化

line 2069–2128 GPU

Populates the depth buffer before the expensive base pass. The early Z pass writes depth for all opaque geometry, enabling the GPU to reject occluded pixels early (Hi-Z rejection). RenderNanite() then runs Nanite's cluster-based rasterizer (both a software and hardware path) to handle millions of triangles efficiently. After this, a Hierarchical Z-Buffer (HZB) is built for later occlusion queries, SSAO, and SSR.

在昂贵的 Base Pass 前填充深度缓冲。Early Z 通道写入所有不透明几何的深度,让 GPU 能提前拒绝被遮挡像素(Hi-Z 拒绝)。随后 RenderNanite() 运行 Nanite 基于 Cluster 的光栅器(软件和硬件双路径),高效处理数百万三角形。之后构建层次 Z 缓冲(HZB)供后续遮挡查询、SSAO 和 SSR 使用。

Read-only depth optimization: When the early Z pass is complete (bAllowReadOnlyDepthBasePass == true), the base pass binds depth as read-only (DepthRead_StencilWrite). This avoids redundant depth writes and reduces memory bandwidth pressure. 只读深度优化:当 Early Z 完成后(bAllowReadOnlyDepthBasePass == true),Base Pass 以只读方式绑定深度(DepthRead_StencilWrite),避免冗余深度写入,降低内存带宽压力。

03Base Pass — GBuffer WriteBase Pass — GBuffer 写入

line 2599–2635 GPU

The base pass is the heart of deferred shading. Every visible opaque surface runs its material shader and writes results into multiple render targets collectively called the GBuffer. This decouples geometry/material evaluation from lighting — lighting can then be computed in screen-space without re-running material shaders.

Base Pass 是延迟着色的核心。每个可见不透明表面运行其材质着色器,将结果写入统称为 GBuffer 的多个渲染目标。这将几何/材质计算与光照解耦——光照随后可在屏幕空间中计算,无需重新运行材质着色器。

04Shadow Map Rendering阴影贴图渲染

line 2516–2793 GPU Conditional条件执行

Renders depth from each light's perspective to produce shadow maps. In the deferred path (default), this runs after the base pass so Lumen can begin async work earlier. UE 5.x introduces Virtual Shadow Maps (VSM): a single 128K×128K virtual texture atlas where pages are allocated on demand per-light, giving uniformly high shadow resolution regardless of distance.

从每个光源视角渲染深度以生成阴影贴图。延迟路径(默认)中在 Base Pass 之后执行,以便 Lumen 能更早开始异步工作。UE 5.x 引入了虚拟阴影贴图(VSM):一张 128K×128K 的虚拟纹理图集,按需为每个光源分配页面,无论距离远近均提供均匀高精度阴影。

05Lumen GI — Fully Dynamic Global IlluminationLumen GI — 全动态全局光照

line 2583–2763 Async Compute

Lumen provides real-time indirect lighting without baking. It maintains a Surface Cache — a low-res atlas capturing direct lighting on scene surfaces. From this, it traces rays (via Mesh Distance Fields or hardware RT) to gather indirect illumination. DispatchAsyncLumenIndirectLightingWork() launches:

Lumen 提供无需烘焙的实时间接光照。它维护一个表面缓存(Surface Cache)——捕捉场景表面直接光照的低分辨率图集。基于此通过网格距离场或硬件光追进行光线追踪来收集间接照明。DispatchAsyncLumenIndirectLightingWork() 启动:

These dispatches run on the Async Compute queue, overlapping with shadow map rendering on the Graphics queue.

这些调度在异步计算队列上运行,与图形队列上的阴影贴图渲染重叠执行。

06Composition / Decals / SSAO合成 / 贴花 / SSAO

line 2553–2876 GPU

Applies deferred decals (projected onto the GBuffer), computes screen-space ambient occlusion (SSAO), renders opaque velocity for motion vectors (needed by TAA/TSR), copies stencil to a lighting channels texture, and runs Substrate material classification. After this stage the SceneTexture uniform buffer is rebuilt with all available data.

应用延迟贴花(投影到 GBuffer 上)、计算屏幕空间环境遮蔽(SSAO)、渲染不透明速度缓冲用于运动向量(TAA/TSR 需要)、将模板复制到光照通道纹理、运行 Substrate 材质分类。此阶段后 SceneTexture 统一缓冲区用所有可用数据重建。

07Deferred Lighting延迟光照

line 2899–3019 GPU

This is where all dynamic lighting is evaluated in screen space using the GBuffer. The key advantage of deferred shading: lighting cost is proportional to screen pixels lit, not to object count × light count.

所有动态光照在此通过 GBuffer 在屏幕空间中计算。延迟着色的关键优势:光照开销与被照亮的屏幕像素数成正比,而非物体数量 × 光源数量。

08Atmosphere / Fog / Volumetric Cloud大气 / 雾 / 体积云

line 3089–3153 GPU

Renders atmospheric scattering using precomputed LUTs (transmittance, sky-view), exponential height fog with local fog volumes, volumetric fog via a 3D froxel texture with temporal accumulation, and volumetric clouds via ray marching at reduced resolution then upscaling.

使用预计算 LUT(透射率、天空视图)渲染大气散射,指数高度雾与局部雾体积,通过 3D Froxel 纹理加时间累积计算体积雾,以及通过降低分辨率的光线步进再上采样渲染体积云。

09Translucency Rendering半透明渲染

line 3254–3332 GPU

Translucent objects cannot use the deferred path (they don't write to the GBuffer) and must be rendered with forward shading, sorted back-to-front. This stage handles standard translucency, ray-traced translucency, refraction distortion, OIT triangle sorting, hair strand composition, and light shaft bloom. Separate translucency can render at reduced resolution and be upscaled to save cost.

半透明物体无法使用延迟路径(它们不写入 GBuffer),必须用前向着色从后到前排序渲染。此阶段处理标准半透明、光追半透明、折射扭曲、OIT 三角形排序、头发合成和光轴 Bloom。独立半透明可以降低分辨率渲染后上采样以节省开销。

10Path Tracing (Optional)路径追踪(可选)

line 3394–3422 RHI_RAYTRACING

When enabled, RenderPathTracing() replaces the entire rasterization-based lighting pipeline with a reference-quality unbiased path tracer. It accumulates samples across frames until convergence, supporting full participation of atmosphere, volumetric clouds, and decals. Primarily used for offline cinematics and validation.

启用时,RenderPathTracing() 用参考品质的无偏路径追踪器替代整个光栅化光照管线。跨帧累积样本直到收敛,支持大气、体积云和贴花的完整参与。主要用于离线动画和验证。

11Post Processing

line 3507–3596 GPU

The final stage applies the full post-processing chain: TSR (Temporal Super Resolution — UE's in-house temporal upscaler that reconstructs a high-res image from lower-res input using motion vectors and history), Bloom, Lens Flare, Depth of Field, Motion Blur, Tonemapping with Color Grading LUT, and final output. TSR is distinct from TAA in that it explicitly targets super-resolution (e.g., rendering at 50% and reconstructing to 100%).

最后阶段应用完整后处理链:TSR(Temporal Super Resolution——UE 自研时间超分辨率,利用运动向量和历史帧从低分辨率输入重建高分辨率图像)、Bloom、镜头光晕、景深、运动模糊、色调映射 + Color Grading LUT,以及最终输出。TSR 与 TAA 的区别在于它明确以超分辨率为目标(如以 50% 渲染重建到 100%)。

Important: Stages 00–11 describe the CPU-side RDG pass registration order, not actual GPU execution. The RDG compiler reorders, merges, and culls passes based on dependency analysis, and inserts Async Compute work into idle Graphics queue slots on supported hardware. 重要:阶段 00–11 描述的是 CPU 端 RDG Pass 的注册顺序,而非实际 GPU 执行顺序。RDG 编译器根据依赖分析重排、合并和裁剪 Pass,并在支持的硬件上将异步计算工作插入图形队列的空闲槽位。

Key Technologies关键技术一览

Technology技术 Files文件 Description说明
NaniteNanite/Virtual geometry; software+hardware rasterizer with cluster-level LOD虚拟几何;软硬件双路光栅器,Cluster 级 LOD
Virtual Shadow MapsVirtualShadowMaps/128K² virtual atlas with on-demand page allocation128K² 虚拟图集,按需页面分配
LumenLumen/Dynamic GI via Mesh SDF + Screen Probes + Radiance Cache动态 GI:Mesh SDF + Screen Probe + Radiance Cache
SubstrateSubstrate/Layered material system replacing ShadingModel enum分层材质系统,替代 ShadingModel 枚举
Clustered DeferredClusteredDeferredShadingPass.cppFroxel-based batched multi-light shading基于 Froxel 的批量多光源着色
MegaLightsMegaLights/Stochastic sampling + temporal denoising for 10K+ lights随机采样 + 时间降噪,处理万级光源
RDGRenderGraphUtils.hLazy pass registration; auto barriers and resource lifetimes惰性 Pass 注册;自动屏障与资源生命周期
GPUSceneGPUScene.cpp/hGPU-side structured buffer for GPU-driven instance cullingGPU 端结构化缓冲,支持 GPU 驱动实例裁剪
TSRPostProcess/TemporalAA.cppUE's temporal super-resolution upscalerUE 自研时间超分辨率
HairStrandsHairStrands/Strand-based hair with Visibility Buffer基于发丝的毛发渲染,Visibility Buffer

Source Navigation源码导航

Key entry points relative to Engine/Source/Runtime/Renderer/Private/. Use Ctrl+Shift+T in Visual Studio or Rider to jump directly.

关键入口,路径相对于 Engine/Source/Runtime/Renderer/Private/。在 Visual Studio 或 Rider 中用 Ctrl+Shift+T 直接跳转。

Unreal Engine 5.6 · Engine/Source/Runtime/Renderer/Private/DeferredShadingRenderer.cpp
Source analysis · For learning purposes