Wormhole Generator
Interactive 3D wormhole visualisation with real-time GLSL shaders, bloom post-processing, and theme-reactive colours. Renders orbiting crystals, vortex rings, and energy particles in a contained WebGL scene.
OVERVIEW
A real-time 3D wormhole rendered with Three.js and hand-written GLSL. A portal core with an animated fresnel rim sits inside concentric vortex rings, orbiting octahedral crystals, helical dimensional streams and hundreds of energy particles, all resolved through a bloom pass for cinematic light bleed. Six live controls reshape the scene while it runs, four fixed colour variants sit alongside a theme-reactive mode that follows the site palette, and the camera can be orbited by hand or left to drift on auto-orbit. Any configuration can be copied as a link, and the last one is restored on return.
ARCHITECTURE
The rendering stack combines Three.js scene primitives, custom shader materials and an UnrealBloomPass post-processing chain. A TypeScript scene controller owns geometry, uniforms, the animation loop and full resource disposal, while a thin React wrapper handles mount, resize, pointer orbit, visibility and theme updates. Colour resolves through a variant layer: the theme mode reads CSS custom properties from the DOM and remaps them into Three.js colours whenever the palette or light/dark mode changes, while each fixed preset supplies its own light and dark colour set plus a render profile that tunes tone exposure and bloom strength, radius and threshold. Control state lives in its own hook that hydrates from the URL query string, then local storage, then defaults, and mirrors every change back to both behind a debounce. A shared art-quality signal, a scroll-activity monitor and a WebGL circuit breaker throttle or park the renderer under load, and the whole surface mounts lazily behind a deferred-mount boundary with chunk-load retry.
SYSTEM ARCHITECTURE
┌────────────────────────────────────────────────────────────────────────────┐
│ CONTROLS · PRESETS · COLOUR VARIANT · URL QUERY · SAVED STATE │
└────────────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────────────┐
│ WORMHOLE SCENE (Three.js + WebGL) │
├────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ CONTROL STATE │ │
│ │ Query then storage then defaults · presets · clamped params │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ SCENE GRAPH + SHADERS │ │
│ │ ┌──────────────────────────┐ ┌─────────────────────────────┐ │ │
│ │ │ Portal core · fresnel │ │ Vortex rings · crystals · │ │ │
│ │ │ GLSL vertex + fragment │ │ streams · particle field │ │ │
│ │ └──────────────────────────┘ └─────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ COLOUR + THEME RESOLUTION │ │
│ │ CSS custom properties or fixed preset · light/dark profile │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ BLOOM PASS + QUALITY GOVERNOR │ │
│ │ UnrealBloom composite · art-quality tier · circuit breaker │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────────────┐
│ ANIMATED PORTAL + SHAREABLE LINK + PNG EXPORT │
└────────────────────────────────────────────────────────────────────────────┘FUNCTIONALITY
THE SCENE
- A portal core whose animated fresnel rim brightens toward its silhouette, wrapped in a space-distortion envelope
- Concentric vortex rings, orbiting octahedral crystals and helical dimensional streams layered around the throat
- Hundreds of energy particles held in place by base-position offsets with sine oscillation, so the field breathes without drifting away
LIVE CONTROLS
- Six sliders — Rotation, Bloom, Particles, Ring Scale, Crystal Speed and Distortion — applied to the running scene without a restart
- Balanced, Cinematic and Hyperspace presets that jump straight to characterised parameter sets
- Pointer and touch orbit with an auto-orbit mode, plus a PNG capture of the current frame
COLOUR & THEME
- A theme-reactive mode that reads CSS custom properties and remaps them to Three.js colours as the palette or light/dark mode changes
- Four fixed colour variants — Electric Indigo/Amber, Cyan/Coral, Gold/Teal and Magenta/Ice Blue — each with its own light and dark set
- Per-variant render profiles that tune tone exposure and bloom strength, radius and threshold so every palette stays legible
PERFORMANCE & RESILIENCE
- IntersectionObserver and page-visibility lifecycle that parks the render loop when the scene is off-screen or the tab is hidden
- A shared art-quality tier, scroll-activity damping and a WebGL circuit breaker that degrades rather than stalls under load
- Full disposal of geometry, materials and frame buffers on unmount to prevent WebGL context leaks, behind a lazy mount with chunk-load retry
HOW IT WORKS
On mount the React wrapper resolves control state — URL query first, then saved state, then defaults — and hands it to a scene controller that builds the camera, renderer, frame buffers and geometry, then compiles the portal core's vertex and fragment shaders. Each frame the controller advances shader uniforms and particle offsets by delta time, rotates the rings, crystals and streams at their configured speeds, and renders the result through the bloom composite. Colour is resolved separately from motion: in theme mode a DOM observer watches the palette and light/dark attributes and remaps CSS custom properties into Three.js colours in real time, while a fixed variant supplies its own colour set and render profile. Pointer and touch drags orbit the camera, and the camera position is mirrored into the URL on an interval so a specific vantage point can be shared. A frame-rate-aware quality tier, a scroll-activity monitor and an IntersectionObserver together decide whether to render at full quality, damp the loop, or park it entirely, and every control change is clamped to a safe range and written to both the URL and local storage before the next frame.
STEP-BY-STEP GUIDE
- Open the Wormhole tab and let the portal, rings and particle field settle into motion.
- Click, hold and rotate to orbit the camera, or leave auto-orbit running to let it drift on its own.
- Drag Rotation and Crystal Speed to change how fast the throat and its orbiting bodies turn.
- Raise Bloom and Distortion to push the scene from a clean portal toward a cinematic, warped one.
- Adjust Particles and Ring Scale to change the density of the energy field and the spread of the vortex rings.
- Try the Balanced, Cinematic and Hyperspace presets to jump between characterised parameter sets.
- Switch colour variants, or stay on the theme-reactive mode and toggle the site palette to watch the scene follow it.
- Copy the link to share the exact configuration and camera angle, or save a PNG of the current frame.
OUTCOMES
- Delivers an interactive 3D portal scene that gives the portfolio a memorable first impression.
- Lets visitors inspect a cinematic WebGL object rather than only watch a static animation.
- Creates long-running ambient motion that feels polished during browsing.
- Adapts to the current theme so the visual belongs to the surrounding page.