Luth Engine

July 12, 2026 · View on GitHub

Long-tail wishlist of unscheduled work, grouped by area. Nothing here has a target version or scheduled slot — items move to ROADMAP.md when they become "next." Pulled here when planning a series so we don't lose the seed.

For what's done or planned next, see ROADMAP.md. For per-system architecture references, see arch/. For shipped history, see history/.


Physics maturity

Carried out of the jolt-physics v2.10.x series. Land when project data demands them.

ItemNotes
feat/jolt-cooked-shapesOn-disk persistence via JPH::Shape::SaveBinaryState sidecar/appended chunk keyed by (modelUUID, meshIndex, shapeKind). Physics::ShapeCache key is already content-addressable, so the migration is a "load-from-blob" branch with no engine API changes. Trigger: startup time / RAM from in-memory shape rebuild becomes a complaint.
jolt-character-tier-2CharacterContactListener, dynamic-body push, crouch, swim. Trigger: first project that needs character ↔ dynamic-body interaction.
Per-mesh PhysicsBakeMode overrideCurrently per-model. Add ConvexHullPerMesh / MeshShapePerMesh enum modes when authoring asks for it.
JPH::MutableCompoundShape compositionMultiple Colliders per entity / child-entity composition. Trigger: first model needing multi-part collision (vehicle chassis, articulated prop).
ConvexDecomposition (V-HACD)Non-convex dynamic shapes that can't be a single ConvexHull. Trigger: first non-convex dynamic object that can't be hand-decomposed.
PhysicsMaterial cook parametersActive-edge angle, double-sided, per-triangle user data. Pairs with on-disk cook landing.
PhysicsMaterial-per-shapeCurrently per-body via RigidBody.materialUUID; per-shape is the natural next refinement (different friction on different sides of one body, character-material slot).
Heightfield / terrain shapesJPH::HeightFieldShape for streamed terrain. Trigger: terrain system arrives.
Dynamic mesh updatesSkinned mesh as physics, deformable shapes. Trigger: cloth / soft-body system arrives.
JPH::Shape LOD / decimationDistance-based collider LODs. Trigger: profiler flags it.

Gameplay enablement

