A real-time dynamic global illumination plugin in the style of CryEngine SVOGI: diffuse color-bleeding GI, large-scale ambient occlusion, rough specular, and ray-traced mirror reflections, driven by a camera-centered voxel representation of the scene.
Overview
VoxelGI adds fully dynamic global illumination to Unreal Engine 5 without baking. Every frame the scene is voxelized into a compact 3D representation, lit, and then cone-traced from the GBuffer to produce indirect diffuse lighting, ambient occlusion and specular. It follows the architecture of CryEngine’s SVOGI (Sparse Voxel Octree Global Illumination): the renderer does not ray trace the original triangle scene for diffuse GI, it ray-marches a lit voxel world. Hardware ray tracing is used only where it pays off most: crisp mirror reflections.
What it produces:
- Diffuse GI with color bleeding – light bounces up to four times, picking up the color of the surfaces it reflects from.
- Large-scale ambient occlusion – soft contactHow it works: the per-frame pipeline darkening in corners, recesses and under geometry, derived from the same cone traces.
- Rough specular – a voxel reflection cone whose aperture widens with roughness.
- Ray-traced mirror reflections – real reflection rays through the engine’s material pipeline for smooth surfaces, with true material color.
Requirements & setup
| Setting | Default | Range | Description |
|---|---|---|---|
| Engine | 5.8 | – | Built and pinned against Unreal Engine 5.8. Renderer private headers are re-declared for 5.8 and must be re-synced on engine upgrade. |
| GPU | HW ray tracing | – | Requires hardware ray tracing (inline RayQuery for voxelization; ray-gen for reflections). D3D12 / SM6. |
| Project | Global Illumination | Plugin | Required for specular ray traced surfaces. |
| Anti-aliasing | TAA/TSR | – | Plugin is not ready to work with SMAA of FXAA. Produces sharp reflections. |
Enable the plugin, then open Window > Voxel GI Settings to access all controls. Toggle Enable Voxel GI to turn the effect on or off.


