360VIEWER

Engineering technical brief

High-resolution 360° rendering in Unreal Engine 5.8

A validated cubemap-to-equirectangular system for stable 4K and 8K output, plus the architecture and present boundary of the preliminary Dome360Renderer plugin.

Six-face captureSeam-aware assemblyAutomated QA

Validated profileStable

8K8,192 × 4,096
6cube faces
~17 GBtypical VRAM
1.01–1.06×seam ratio

Executive assessment

Correctness comes from coordination, not brute force.

The system treats a panorama as six synchronized perspective cameras, each with explicit orientation, memory, temporal, and initialization rules. Those faces become a 2:1 master, receive finishing in the panorama’s topology, and are accepted only after spatial and temporal QA.

The decisive choices are camera-local quaternion composition, bounded face concurrency, Movie Render Queue high-resolution tiling, deterministic exposure and warm-up, and longitude-wrap-aware post-assembly bloom. The validated presets are conservative on purpose: they exchange some throughput for reproducibility, seam stability, and usable VRAM headroom in foliage-heavy scenes.

Capture + projection

Six ordinary views become one continuous frame.

A cubemap covers the sphere with six 90° rectilinear cameras aligned to the positive and negative axes of the source camera’s local frame. Unreal can render each face through its normal perspective pipeline, including MRQ, Lumen, virtual shadow maps, foliage culling, and post-processing, without shading one extreme equirectangular render target directly.

+X+Y−X−Y+Z−Z
→
2:1Assembly
→
FXWrap bloom
→
QAAdmit / reject

Direction mapping

For normalized output coordinates u and v, the assembler constructs a longitude, latitude, and unit direction. The dominant component selects a cube face; the other components become face-space coordinates. The renderer and assembler must share one tested convention for axes, handedness, texture flips, and pole roll.

λ = 2π(u − 0.5)    φ = π(0.5 − v)    d = (cosφ cosλ, cosφ sinλ, sinφ)
FaceLocal lookLocal upRole
+X(1, 0, 0)(0, 0, 1)Camera-forward
+Y(0, 1, 0)(0, 0, 1)Camera-right
−X(−1, 0, 0)(0, 0, 1)Camera-back
−Y(0, −1, 0)(0, 0, 1)Camera-left
+Z(0, 0, 1)(−1, 0, 0)Zenith; intentional roll
−Z(0, 0, −1)(1, 0, 0)Nadir; intentional roll

Pole-facing cameras have no naturally unique screen-up direction. Their up vectors intentionally choose the roll that makes the zenith and nadir meet the lateral faces in the order expected by the assembler.

Orientation correctness

Face offsets belong in camera-local quaternion space.

Let qcamera be the animated camera orientation and qface the fixed local rotation for one cube face. Under the active-rotation convention used here, the world orientation is:

qworld-face = normalize(qcamera × qface-local)

In Unreal, the implementation should be verified by vectors rather than by memorized multiplication-order wording: rotating the canonical forward and up vectors by the final quaternion must produce the same vectors as first choosing the face-local look/up pair and then rotating those vectors by the animated source camera. Once that identity holds for all six faces, source pitch, yaw, and roll propagate uniformly to the cube.

Why Euler addition fails

Adding 90° offsets to a Rotator is not composition. Three-dimensional rotations do not commute, and the axes represented by Euler components change as earlier rotations are applied. The error becomes obvious at the zenith and nadir: ±90° pitch sits at the Euler singularity, where yaw and roll become coupled. If the source camera is already pitched or rolled, the pole offset is applied about a world or intermediate axis instead of the camera-local right axis. The cap can twist, flip, or detach from the four lateral faces while level-camera tests still look correct.

Validated raster structure

Master resolution determines the retained face core.

For a 2:1 master of width W and height W/2, the validated face core is N = W/4. Six source squares jointly sample solid angle; they are not packed directly into the output raster, so their total source pixel count is intentionally larger than the equirectangular frame.

MasterOutput rasterCore face5% guarded sourceGuard / side
4K4,096 × 2,0481,024²≈ 1,076²≈ 26 px
8K8,192 × 4,0962,048²≈ 2,152²≈ 52 px

The guarded sizes are rounded to practical even dimensions. At constant angular pixel density, a 1.05 linear guard implies a field of view near 92.8°. Assembly retains the central 90° core. Overscan lets view-space filters converge before the crop edge, but it cannot make opposite cube edges or the 0°/360° longitude seam visible to one per-face filter.

Work partitioning

Face batching and MRQ tiling solve different problems.

MechanismWhat it dividesPrimary effectInvariant
Cube-face batchingSix camera views into jobsControls live view contexts, retry scope, and concurrencyEvery face stays a full 90° view
MRQ high-resolution tilingOne face raster into 2×2 or 3×3 tilesReduces raster-scaled render targets and post buffersFace count and delivery resolution do not change

A 2×2 MRQ setting renders four sub-frusta of one face and stitches them back into that face. It does not mean two cube faces. Tiling reduces scene color, depth, velocity, G-buffer, history, and post-process allocations that scale with raster area. Textures, foliage instance data, shadow resources, Lumen scene data, and ray-tracing acceleration structures can remain resident, so memory does not fall by the square of the tile count.

