Architecture Overview — A Hybrid Tracing System架构概览 — 混合追踪系统

Lumen is UE's fully dynamic global illumination system. Unlike baked lightmaps, it reacts to moving lights, geometry changes, and sky light at runtime. It achieves this through a hybrid tracing architecture that selects the cheapest tracing method for each situation, trading precision for performance at different scene scales.

Lumen 是 UE 的完全动态全局光照系统。与烘焙光照贴图不同,它在运行时对移动的灯光、几何体变化和天空光做出反应。它通过混合追踪架构实现这一目标,为每种情况选择最经济的追踪方法,在不同场景尺度上用精度换取性能。

Per-frame rendering pipeline: 1. Update Surface Cache (LumenSceneRendering.cpp) → Re-capture changed cards with direct lighting 2. DispatchAsyncLumenIndirectLightingWork() [Async Compute] ├── RenderLumenScreenProbeGather() ← diffuse GI │ ├── Screen Space Radiance Cache (nearest occluders) │ ├── Mesh SDF Tracing (medium range) │ └── Hardware Ray Tracing (optional, long range) ├── RenderLumenReflections() ← specular GI └── (optional) RenderLumenReSTIRGather() ← higher quality GI 3. RenderDiffuseIndirectAndAmbientOcclusion() → Composite Lumen GI into scene color

Surface Cache — The Indirect Lighting Foundation表面缓存 — 间接光照基础

The Surface Cache is Lumen's most critical component. It maintains a collection of mesh cards — low-resolution 2D atlases that approximate the direct lighting on the surfaces of nearby objects. Think of it as a dynamic, simplified "fake GBuffer" for the scene from multiple directions.

表面缓存是 Lumen 最关键的组件。它维护一组Mesh Cards——近似附近物体表面直接光照的低分辨率 2D 图集。可以把它想成场景从多个方向的动态简化"伪 GBuffer"。

For each object, Lumen generates 6 cards (one per major axis direction, like a cube map projection). Each card stores: radiance, direct lighting, albedo, normal, and emissive — all at low resolution (typically 32×32 to 256×256 texels per card). This surface cache is updated incrementally each frame, prioritizing cards that changed (new light, geometry, or stream-in).

对于每个物体,Lumen 生成 6 张 Card(每个主轴方向一张,类似 Cube Map 投影)。每张 Card 存储:辐射率、直接光照、反照率、法线和自发光——均为低分辨率(通常每 Card 32×32 到 256×256 纹素)。此表面缓存每帧增量更新,优先处理已变化的 Card(新灯光、几何体或流入)。

// Card capture is driven by UpdateLumenScene() → LumenSceneCardCapture.cpp
// Priority system: recently changed cards get higher recapture priority
bool FLumenSceneData::RecaptureCardPage(
    const FViewInfo& MainView,
    FLumenCardRenderer& LumenCardRenderer,
    // ...)  — adds pages to LumenCardRenderer.CardPagesToRender

// Direct lighting is injected into the surface cache via compute shaders
// (LumenSceneDirectLighting.cpp) — all dynamic lights in the scene illuminate cards
// Result: each card texel has accurate direct radiance from all lights

// Radiosity bounces are computed separately (LumenRadiosity.cpp)
// — each card texel shoots rays into the Surface Cache to accumulate indirect light

Tracing Decision Tree — When Does Lumen Use What?追踪决策树 — Lumen 何时使用什么?

The core tracing decision is made in AnyLumenHardwareRayTracingPassEnabled() (Lumen.cpp:128) and related functions. The selection depends on hardware support, CVar settings, and scene conditions:

核心追踪决策在 AnyLumenHardwareRayTracingPassEnabled()Lumen.cpp:128)及相关函数中做出。选择取决于硬件支持、CVar 设置和场景条件:

For each screen probe ray: Is HWRT available AND r.Lumen.HardwareRayTracing=1? ├── YES → UseHardwareRayTracing() == true │ └── Full scene HWRT via TLAS (most accurate) │ BUT: expensive, requires DXR/VK_RT └── NO → Software tracing path: ├── Screen Space Radiance Cache (SSRC) │ ← fast, only sees what camera sees, range ~2m │ ├── Mesh SDF Tracing (Global Distance Field) │ ← traces rays through per-object signed distance fields │ ← range: several hundred meters, ~90% of samples hit here │ ← misses thin geometry, no LOD transitions visible │ └── Surface Cache fallback ← ray samples nearest card texel for far hits ← unlimited range but low precision

Screen Probes — Sparse Diffuse GI Sampling屏幕探针 — 稀疏漫反射 GI 采样

Screen Probes are the output stage of Lumen GI. Instead of computing indirect lighting at every pixel (which would be prohibitively expensive), Lumen places a sparse grid of probes on visible surfaces (one probe every ~8×8 pixels). Each probe traces many rays into the scene, samples the Surface Cache for hits, and accumulates irradiance. The probe results are then interpolated back to full resolution for every pixel.

