SplatGarden
Overview
A 3D Gaussian Splatting web viewer for an end-to-end asset-pipeline showcase. The same garden was authored conventionally in Houdini and Unreal, captured at a multi-camera rig, reconstructed back to 3D via COLMAP, trained in parallel by Postshot and Lichtfeld Studio, then served as a single-page web experience powered by Spark on Three.js. Three million Gaussian splats, real-time interactive FX, hand-tracking input, and a 3DGS / USD layer switcher for inspecting alternative representations of the same scene.
The viewer surfaces the pipeline itself as the artefact. Visitors can flip between the splat render and two alternative USD-PointInstancer representations (Billboard and Voxel) of the same scene, and a tech-spec drawer walks through each asset's authoring history with embedded videos and before/after comparisons.
The same garden assets were also deployed in a parallel Virtual Production track — driven through MediaPipe hand-tracking and pushed to an LED Wall via disguise — making this a dual-medium showcase rather than a single deliverable.
Pipeline
Five stages, end-to-end — from conventional DCC authoring to a live splat in the browser. Two Gaussian-Splatting trainers were run in parallel for cross-comparison.
1 · Authoring
Garden assets built in Houdini (procedural foliage, vine generator, VAT-baked animation) and Unreal Engine (set dressing, lighting, hero shaders).
2 · Capture
Multi-camera capture rig recording the Unreal scene from synthetic viewpoints, generating the source imagery for reconstruction.
3 · Reconstruction
COLMAP Structure-from-Motion reconstructs 990 training-camera poses. The same poses are surfaced as toggleable wireframe frustums in the live viewer.
4 · Training (parallel)
Postshot and Lichtfeld Studio trained against the same COLMAP output. Validated against the source pointcloud via XYZ-tool overlay before downstream consumption.
5 · Playback
Spark on Three.js + WebGL 2 renders 3M splats live in the browser. Hosted on GitHub Pages — no install, no plugin.
+ AI Texture Stylization
A custom diffusion pipeline (IP-Adapter + ControlNet + AdaIN) stylises the source textures before re-capture, layering a painterly look over the photographic base.
Houdini Procedural Tools
Grape Hyacinth — Per-part GUI
Authored a procedural grape-hyacinth tool in Houdini with a per-part GUI — artists tune stalk count, bloom density, petal twist. Animation is baked to a Vertex Animation Texture for GPU-cheap playback in Unreal, then scattered via PCG so density follows the planter splines. Hero render uses Unreal's SubsurfaceTwoSidedFoliage shader so backlit petals translucently glow without doubling the geometry. SSS colour and falloff were tuned against the Shot 4B lighting setup.
Houdini procedural tool with per-part GUI.
Final stylised render — VAT in Unreal, PCG scatter, Movie Render Queue.
Vine Generator
Built a vine generator to procedurally create growth patterns that wrap around scene geometry, giving the team a flexible way to drape vines on architecture and props without bespoke modelling per surface. Pairs in Unreal with a UMG-driven world-position-offset shader for procedural growth synchronised to the camera move.
Vine growth animation tied to the Shot 4B interaction beat.
3DGS Capture, Cleanup & Validation
Beyond browser-side playback, the same Gaussian-Splatting assets were captured out of Unreal and validated against the source geometry to surface drift, holes, and alignment issues before relying on the splat downstream.
Pointcloud Overlay Validation
Loaded the trained 3DGS asset alongside its source pointcloud and used an XYZ-tool overlay to compare both representations side-by-side. This catches reconstruction errors that aren't visible from a single viewpoint — drift along occluded faces, holes where coverage was thin, alignment skew from camera-pose error.
Cleanup via GSOPs DBSCAN
Cleaned the trained splat using a USD-voxel pass to isolate clean regions, followed by DBSCAN clustering through a Houdini GSOP workflow to remove stray outlier splats that survived training. The cleanup pass measurably improved the splat's edge density without sacrificing the photographic detail in the interior.
Trained 3DGS for the Shot 4B map — cleaned and overlaid for validation.
Real-time Web Viewer
The viewer ships as a single-page web app — Spark for splat rendering on top of Three.js, GitHub Pages for hosting, no install. A scripted opening camera move (FBX-driven) introduces the scene, then orbit / WASD / hand-tracking takes over for free exploration.
Click-effect FX engine
Eight GPU-shader effects (Scan Line, Dissolve & Reform, Slime Molds, Feather Roots, etc.) authored via a dyno-block modifier on the splat mesh. Click or brush onto the splat to fire effects at world-space hit points.
3DGS / USD layer switcher
Flip between the splat render and two alternative USD-PointInstancer reps of the same scene — Billboard (UsdGeomPlane proto) and Voxel (UsdGeomCube / UsdGeomSphere proto). Reveals the splat's underlying structure.
Hand-tracking input
MediaPipe HandLandmarker mapped onto an Apple-Vision-Pro-style state machine. Pinch = click, drag = orbit, two-hand pinch + spread = zoom / pan. Monochrome 21-landmark overlay.
COLMAP training-camera vis
The 990 training-camera poses toggle on as wireframe frustums in the scene, with optional data-label overlays. Bridges "demo viewer" toward "research debug tool".
Performance preference
Single dial — Battery / Balanced / Max Quality — drives DPR cap, bloom default, particle-system enable. Persisted to localStorage.
Deep-linked viewpoints
URL hash encodes camera pose (#v=px,py,pz,tx,ty,tz). A presenter can email a specific angle of the gazebo and the recipient lands at exactly that view.
Parallel Track — Virtual Production
The same garden assets ran through a parallel Virtual Production deployment — hand-tracking driving in-engine interaction, splats sitting alongside conventional geometry inside Unreal, and the whole composition pushed to an LED Wall via disguise. Both the browser viewer and the VP shoot share the same source pipeline; only the playback medium differs.
MediaPipe → Unreal Interaction
Built the MediaPipe-to-Unreal pipeline as the interaction backbone. Key fixes that took the prototype from "twitchy demo" to "shoot-ready": lerp smoothing on the gesture-driven values to kill jitter from the per-frame MediaPipe callbacks, and a previous-state persistence fix so plant growth retains its state when hands leave the frame instead of snapping back to zero.
MediaPipe-driven daffodil interaction with lerp smoothing and state persistence.
Statue VAT — Hand-driven Animation
Added a statue interaction using Vertex Animation Textures driven by MediaPipe input, so hand-tracked gestures can trigger and scrub the statue animation in engine. Two-handed setup: left hand drives the statue, right hand drives the daffodil — both responsive in the same frame.
Left hand: statue VAT · Right hand: daffodil interaction.
3DGS in Unreal — Volinga + SplatRenderer
Integrated 3DGS assets into Unreal using both the Volinga plugin and SplatRenderer, then layered additional FX on top of the splats in Unreal so the splat content sits inside the scene rather than reading as a flat insert. Cross-checked rendering between the two plugins to compare visual quality and integration overhead.
3DGS in Unreal with additional FX passes — splat sitting inside the scene, not on top of it.
LED Wall Deployment
Final composition pushed to LED Wall via disguise. Pre-rendered MP4 deliverables were transcoded to MOV HAPQ for clean disguise ingest, then a load test validated playback stability before shoot day. The disguise + RenderStream path also drove a live Unreal feed for the interactive moments.
Pilot footage from the LED Wall shoot day, featuring the Niagara interaction system.
Credit
Team: Danci Shen, Itim Kongsakulvatanasook, Yiqi Zheng, Yiyi Long, Yichen Shi, Ben Jones, Xinyi Liang
Special Thanks: Dr. Deborah R. Fowler, Munkhtsetseg Nandigjav, NVIDIA Omniverse and OpenUSD team
Hardware: Rendered on NVIDIA RTX PRO 6000 Blackwell Max-Q Workstation Edition — sincere thanks to NVIDIA.
Splat rendering: @sparkjsdev/spark on Three.js / WebGL 2
Reconstruction: COLMAP
Splat training: Postshot, Lichtfeld Studio
3DGS in Unreal: Volinga, SplatRenderer
Interaction: MediaPipe HandLandmarker
LED Wall: disguise, RenderStream