Validated hardware presets

Concurrency is deliberately asymmetric by GPU and resolution.

GPUMasterFaces / jobMRQ tilesTexture pool
RTX 50904K2 opposing2 × 26,000 MB
RTX 50908K12 × 27,000 MB
RTX 40904K12 × 24,500 MB
RTX 40908K13 × 35,000 MB

The 5090 recovers throughput at 4K by scheduling two opposing faces per job. Every 8K preset returns to one face per job. The 4090 remains at one face per job at both resolutions and uses a finer 3×3 split at 8K. The texture-pool values constrain streaming residency; they are not total VRAM limits.

VRAM findings

The final 8K profile roughly halved practical pressure.

The initial non-tiled, more-concurrent 8K approach nearly exhausted a 32 GB RTX 5090. The final foliage-heavy 8K configuration generally used about 17 GB, leaving roughly 15 GB of headroom for scene variation, driver allocations, shader transitions, encoding, and transient peaks.

Face concurrency

Each live face can own full render targets, visibility state, histories, and post-process intermediates.

Lumen histories

Screen probes, radiance state, denoising, and temporal state are view- and resolution-sensitive.

Foliage instances

Dense transforms, culling data, wind deformation, material variety, and alpha overdraw remain expensive.

RT acceleration

BLAS/TLAS storage and updates can dominate when millions of animated leaf and branch instances are admitted.

Textures + shadows

High-resolution mips compete with virtual shadow map pages and per-light resources outside the tile-scaled buffers.

Post-processing

Scene color, depth, velocity, bloom, denoisers, AA, and tile overlap create multiple large surfaces.

Foliage-heavy lighting policy

ProfileLumenStandalone RTFoliage in RTASIntent
FoliageSoftwareDisabledExcludedMaximum stability and headroom
BalancedSoftware; optional hardwareExplicitExplicitHigher fidelity when scene and memory permit
CustomExplicitExplicitExplicitExpert control with no hidden inheritance

Hardware Lumen and standalone ray-traced reflections, shadows, or ambient occlusion are separate choices. Balanced may retain optional hardware Lumen without silently enabling every standalone effect or rebuilding a massive foliage acceleration structure.

Temporal strategy

Initialize histories; do not spread one output instant across time.

ControlValueReason
Spatial samples4Improves per-frame sampling without shifting the delivery time
Temporal samples1Avoids face/tile motion divergence and accumulation mismatch
HistoryPer tile enabledKeeps state aligned with each sub-frustum and raster extent
Motion blurRestrainedLimits boundary disagreement and does not hide foliage defects
Engine warm-up64 framesSettles streaming, Lumen, shadows, particles, and simulation
Render warm-up48 framesBuilds view-specific render histories before capture
Handle1 frame / faceAbsorbs the residual first-capture transient and is trimmed

The six faces and MRQ tiles are independent projections. A screen-space sample on one face has no valid pixel correspondence on its neighbor, and history from one tile can represent another sub-frustum or overlap region. Reuse produces ghosts, unstable Lumen convergence, exposure drift, and seams that change with motion. High-frequency foliage amplifies the risk: thin alpha edges, subpixel branches, wind deformation, and changing occlusion generate legitimate temporal energy that multi-sample accumulation can smear or resolve differently on adjacent faces.

Handle-frame arithmetic

For a 20-second clip at 24 fps, the manifest and assembler must agree on all three counts:

20 s × 24 fps = 480 delivery frames
1 handle + 480 delivery = 481 source frames per face
6 faces × 481 = 2,886 source PNGs

Delivery frame 0 uses source frame 1 from every face; source frame 0 is discarded independently. Counts and timestamps must be recorded per face so a retry cannot introduce a one-frame phase error on one side of the cube.

Image formation + delivery

Panorama topology governs bloom and exposure.

Two-stage bloom

The validated forest profile uses restrained Unreal bloom at intensity 0.10 and threshold 2.0 while the faces retain their 5% guards. After equirectangular assembly, a second bloom pass uses strength 0.22 and a 64 px radius at 4K or 128 px at 8K. Doubling the radius preserves roughly the same angular footprint.

Per-face bloom cannot guarantee continuity. Its convolution sees only one perspective image; adjacent energy is absent or oriented differently, and cropping removes the outer guard. The equirectangular left and right edges are neighbors on the sphere but distant in ordinary image memory. The finishing kernel therefore samples longitude modulo image width so light crossing 0°/360° contributes on both sides. Latitude uses an intentional pole policy rather than wrapping north to south.

Fixed exposure

The forest profile locks exposure at 5.0 with exposure bias −5.5. Both values are identical for every face, tile, warm-up, and frame. Independent auto-exposure would meter a sun-facing view, shaded forest view, zenith, and nadir from very different luminance distributions. Those differences become stable face seams or temporal pumping that geometric reprojection cannot repair.

HEVC Main10 delivery