屏幕探针是 Lumen GI 的输出阶段。Lumen 不在每个像素处计算间接光照(这成本过高),而是在可见表面上放置稀疏的探针网格(每约 8×8 像素一个探针)。每个探针向场景追踪多条光线,对命中处采样表面缓存,并累积辐照度。然后将探针结果插值回每个像素的完整分辨率。

Temporal reprojection accumulates probe results across frames for higher quality — newer frames refine with fewer rays, older frames provide variance reduction. The screen probe gather is implemented in LumenScreenProbeGather.cpp (the largest single file in the Lumen system at 140K).

时间重投影跨帧累积探针结果以提高质量——新帧用更少光线细化,旧帧提供方差减少。屏幕探针采集在 LumenScreenProbeGather.cpp(Lumen 系统中最大的单个文件,140K)中实现。

Radiance Cache — Long-Range Indirect Lighting辐射缓存 — 长距离间接光照

The Radiance Cache extends Lumen's reach beyond what the Screen Probes can see. It's a world-space 3D cache of probes placed at logarithmically spaced distances from the camera. Each probe in the Radiance Cache stores irradiance from all directions. Screen Probes that trace rays beyond mesh SDF range fall back to sampling the Radiance Cache for long-range indirect illumination — this is how sky light, distant fog, and inter-room bounce lighting is approximated.

辐射缓存将 Lumen 的覆盖范围扩展到屏幕探针所能看到的范围之外。它是一个以对数间距距离摄像机放置的世界空间 3D 探针缓存。辐射缓存中的每个探针存储所有方向的辐照度。追踪超出 Mesh SDF 范围的屏幕探针回退到采样辐射缓存以获取长距离间接照明——这就是天空光、远处雾以及房间间反弹照明的近似方式。

Lumen ReflectionsLumen 反射

Lumen Reflections replaces SSR for specular indirect lighting. Like diffuse GI, it uses a hybrid tracing strategy. For rough surfaces the reflection rays are wide-cone and can be approximated cheaply with the Surface Cache. For mirror-like surfaces, rays must be traced precisely — using either HWRT or software SDF tracing. Reflections are denoised with a temporal reprojection filter that handles the variable ray length inherent to specular tracing.

Lumen 反射替代 SSR 用于镜面间接光照。与漫反射 GI 一样,它使用混合追踪策略。对于粗糙表面,反射光线是宽锥形的,可以用表面缓存廉价近似。对于镜面,光线必须精确追踪——使用 HWRT 或软件 SDF 追踪。反射通过处理镜面追踪固有的可变光线长度的时间重投影滤波器降噪。

Async Compute Integration异步计算集成

// Lumen.cpp:72 — async compute availability check
bool Lumen::UseAsyncCompute(const FViewFamilyInfo& ViewFamily)
{
    bool bUseAsync = GSupportsEfficientAsyncCompute
        && CVarLumenAsyncCompute.GetValueOnRenderThread() != 0;
    
    if (Lumen::UseHardwareRayTracing(ViewFamily))
    {
        // HWRT async requires platform support for async RT dispatch
        bUseAsync &= GRHIGlobals.RayTracing.SupportsAsyncRayTraceDispatch
                  || Lumen::UseHardwareInlineRayTracing(ViewFamily);
    }
    return bUseAsync;
}

// When async compute is active:
// Surface Cache lighting runs on Graphics queue
// Screen Probe gather + Reflections run on Async Compute queue
// → These overlap on the GPU with shadow map rendering
// → Net effect: ~15-20% frame time reduction on console/high-end PC

Performance Tuning性能调优

CVarEffect效果
r.Lumen.DiffuseIndirect.Allow=0Disable Lumen GI entirely (use with static lighting)完全禁用 Lumen GI(与静态光照配合使用)
r.Lumen.Reflections.Allow=0Disable Lumen reflections, fall back to SSR禁用 Lumen 反射,回退到 SSR
r.LumenScene.SurfaceCacheResolutionScale surface cache resolution (0.5 = half res, big savings)缩放表面缓存分辨率(0.5 = 半分辨率,节省大量开销)
r.Lumen.ScreenProbeGather.ScreenSpaceReconstructionKernelRadiusProbe interpolation radius — higher = smoother but more blurry探针插值半径——越高越平滑但越模糊
r.Lumen.HardwareRayTracing=0Force software SDF tracing even on RT-capable hardware即使在支持 RT 的硬件上也强制使用软件 SDF 追踪
r.Lumen.AsyncCompute=1Enable async compute overlap (requires efficient async compute support)启用异步计算重叠(需要高效异步计算支持)

Lumen Limitations & Known IssuesLumen 限制与已知问题

Source Navigation源码导航

Unreal Engine 5.6 · Engine/Source/Runtime/Renderer/Private/Lumen/
Source analysis · For learning purposes