Interactive Gaussian Splat landing page with mouse-driven displacement effects. Hover over the scene to disintegrate and color-shift splats in real time.
Built with Three.js + Spark.js (Gaussian Splat renderer) + a custom GLSL vertex shader for per-splat displacement.
npm install
npm run devOpens at http://localhost:5173. Move your cursor over the scene to see the effect.
- A full-viewport canvas renders a Gaussian Splat scene (
.spzfile) via Spark.js - An invisible collider mesh (
.glb) sits behind the splats for mouse raycasting - When the cursor moves, a ray is cast from the camera through the mouse position
- Where it hits the collider, an Ethereal Volume (invisible sphere) follows
- A custom vertex shader checks each splat's distance to the volume center
- Splats inside the radius are displaced (moved) and color-shifted per frame
- The radius scales automatically based on distance from camera (small close, larger far)
src/
main.js — App entry: renderer, camera, input, render loop, GUI controls
ethereal.js — EtherealVolume class, uniform bridge, GLSL vertex shader (657 lines)
styles.css — Full UI styling (loader, overlay, vignette, lil-gui theme)
public/assets/
scene.spz — Gaussian Splat model
collider.glb — Invisible raycasting mesh (must match splat geometry)
index.html — Canvas + overlay markup
vite.config.js — Vite build config
All tunable parameters live in the CONFIG object at the top of src/main.js:
| Key | Default | Description |
|---|---|---|
fov |
87 |
Field of view (degrees) |
position |
[0.04, 0.85, 0.98] |
Camera XYZ position |
target |
[-0.53, 1.99, -0.53] |
Look-at target |
| Key | Default | Description |
|---|---|---|
radius |
1.1 |
Sphere radius when close to camera |
radiusFar |
2.5 |
Sphere radius when far from camera |
feather |
0.45 |
Edge softness (0 = hard, 0.99 = very soft) |
pattern |
4 |
Displacement pattern (see below) |
intensity |
0.5 |
Effect strength multiplier |
amplitude |
0.16 |
How far splats move |
frequency |
0.1 |
Pattern detail frequency |
speed |
3.6 |
Animation speed |
| ID | Name | Description |
|---|---|---|
| 0 | Sine Drift | Gentle sinusoidal waves |
| 1 | Cubic Warp | Cubic distortion |
| 2 | Spiral Vortex | XY rotation spiral |
| 3 | Breathe | Radial pulse in/out |
| 4 | Turbulence | Per-splat random oscillation |
| 5 | Shatter | Outward explosion / disintegration |
| 6 | Spiral Flat | XZ horizontal spiral |
| 7 | Ripple | Concentric waves |
| Key | Default | Description |
|---|---|---|
colorShift |
1.0 |
Color change strength (0-1) |
colorMode |
0 |
0=Tint, 1=Override, 2=Desaturate, 3=Rainbow, 4=Emissive |
tint |
[0.65, 0.75, 1.0] |
Tint color (RGB, used in mode 0) |
brightness |
10.0 |
Emissive brightness (used in mode 4) |
colorOverride |
[1.0, 0.3, 0.1] |
Override color (used in mode 1) |
alphaFlicker |
1.0 |
Opacity flicker amount (0-1) |
| Key | Default | Description |
|---|---|---|
centerLerp |
8.0 |
How fast the volume follows the mouse (higher = snappier) |
intensityFade |
4.0 |
Fade-out speed when cursor leaves |
intensityRise |
6.0 |
Fade-in speed when cursor enters |
A lil-gui panel appears in the top-right corner with real-time controls for all effect parameters. The camera uses standard Three.js OrbitControls (drag to rotate, scroll to zoom, right-click to pan).
Click Export Settings in the GUI to copy the current camera position, target, and all volume/color/renderer settings to your clipboard as JSON. Paste the result into CONFIG in main.js to persist your changes.
- Replace
public/assets/scene.spzwith your Gaussian Splat file - Replace
public/assets/collider.glbwith a matching invisible collider mesh- The collider should roughly match the splat's geometry so raycasts hit the right surfaces
- It's placed on layer 2 (invisible to camera) and used only for raycasting
- Adjust
CONFIG.cameraposition/target to frame your new scene - Use the GUI + OrbitControls to find the right angle, then Export Settings
- Three.js v0.180 — WebGL renderer, camera, raycasting
- Spark.js v2.0-preview — Gaussian Splat rendering (SPZ format)
- lil-gui — Runtime parameter controls
- Vite v6 — Dev server and build
npm run build # Production build → dist/
npm run preview # Preview production build locally