Final video is HEVC Main10 through NVENC at 24 fps, approximately CQ17 with the P7 preset. Main10 improves gradient precision and reduces banding risk; it does not itself define an HDR deliverable. HDR also requires an HDR output transform, appropriate primaries and transfer function, correct matrix/range signaling, and any necessary mastering metadata. Main10 can carry excellent 10-bit SDR.

Automated QA

Every frame is analyzed; seams and motion are normalized locally.

Full assembled frames are reduced to a practical analysis resolution so every frame can be checked rather than sampled. Downscaling preserves the broad seams, pole defects, clipping, exposure shifts, and temporal discontinuities that determine admission.

MetricComputation conceptDefect class
Mean luminanceFull-frame luma meanExposure drift or gross failure
Highlight / near-whiteCoverage above configured thresholdsBloom growth, clipping, range errors
Crushed blackCoverage below the near-black thresholdLost shadow detail
Left/right wrap ratio0°/360° difference ÷ local gradient baselineLongitude seam
Cube-boundary ratioProjected boundary energy ÷ parallel local baselineFace crop, orientation, light, or history seam
Zenith/nadir spreadRobust statistics in high-latitude bandsPole pinching, rotation, or unstable shading
Pole-wrap deltaCircular horizontal differences near the polesLongitude discontinuity amplified by projection
Frame deltaMean absolute first-order differenceLarge one-frame visual change
Temporal accelerationFirst-difference change, full frame and blocksPop, intersection, missing frame, or state reset

A seam ratio near 1.0 means the tested boundary is no stronger than a comparable nearby gradient. A tree trunk crossing a face boundary should not fail merely because it contains contrast; it should fail when the boundary is disproportionately strong relative to the same local content.

Independent temporal analyzer

D1t = Yt − Yt−1    D2t = D1t − D1t−1

First-order differences measure motion and appearance change. Second-order differences measure acceleration of that change. The analyzer evaluates a low-frequency signal and a detail residual, then aggregates second-order energy over spatial blocks. Block-level p95 and maximum values keep a localized intersection or missing fragment from disappearing inside a calm frame mean.

Each value is divided by a robust rolling temporal baseline. Local ratios are more useful than absolute deltas in fast foliage motion: wind, camera speed, leaf density, shutter, and contrast can make a healthy shot produce large raw differences. A local baseline rises during sustained motion but still exposes an isolated acceleration several times stronger than its neighbors.

1.01–1.06×median cube-boundary ratios across six final clips
1.10–1.18×worst local temporal scores across the final set
0%crushed-black coverage in all six final clips

Preliminary plugin boundary

The plugin is the declarative control plane — today.

The UE 5.8 C++ editor plugin uses UDeveloperSettings. It exposes RTX 5090, RTX 4090, and Custom hardware choices; 4K, 8K, and Custom resolutions; and Foliage, Balanced, and Custom scene profiles. Advanced settings remain transparent rather than hiding the interactions that determine stability.

Work partitioning

MRQ tile grid, face batching, job structure, VRAM and texture-pool budget

Sampling

Spatial/temporal samples, per-tile history, warm-ups, handle frames, motion blur

Lighting

Software/hardware Lumen, standalone ray tracing, foliage participation in RTAS

Image formation

Overscan, Unreal bloom, wrap bloom, fixed exposure, exposure bias

Delivery

Frame rate, HEVC Main10, NVENC quality, paths, naming, and cleanup policy

Reproducibility

A resolved JSON recipe containing explicit effective values after preset inheritance

The resolved recipe is the architectural center. Preset names are user input; workers should consume explicit, versioned effective values. A complete recipe includes frame range and rate, face convention, quaternion policy, core/guard dimensions, tiling and batches, warm-ups and handles, lighting switches, exposure and bloom, encoder signaling, expected artifact counts, and cleanup scope.

Recommended next milestone

Make the resolved recipe drive a resumable worker pipeline.

  1. 01
    Resolve + validate

    Validate schema, freeze paths and frame math, and compute the expected job graph.

  2. 02
    Isolated capture worker

    Launch UE/MRQ outside the editor so crashes, resets, and memory leaks cannot corrupt orchestration state.

  3. 03
    Resumable manifests

    Track every clip, face, frame, dimension, timestamp, checksum, and state: pending, running, rendered, verified, or failed.

  4. 04
    Assembly + encode

    Trim handles, crop cores, convert projection, apply wrap bloom, and encode Main10 with explicit color signaling.

  5. 05
    Automated QA report

    Emit machine-readable metrics and concise human evidence; block publication on rejection.

  6. 06
    Publish

    Publish only QA-approved masters and reports, then verify the destination is readable.

  7. 07
    Transactional cleanup

    Plan deletion only for recipe-owned intermediates and commit it after durable publication verification.

RESOLVED → CAPTURING → SOURCE_VERIFIED → ASSEMBLED → QA_PASSED → PUBLISHED → CLEANUP_COMMITTED

Failure at capture returns only the affected face/job to pending. Assembly failure preserves verified sources. QA failure preserves both sources and the candidate master. Cleanup is a separate commit, never an unconditional epilogue. That state model makes a 2,886-file clip recoverable without rerendering successful faces and makes deletion auditable.