Skip to content

Rendering quality roadmap — remaining gap vs Cycles / Unity HDRP #11

Description

@proggeramlug

Comprehensive backlog of rendering improvements, surfaced through cross-engine apples-to-apples comparisons this week (Bloom vs Unity HDRP vs Cycles path-traced, on Intel Sponza and Amazon Lumberyard Bistro). Parking this while I focus on non-rendering work; picking items off this list when I return to rendering.

Reference images (local): /tmp/sponza_bloom.png, /tmp/sponza_unity.png, /tmp/sponza_cycles.png, /tmp/sponza_leadr_3way.png.

Already-shipped session wins are in commits 80d2553, 1bf0fdb, 79ecb85, 65667f2, 805dd2c, 9346a6f, 3b1b955, 3de2bb7, febc257, cc77ee2 (Lagarde spec occlusion, dielectric luma cap, roughness floor, Reinhard soft cap, SSR metals-only, contact-shadow tightening, normal-LOD bias, LEADR-lite with per-mip variance in normal-map alpha, warm ambient grade, sharpen + SSAO radius).


Known remaining gaps vs Cycles (directly observed)

  • Column faint highlight residue — even after spec-occ + luma cap + roughness floor + universal damp, a subtle line traces down smooth dielectric cylinders where the HDR sky reflects at grazing. Cycles kills this via ray-traced visibility. Fix requires visibility-aware IBL (see below).
  • Mortar depth — Cycles shows deep shadows inside brick mortar that the normal map's self-occlusion produces naturally. Our normal-mapped BRDF doesn't self-shadow. Fix: POM or per-material height-map support.
  • Shadow richness under arches — Cycles under-arch shadows are deeper and fall off more naturally. Our 0.15 indirect-shadow floor is a global compromise; a per-pose / per-volume probe would solve it.
  • Last ~5% warmth — Cycles atmosphere still reads a hair warmer; our ambient/fill grade is close but not matched.

Feature categories

A. Visibility-aware IBL (highest impact — closes the column/corner artifacts)

  • Light probe volumes with local visibility (Filament / Unity LPV / DDGI). Per-probe visibility mask so probes don't leak sky radiance into shadowed interiors.
  • Bent normals baked per-mesh or computed at runtime. IBL diffuse samples at the bent normal instead of the shading normal; kills envmap-in-crevice artifacts.
  • Specular occlusion from SSAO — apply the screen-space AO term to IBL specular, not just diffuse. Combine with the existing Lagarde approximation.
  • Screen-space directional occlusion (SSDO) — directional variant of SSAO that tints occluded indirect with the blocked ray's missed radiance.
  • Light probe interpolation via tetrahedral mesh or 3D grid for smooth indirect transitions.

B. Full LEADR / LEAN anisotropic normal filtering

We shipped the scalar variant (σ in alpha). Full LEADR stores 2D covariance.

  • 2D covariance LEADR — bake σ_xx, σ_xy, σ_yy per texel in auxiliary channels/textures. Brushed-metal, cloth, hair, and any directionally-varying material gets proper anisotropic GGX widening.
  • Toksvig-per-light pipeline — run the variance math inside each per-light loop using normal-space covariance.

C. Material / BRDF expansions

  • Anisotropic GGX BRDF — tangent-space anisotropy for brushed metal, hair, sandstone grain (KHR_materials_anisotropy).
  • Clearcoat (KHR_materials_clearcoat) — lacquered wood, car paint, skin cornea.
  • Sheen (KHR_materials_sheen) — fabric, velvet, cloth.
  • Iridescence (KHR_materials_iridescence) — thin-film reflection (soap bubbles, oil slicks, peacock feathers).
  • Proper transmission (KHR_materials_transmission) with refraction, absorption, and thickness (we have a metallic-mirror hack).
  • Volume (KHR_materials_volume) — for glass with colored absorption, gemstones.
  • Subsurface scattering — BSSRDF or screen-space SSS (skin, wax, marble, leaves, jade).
  • Dispersion (KHR_materials_dispersion) — wavelength-dependent refraction (jewelry).
  • Energy-conserving multi-scatter — the Fdez-Aguera approximation we have is good; the full Heitz 2016 form is better for rough metals at grazing.
  • Proper Fresnel for dielectrics at grazing — current Schlick overestimates past θ=80°; Schlick-Bowers or full Fresnel.

