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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions