Inspiration

We have always been mesmerized by mind-bending sci-fi concepts the dream-within-a-dream architecture of Inception, the localized gravity distortion in Interstellar, and the environmental puzzles of Portal. We wanted to bring these cinematic themes to the web natively, creating an atmospheric, brain-teasing game that bridges the gap between dreams, gravity, and relativity. Furthermore, we wanted to challenge ourselves by utilizing the bleeding-edge technology of 3D Gaussian Splatting, proving that it can be used for deep, interactive gameplay rather than just static image viewing.

What it does

The Paradox is a surreal, two-layered 3D puzzle exploration game built entirely in the browser.

  • Layer 1: The Dream City Paradox Architecture. Players spawn into a fractured, surreal cityscape. Guided by an immersive Heads-Up Display (HUD) compass, they must explore impossible geometry to locate three visual anomalies: the Anomaly Origin, the Rotating Room, and the Clock Courtyard. Reconciling these fractures unlocks a cryptic chamber and a totem that warps them out of the dream state.

  • Layer 2: The Desolate Exoplanet Observatory. A true physics and time-bending puzzle. Players face the Time Dilation Anomaly—a Blue Metronome ticking calmly at 1Hz, and a Red Metronome ticking wildly out of control due to a localized gravity fracture. Players must physically locate, pick up, and carry a glowing "Gravity Dampener." By calculating relational distance, the dampener mechanically alters the localized time dilation of the Red Metronome. The player must find the perfect spatial coordinate to synchronize the pendulums, collapsing the paradox.

How we built it

  • Engine & Physics: Built entirely from scratch using TypeScript and Three.js for lightweight, performant 3D rendering. We implemented custom collision detection using Three.js/Octrees to provide smooth, sub-stepped First-Person Shooter (FPS) movement.
  • Gaussian Splatting: To achieve photo-realistic complex environments without the polygon constraints of traditional meshes, we leveraged the @sparkjsdev/spark library. This allowed us to render dense .spz Gaussian Splats as the visual backbone of our worlds.
  • Game Systems: We engineered a modular architecture featuring a custom InteractionSystem, TriggerSystem, and TransitionSystem. This handles everything from picking up items and mathematically binding them to the camera's local matrix, to managing memory disposal between world loads.
  • The Math: In the Layer 2 puzzle, the time dilation is calculated cleanly inside the render loop using mathematical relativity algorithms. The Red Pendulum's rotation applies a mathematical dampening curve: $Speed = Max(1.0, 10.0 - \frac{20.0}{Distance + 1.0})$. We calculate the 2D radial distance ($XZ$ plane) between the dampener and the anchor to adjust the sine-wave phase rotation of the pendulum in real-time.

Challenges we ran into

  • Splat vs. Collision Synchronization: Because Gaussian Splats are volumetric data and not solid geometry, we couldn't use them for physics. We had to meticulously map invisible glTF collider meshes perfectly over the .spz splats so the player didn't fall through the floor while exploring.
  • The Dilation Mathematics: Getting the synchronization of the pendulums to feel "fair" was incredibly tricky. Initially, vertical height differences between the suspended metronomes and the floor broke our 3D distance calculations, making the puzzle impossible. We had to pivot to calculating a flattened $$\text{Radial projection of } \mathbb{R}^2 \text{ on the } XZ$$ plane to ensure the gravity dampening felt intuitive.
  • Performance Optimization: Maintaining a locked 60 FPS while rendering millions of splats and calculating continuous Octree collisions required aggressive optimization. We had to carefully manage our render loops, sub-step our physics engine, and properly dispose of materials and textures during the seamless world transitions.

Accomplishments that we're proud of

  • Successfully integrating Gaussian Splats into a fully playable, interactive WebGL game, allowing for breathtaking environments that run in a standard web browser.
  • Engineering a completely seamless, cinematic code transition between two vastly different worlds without relying on heavy URL reloads or messy loading screens.
  • The incredibly satisfying "Aha!" moment when the physics math finally clicks, and the Red and Blue metronomes snap into perfect, synchronized harmony.

What we learned

Building "The Paradox" drastically deepened our understanding of WebGL and Three.js matrix transformations. We mastered the complexities of managing game states in a purely web-native ecosystem, bypassing mainstream game engines like Unity or Unreal. Additionally, we learned the heavy mathematical intricacies of simulating physical pendulums, applying localized time-dilation algorithms, and working with the burgeoning field of Gaussian Splatting.

What's next for The Paradox

We believe this is just the foundation for a much larger geometric universe!

  • WebXR Integration: We want to refactor the camera controls to support WebXR, allowing players to put on a headset and physically walk around these spatial anomalies.
  • Deeper Layers: Adding more "Layers" with increasingly complex, physics-breaking mechanics like non-Euclidean portals, reverse-time gravity zones, and M.C. Escher-style gravity flipping.
  • Procedural Audio: Enhancing the atmospheric experience by mapping our render loop mathematics to procedural Web Audio API synthesizers, so the ticking metronomes and cracking ice generate dynamic, real-time spatial audio.

Built With

Share this project:

Updates