How it works: the per-frame pipeline
Each frame the plugin runs two groups of GPU passes. Voxelization happens right after the ray tracing scene is built; everything else runs as a post-process at BeforeDOF where the GBuffer and scene color are available.
Stage A – Voxelization & light injection (after TLAS build)
- Voxelize – an inline-RayQuery compute shader tests occupancy of an amortized slab of the volume (a few Z-slices per frame) and estimates a surface normal from probe rays. Occupied voxels receive direct sun (shadow ray), sky (visibility ray) and local point/spot lights (shadow ray per light).
- Learn material color – the lit scene color and GBuffer base color are splatted into the volume from the screen, so on-screen surfaces contribute real material colors and all light types to the bounce.
Stage B – Trace & composite (BeforeDOF post-process)
- Mip / pyramid build – a coarse radiance pyramid is generated for wide cones.
- Bounce iterations – for N bounces, N-1 in-frame gather passes propagate light through the volume, each tinted by voxel albedo (this is where color bleeding compounds).
- Cone trace (diffuse) – six cones per pixel gather irradiance and occlusion from the GBuffer surface, at half resolution by default.
- Specular trace – a reflection cone (rough) and a ray request (smooth) are produced at their own resolution.
- Ray-traced reflections – a ray-gen shader traces the smooth-surface requests through the material pipeline and shades the hits with real material color.
- Temporal filter – the traced GI is reprojected against the previous frame and accumulated, with a neighborhood clamp to reject stale history.
- Bilateral upscale & composite – half-resolution GI is upsampled using depth and normal weights, then added to scene color.
The final composite is, per pixel:
SceneColor
+ AO * (Albedo * DiffuseIrradiance * GIIntensity)
+ Fresnel * (ConeSpecular * SpecularIntensity
+ RayTracedSpecular * RayTracedSpecularIntensity)
The voxel volume
The volume is anchored in absolute world space and follows the camera, snapping to a coarse grid so it stays stable while the camera moves inside a cell. When the camera leaves the covered region the volume recenters, which clears and refills it (a brief GI settle). Volume Extent sets the world size it covers and Volume Resolution the voxels per axis; together they set the voxel size, e.g. 2000 cm / 256 = ~7.8 cm voxels.
Update model. By default the GI updates when it needs to – on settings, light or geometry changes, or a manual refresh – and pauses while assets/levels stream. Enable Update GI Every Frame for fully dynamic test scenes, or press Update GI Now in the settings window to force a rebuild.
Sparse voxel octree
By default the fine voxel level is stored sparsely (CryEngine SVOGI layout). A node grid at one eighth of the volume resolution points into atlases of 8x8x8 voxel bricks. Only occupied bricks consume memory, and empty nodes are skipped while cone marching – the core SVO acceleration. Wide cones read a small dense coarse pyramid rebuilt each frame, so distant gathering quality is unchanged.
- Memory. Sparse storage typically cuts the fine-volume footprint several-fold, and the saving grows as resolution rises (a dense 512-cubed volume is over a gigabyte per radiance buffer).
- Speed. The bounce pass runs one thread group per occupied brick instead of over the whole volume – a large reduction in dynamic scenes.
- Brick budget. Brick capacity is fixed per volume (default 16,384). If a scene has more surface than the budget, new regions silently stop filling. Raise Sparse Brick Capacity if GI stops appearing in fresh areas.
Disable Sparse Voxels to fall back to dense volumes (every affected shader is a compile-time permutation, so behavior is identical apart from memory and speed). A faint one-voxel filtering seam can appear at brick boundaries; it is hidden by the cone average
Specular & ray-traced reflections
Specular is split by roughness. Smooth surfaces (roughness below the threshold) get real ray-traced reflections; rougher surfaces use the voxel reflection cone. The two cross-fade at the boundary so there is no
seam. Reflection-ray hits are shaded with the hit surface’s true material base color, lit by the sun (with a shadow ray) plus indirect light gathered from the voxel volume – so reflections stay consistent with the GI.
Specular can be traced at its own resolution, independent of diffuse. Half-resolution specular is cheaper; full-resolution gives crisp mirror detail. The two intensity controls (Specular Intensity for the rough cone and Ray Traced Specular Intensity for the mirrors) let you tune reflection brightness separately.
Near-mirror surfaces fade the voxel cone out because a voxel representation cannot resolve a sharp reflection; those rely on the ray-traced path. If ray tracing is unavailable the reflection contribution is simply
zero.
Debug Views & On-Screen Stats
Debug View Mode replaces the composite with a diagnostic overlay. Use these to verify each stage in isolation, especially mode 1 and 4 to confirm the scene is voxelizing with color.
| Mode ID | Debug View Name | Diagnostic Description |
| 0 | Off | Normal composite view. |
| 1 | Radiance Voxels | Camera raymarch of the lit voxel volume. Crisp voxel cubes; colored surfaces should appear colored. |
| 2 | Diffuse GI | The upsampled diffuse indirect (albedo applied), tone-mapped. Color bleeding should be visible here. |
| 3 | AO | The cone-traced ambient occlusion / visibility term. |
| 4 | Albedo Voxels | Camera raymarch of the learned material-color volume. Verifies albedo capture. |
| 5 | Specular | Cone specular plus ray-traced reflections, tone-mapped. |
Show Debug Text: Draws a performance/status overlay in the viewport: frame time, volume resolution and mode (sparse/dense), bounce count, voxelization slices per frame, the active debug view, and the diffuse and specular trace resolutions (with megapixel counts), and whether ray-traced specular is on. For the authoritative GPU cost of the passes, use the engine’s
Settings Reference
General
| Setting | Default | Range | Description |
| Enable Voxel GI | On | on/off | Master toggle for the viewport pass. |
| Debug View Mode | 0 | 0–5 | Diagnostic overlays (see section 5). |
| Show Debug Text | Off | on/off | Viewport performance/status overlay. |
Volume
| Setting | Default | Range | Description |
| Volume Resolution | 256 | 32–512 | Voxels per axis (rounded to a power of two). Cost scales cubically; prefer lowering Volume Extent over raising this for smaller voxels. |
| Volume Extent | 2000 | 500–100000 | World size covered by the volume, in centimeters. Along with resolution, this sets voxel size. |
| Voxelize Slices Per Frame | 16 | 0–512 | Z-slices re-voxelized per frame (amortized). A full refresh takes Resolution/Slices frames. 0 = whole volume each frame. |
| Sparse Voxels | On | on/off | Sparse node-grid + brick-atlas storage with empty-space skipping. Off = dense volumes. |
| Sparse Brick Capacity | 16384 | 1024–65536 | Maximum allocated 8x8x8 bricks. Raise if GI stops filling new areas in large scenes. |
Injection
| Setting | Default | Range | Description |
| Inject Sun Light | On | on/off | Direct sunlight into occupied voxels via shadow ray. |
| Inject Local Lights | On | on/off | Nearest point/spot lights (up to 16) with shadow rays. |
| Inject Sky Light | On | on/off | Sky light into voxels via an upward visibility ray. |
| Inject Scene Color | On | on/off | Splat lit scene color + material albedo from screen (highest-quality bounce source for on-screen surfaces). |
| Scene Color Blend | 0.25 | 0.01–1.0 | Temporal blend of screen injection. Higher reacts faster, flickers more. |
| Injection Radiance Clamp | 64 | 0–100000 | Max injected luminance (kills specular/emissive fireflies). 0 = off. Raise for physically calibrated sun, or the bounce is silently capped. |
| Voxel Base Color | 0.7 grey | color | Fallback albedo for voxels the camera has never seen. |
Bounces
| Setting | Default | Range | Description |
| Num Bounces | 4 | 1–4 | Diffuse light bounces. 1 = direct only; each extra bounce adds one in-frame gather iteration. |
| Secondary Bounce Intensity | 1.0 | 0.0–1.0 | Strength of the 2nd and later bounces. Keep $\le 1.0$ for energy-conserving falloff. |
Color Bleed
| Setting | Default | Range | Description |
| Color Bleed Saturation | 1.0 | 0.0–8.0 | Saturation of the gathered indirect. 1 = physical; >1 exaggerates the bleed color; 0 = monochrome. |
| Color Bleed Intensity | 2.0 | 0.0–8.0 | How strongly voxel albedo tints bounced light. 0 = grey bounce; 1 = full material color; >1 exaggerates. |
Cone Tracing
| Setting | Default | Range | Description |
| Cone Aperture Degrees | 60 | 20–120 | Diffuse cone half-angle spread. Narrower = sharper, more directional gather. |
| Cone Step Factor | 0.5 | 0.25–2.0 | Step length as a fraction of cone diameter. Lower = higher quality, slower. |
| Cone Initial Offset Voxels | 2.0 | 0.5–8.0 | Start distance along the cone, in voxels (avoids self-occlusion). Lower to catch near-field bleed. |
| Cone Normal Offset Voxels | 1.0 | 0.0–8.0 | Trace-origin offset along the surface normal, in voxels. |
| Cone Max Distance | 0 | 0–100000 | Max cone distance in cm. 0 = half the volume extent. |
| Occlusion Strength | 1.0 | 0.0–4.0 | Scales voxel opacity during accumulation. Higher = darker occlusion. |
Tracing & Filtering
| Setting | Default | Range | Description |
| Half Res Trace | On | on/off | Trace diffuse cones at half resolution and bilaterally upscale. Large speedup, slight softening. |
| Temporal Filter | On | on/off | Reprojected temporal accumulation on the traced GI. |
| Temporal Weight | 0.85 | 0.0–0.97 | History blend weight. Higher = smoother/stabler, slower to react (more smearing on motion). |
| Update GI Every Frame | Off | on/off | Continuously refresh instead of only on invalidation. More expensive; for fully dynamic scenes. |
Specular
| Setting | Default | Range | Description |
| Specular GI | On | on/off | Rough voxel specular reflection cone. |
| Half Res Specular Trace | On | on/off | Trace specular (cone + RT requests) at half resolution. Disable for full-res specular while diffuse stays half-res. |
| Specular Intensity | 1.0 | 0.0–8.0 | Brightness of the rough voxel specular cone. |
| Ray Traced Specular | On | on/off | Material-pipeline reflection rays for smooth surfaces (mirror reflections). |
| Ray Traced Specular Intensity | 2.0 | 0.0–8.0 | Brightness of ray-traced mirror reflections (tuned separately from the cone). |
| Ray Traced Roughness Threshold | 0.3 | 0.05–1.0 | Roughness below this uses ray-traced reflections; above it the voxel cone takes over (they cross-fade). |
Intensity
| Setting | Default | Range | Description |
| GI Intensity | 1.0 | 0.0–20.0 | Overall multiplier on the added diffuse indirect. |
| AO Strength | 1.0 | 0.0–1.0 | How strongly cone occlusion darkens the added indirect light. |
| AO Min Visibility | 0.35 | 0.0–1.0 | Darkest allowed AO multiplier — lifts creases/folds out of pure black. |
| AO Power | 0.5 | 0.1–4.0 | AO response curve. Below 1 softens high-contrast contact occlusion. |
| Sky Light Intensity | 1.0 | 0.0–20.0 | Sky ambient added where cones leave the volume unoccluded. |
Tuning Guide
Match voxel size to scene scale
This is the single most important tuning step. Cones start a voxel or two away from the surface, so if voxels are large relative to your geometry, the near field (contact bleeding, small objects, arch undersides) is skipped and GI looks like uniform fog. For an interior on the order of tens of meters, aim for voxels around 3–8 cm: lower Volume Extent (e.g., 2000 cm) or raise Volume Resolution (256). Lowering extent is free; raising resolution costs cubically.
Match voxel size to scene scale
A post-process plugin cannot subtract light already in scene color. If the level’s SkyLight floods everything with flat ambient, it washes out the voxel bounce and AO. Turn the level SkyLight down (or off) and let the plugin’s Sky Light Intensity supply occluded sky ambient instead—that is what produces the corner darkening and the open-to-covered gradient.
Make color bleeding read
Confirm with debug view 4 that colored surfaces store colored albedo, and view 2 that the indirect carries their tint. To strengthen it, raise Color Bleed Saturation (1.5–2) and use several bounces. Verify the direct light hitting the colored surface is bright enough—bleed is proportional to it.
Control brightness & energy
If interiors slowly brighten or blow out, check that Injection Radiance Clamp is not capping (physically calibrated suns need a high or zero clamp), keep Secondary Bounce Intensity at or below 1, and moderate GI Intensity. If interiors are too dark after matching voxel size, raise Sky Light Intensity or lower Occlusion Strength.
Stability under motion
Smearing while moving the camera is caused by the temporal filter: lower Temporal Weight toward 0.7. Light ‘swimming’ as slabs revoxelize means raising Voxelize Slices Per Frame. Thin bright streaks that persist across angles are usually thin geometry caught in coarse mips: raise resolution or lower Occlusion Strength.
Suggested Starting Points
- Interior (Sponza-like):
Extent 2000,Resolution 256,Aperture 40-45,Initial Offset 1.0,Bounces 3-4, low level SkyLight,Sky Light Intensity ~0.5. - Large Exterior:
Extent 8000-20000,Resolution 256-512,Bounces 1-2, higherVoxelize Slices Per Framefor faster light response. - Sharp Reflections:
Ray Traced Specularon,Half Res Specular Traceoff,Ray Traced Specular Intensityto taste;Roughness Threshold ~0.3. - Performance First:
Half Res Traceon,Half Res Specular Traceon,Bounces 2,Resolution 128-256,Sparse Voxelson.
Performance & Memory
Cost is dominated by three things: the volume size (memory and every whole-volume pass), the number of bounces (one gather + pyramid rebuild each), and the trace resolution (diffuse and specular). Voxelization is amortized over frames, so it is usually cheap.
- Volume memory scales cubically with resolution. Sparse storage removes empty space; the albedo volume is a compact 8-bit buffer. Dense 512 is expensive in both memory and per-pass time—prefer smaller extent over higher resolution.
- Bounces each add a full-volume (sparse: per-brick) gather and a pyramid rebuild. For high resolutions, consider 2 bounces rather than 4.
- Trace resolution: keep diffuse at half res; give specular full res only when you need crisp mirrors.
- Ray-traced reflections cost one ray per specular-resolution pixel (plus a shadow ray and a short gather per hit). Half-res specular roughly quarters that.
Tip: Use Show Debug Text for frame time and the active workload (resolution, bounces, trace sizes), and the console command stat gpu for the exact GPU cost of the VoxelGI passes.