ItemDepends onNotes
Scripting (C# via Mono, or Lua)play-mode ✅, jolt-physicsTop priority of this category — deletes the PlayerControllerSystem stub. Big design surface (language pick, embedding, hot-reload, ECS bindings).
Prefab Systemplay-mode ✅, scripting (recommended)Entity templates with override tracking.
Ragdolljolt-physics ✅, animation-controller-v2Bone driven by Jolt body during ragdoll state.

Rendering (beyond planned-epic deps)

ItemDepends onNotes
Full deferred shadingrt-renderer (slim G-buffer lands in Phase A.2)If the forward path hits material-variant complexity limits; the slim G-buffer is already there feeding RT denoising, motion vectors, and SSR-replaced-by-RT-reflections. Full deferred would extend it with albedo + metallic/roughness + emissive + opaque shading model ID.
HZB Occlusion Cullingcompute-gpu-culling ✅, gpu-driven seriesTwo-phase cull pipeline; depth pyramid as compute. Lands as part of the post-rt-renderer gpu-driven series (mesh shaders + GPU-driven culling).
Volume decals (DecalVolume component)forward+ clustered (like lights); scene component like FogVolumeBox-projected decals as a scene component (transform + decal texture), gathered + cluster-binned like lights, applied in the forward PBR pass (the slim G-buffer has no albedo, so classic deferred-decal G-buffer writes don't fit). Key call: the raster==RT stance - raster-only is simple but decals miss RT reflections/GI; RT-correct needs decal projection at ray hits too (novel, the design crux). Deferred from surface-detail (#175, 2026-07-12); UV-space material decals shipped there instead as a complementary node. L/XL.

Removed because absorbed into rt-renderer: Volumetric Fog → Phase A.4 (Wronski full voxel volume), Global Illumination → Phase C (ReSTIR DI + GI), SSR → Phase D.1 (RT reflections supersede screen-space). Shadow frustum-union fit removed because Phase B.3 retires CSM entirely.

rt-renderer Phase A polish & follow-ups

Items deferred from Phase A history files (v3.0.0–v3.0.7). None on critical path; pick up opportunistically or fold into the next polish pass.

ItemSourceTrigger
Salvi K4 variance-clip TAA upgradeimage-quality v3.0.7When RT specular pinpoints surface (Phase D RT reflections)
Mitchell-Netravali TAA post-sharpen passimage-quality v3.0.7After Phase A.5; close remaining TAA blur gap
TAA debug viz ShadeMode (TaaHistory)image-quality v3.0.7Diagnostic convenience
Blackman-Harris weight normalization (sum 0.9956 → 1.0)image-quality v3.0.7Imperceptible drift; opportunistic
AgX exposure-aware curve fit (Filament's expanded range)image-quality v3.0.7If users push pp.exposure past ±2 stops of unity
Slim G-buffer cutout coverageslim-gbuffer v3.0.1When cutout-heavy scene surfaces (foliage / glass cards)
Per-froxel light culling for fogtracked as #134; volumetric-fog-polish v3.0.6When a scene shows residual fog Z-banding
Volumetric per-pass timing in RenderPanelvolumetric-fog-polish v3.0.6Convenience; FrameDebugger already shows pass timings
Sun-fog absorption via world-space LUTtracked as #133; volumetric-fog-polish v3.0.6When god rays through low fog with off-frustum density expose the artifact
IBL ambient multi-direction sampling (currently +Y only)volumetric-fog-polish v3.0.6Matters at fog scales rarely
RG lastReader / first-consumer cross-queue sync (foundational RG change)vulkan-sync-hardening v3.0.11Research-validated: NOT needed for correctness — Fix A's ALL_COMMANDS cross-queue waits cleared every cross-queue hazard. Full UE5-RDG first-consumer placement needs per-pass semaphores. Pick up when ReSTIR/SVGF surfaces concrete cross-queue-WAR cases + tests
N-buffer high-contention cross-queue persistent resourcesvulkan-sync-hardening v3.0.11Relaxes the first-view gA → prev-frame-compute cross-frame wait so frame N+1 graphics overlaps frame N compute. Trigger: profiler flags the stall, or ReSTIR/SVGF history buffers multiply contention
VKTexture creation transition → sync2 + cleaner initial layoutvulkan-sync-hardening v3.0.11The 9 best-practices UNDEFINED→read-only warnings are VKTexture's one-time legacy vkCmdPipelineBarrier creation transitions — benign (GPU-AV-clean, written before read) but flagged. Migrate to VkImageMemoryBarrier2 + transition to write/general first
Small-buffer VMA sub-allocationvulkan-sync-hardening v3.0.11The 6 best-practices vkBindBufferMemory dedicated-alloc hints (<1 MB); tagged-heap by design. VMA pool / sub-allocation if validation cleanliness is wanted
Memory Budget table refresh in arch/rendering-pipeline.mdthis auditStale post-arc; Light UBO removed, GBuffer sizes wrong, volumetric/TAA/IBL/BoneMatrix-dual not listed

Animation maturity (post animation-controller-v2)

ItemDepends onNotes
Animation v3 (DQS, IK, morph targets)animation-controller-v2Beyond state machine + blend trees.

Audio

ItemDepends onNotes
3D Spatial Audioplay-modeOrthogonal; integrate when demo needs it.
Audio asset pipeline.wav / .ogg importer + AssetManager dispatch.

Editor & Tools

ItemDepends onNotes
Asset Streamingcompute-gpu-cullingAsync GPU upload via transfer queue.
Frame Debugger per-view capturegame-panelCapture currently scene-view-only; extend tracked RTs + archive slots to tag by view.
Scene-panel post-process toggleUnity-style toggle to disable bloom/tonemap/vignette for lookdev.
Auto-wire GPUTimerPool into RenderGraphCurrently per-pass insertion is manual.

Profiling / Memory

ItemDepends onNotes
Tracked STL allocators (LH::Vector<T>)Closes the STL gap on MemoryTracker (currently covered only by Tracy hooks).
GPU heap stress testfoundation-testingGPUTaggedPageAllocator V6 overflow + backing-pool growth under sustained pressure. Deferred from foundation-testing because of Vulkan-device setup overhead. CPU side covers the architectural shape.