D. Shadows (biggest perceptual impact after visibility)

  • PCSS — Percentage-closer soft shadows; penumbra width proportional to blocker-to-receiver distance. Physically-plausible shadow softness.
  • Cascade blending — cross-fade between CSM cascades (we likely have visible cascade seams at the transition distances).
  • Virtual shadow maps (Unity HDRP / UE5 VSM) — page-based shadow atlas for hundreds of shadow-casting lights without a fixed shadow-map-per-light budget.
  • Ray-traced screen-space shadows for spot/point lights (we do this for the sun).
  • Distance field shadows — signed distance fields per mesh, ray-march for soft area-light shadows.
  • Volumetric shadow maps — sun shafts that respect depth properly (current implementation was a screen-space radial blur that didn't respect depth).

E. Global illumination upgrades

  • DDGI (Dynamic Diffuse Global Illumination) — probe grid + per-probe irradiance/distance cubemaps; updated per-frame. Works beautifully for dynamic scenes without baking.
  • SSGI multi-bounce — currently single-bounce. Accumulate over frames via reprojection.
  • Voxel GI (VXGI) — voxelize scene, cone-march for diffuse + specular GI. Good fallback when probes aren't enough.
  • SDF GI — UE5 Lumen's approach. Global SDF per world, cone-traced for GI.
  • Emissive GI contribution — emissive surfaces feeding SSGI (e.g. lamps, neon signs illuminating walls).

F. Area lights

  • LTC area lights (Heitz 2016) — linearly transformed cosines. Physically-correct rectangular/spherical/disk lights that match path-tracer results at a fraction of the cost.
  • Linear lights (tube lights, fluorescent bars).
  • Emissive mesh lights — mesh materials with high emission contribute as area lights.

G. Post-processing

  • Motion blur — camera-motion + per-object velocity-buffer based.
  • Depth of field / bokeh — circle-of-confusion + bokeh shape per-aperture (polygonal blades for character).
  • Proper volumetric sun shafts — ray-march through depth + volumetric density, not screen-space radial blur.
  • Physically-motivated lens flares — Hullin/Kautz style with actual lens element simulation. Optional, very stylized.
  • Color grading LUT pipeline — support .cube files for look-dev.
  • Film grain — monochromatic + chromatic grain, per-pixel hash-noise, helps mask HDR banding.
  • Exposure ramp for transitions — avoid auto-exposure popping when entering a bright / dark area.
  • Dithering before 8-bit final write — breaks up HDR banding in dark skies and smooth gradients.

H. Anti-aliasing improvements

  • Better TAA — YCoCg clipping in sub-pixel space, neighborhood variance clamping, improved subpixel jitter (Halton), better history rejection.
  • TAAU / TSR — temporal supersampling for upscaling; Unity HDRP has it, UE5 TSR is the gold standard.
  • DLAA-style — ML-based temporal supersampling (if we ever ship a HW-ML path).
  • SMAA / FXAA alternatives to TAA for forward-compatible paths.

I. Atmospherics / volumes

  • Physically-based atmospheric scattering (Bruneton 2008 / Hillaire 2020) — Rayleigh + Mie, altitude-dependent density, multi-scattering. Needed for open-world skies and aerial perspective.
  • Volumetric fog with density textures — authorable 3D fog volumes with custom densities and emission.
  • Cloud rendering — ray-marched volumetric clouds, either perf-tier (impostor) or quality-tier (Nubis / UE5-style).
  • Height-fog with noise / wind — gently animated fog for atmosphere.

J. Detail / parallax

  • Parallax occlusion mapping (POM) — heightmap-driven surface self-occlusion. Biggest single win for mortar/brick/cobble depth.
  • Displacement mapping — tessellation-based real surface displacement. Overkill for most, but needed for terrain / hero surfaces.
  • Detail normal maps — secondary high-freq normal blend. Huge for stone, rust, micro-scratches.
  • Detail albedo maps — same for albedo noise (wet asphalt, dirty surfaces).
  • Triplanar mapping — for surfaces without good UVs (terrain, procedural meshes).

K. Texture pipeline

  • BC7 / BC6H compression — we load RGBA8; BC7 quality is indistinguishable at 1/4 size. BC6H for HDR env maps.
  • Virtual texturing / streaming — page-in textures on demand. Cuts VRAM drastically for big scenes.
  • Per-material mip bias — authored hint for texture sharpness.
  • Anisotropy hints per material — override the global 16x for surfaces that need less (avoid over-sharpening of noisy maps).
  • KTX2 + Basis Universal support — GPU-ready compressed glTF asset pipeline.

L. Hair / skin / eyes (character quality)

  • Strand-based hair — Marschner BSDF, dual-scattering for multi-strand transmission.
  • BSSRDF or screen-space SSS for skin (burley / sep-diffusion-profile).
  • Eye rendering — cornea refraction, sclera SSS, iris parallax.
  • Hair alpha sorting — order-independent transparency for hair cards.
  • Face normal maps — per-vertex or Morph-Target aware normal interpolation.

M. Many-light rendering

  • Forward+ / clustered shading — light culling by 3D clusters. Enables hundreds of shadow-casting lights per frame.
  • Light atlas — unified shadow atlas for spot / point / area lights.
  • Shadow caching — re-use prior-frame shadow maps for static geometry.

N. Geometry / LOD

  • Nanite-style virtualized geometry — cluster-based mesh streaming. Big effort; realistic only post-1.0.
  • Traditional LOD chain support — per-mesh LOD swaps based on screen coverage.
  • Mesh shader path — GPU-driven culling + cluster rendering on newer hardware.

O. HW ray tracing (future)

  • RT reflections — glossy reflections beyond SSR (off-screen content).
  • RT shadows — replace CSM for dynamic scenes.
  • RT AO — replace SSAO when HW available.
  • RT GI — gold standard. UE5 Lumen HWRT, Unity HDRP RT path.

P. Bug / correctness fixes

  • Contact shadows extend beyond sun — currently sun-only; extend to the primary bright light or to any shadow-casting light.
  • SSR thickness rejection false positives — still occasionally cuts valid reflections (e.g. reflection of a far object off a close surface).
  • TAA specular ghosting — specular highlights on moving objects drag through history.
  • Alpha-cutout foliage pop at mip transitions — leaves change silhouette between mips; need alpha-to-coverage + coverage preservation.
  • HDR banding at smooth sky gradients — dithering + better tonemap EOTF.

Q. Developer / tooling improvements

  • Render-graph visualizer — debug view of each pass output (GBuffer, SSAO, SSGI, SSR, bloom, tonemap, etc).
  • Material preview sphere — per-material inspector with a spherical preview.
  • Specular probe placement tool — UI for light probe authoring / visualization.
  • PIX / RenderDoc integration — named draw calls, debug markers on every pass.
  • Runtime quality presets — Low / Medium / High / Ultra single-call switch for all the above.

Reference materials surfaced during this session

  • Intel Sponza (2022 photogrammetry): examples/intel-sponza/ — the cross-engine comparison workhorse.
  • Amazon Lumberyard Bistro: examples/bistro/ — exterior street scene, harder loader compatibility, less consistent cross-engine.
  • Cycles harness: tools/cycles_reference/ — path-traced ground truth; ./render.sh --scene sponza --view AgX --samples 256.
  • Unity HDRP harness: tools/unity_reference/ — real-time peer; SCENE=sponza ./render.sh.
  • UE5 harness: tools/unreal_reference/ — scaffolded but Mac-headless is brittle; owner plans to run on Windows.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions