A modular 3D open-world browser game set in Neo Valley — ginkgo groves, retro-futuristic chrome spires, a living day/night cycle, and 20 spirit lights lost across the map. Built entirely in vanilla Three.js, no game engine.
380 instanced ginkgo trees with fan-shaped leaf geometry — ~9,900 individual leaf fans in autumn gold and chartreuse. Golden leaves drift down around you during the day.
The Aurora Spire — a chrome tripod tower with a glass saucer crown, neon rings, and a pulsing beacon. Six glass dome habitats, a monorail ring with an orbiting tram pod, and three relay pylons across the map.
A custom sky shader with a real sun disc, corona glow, and low-angle atmospheric haze. The sun moves on a 5-minute cycle. Clouds drift, stars fade in at dusk, and city windows light up at night.
ACES filmic tone mapping, 4K shadow maps with normal bias, PBR MeshStandardMaterial throughout, and procedurally generated detail + roughness textures for close-up ground realism.
Water is a subdivided plane with vertices displaced by three overlapping sine waves every frame. Normals recomputed live so the PBR material produces real sun glints across the surface.
Hold Space while falling to deploy a paraglider and drift off cliff edges. Sprint drains a stamina wheel; hit a relay pylon to recharge. Gliding also drains stamina, turning red when exhausted.
16,000 instanced grass blades with a custom GLSL vertex shader that drives per-blade sway based on world position and time — no texture, pure geometry and shader math.
Glowing orbs scattered across the map — some near relay pylons to reward exploration. Each has a point light, a pulsing halo, and bobs on a sine curve. Collect all 20 to restore the valley.
Every system exposes init(ctx) and update(ctx).
They never import each other's internals — communication happens only through
the shared ctx object. Adding a new system means writing one file and
registering two lines in main.js.
| Module | Responsibility | Key exports / ctx contract |
|---|---|---|
| config.js | All tunables single source | World size, speeds, counts, day length — change here, everything updates |
| noise.js | Procedural math pure | hash, fbm, terrainHeight, makeNoiseTexture, scatterSpots |
| engine.js | Renderer + lighting rig | ctx.scene, ctx.camera, ctx.renderer, ctx.sun, ctx.hemi |
| sky.js | Sky dome, stars, clouds, day/night | ctx.time · { timeOfDay, sunUp, duskAmt, night } |
| terrain.js | Heightmap mesh + biome colors | Reads terrainHeight, writes PBR terrain mesh to scene |
| water.js | Animated wave surface | CPU wave sim, recomputes normals every frame |
| flora.js | Trees, grass, rocks, particles | Instanced ginkgos, wind shader grass, leaf/firefly clouds |
| settlement.js | Spire, domes, monorail, relays | Window glow reacts to ctx.time.sunUp, relay checks ctx.player.pos |
| player.js | Physics, stamina, keyboard | ctx.player · { pos, vel, facing, stamina, gliding, onGround } |
| character.js | Hero mesh + procedural animation | Reads ctx.player state, drives limb rotations and glider visibility |
| camera.js | Third-person orbit follow | ctx.cam · { yaw, pitch, dist } — mouse + scroll input |
| collectibles.js | Spirit lights + pickup | Reads ctx.player.pos, calls ctx.hud.toast on collect |
| hud.js | All DOM | ctx.hud · { toast, setStamina, setClock, setOrbs } |
| main.js | Composition root + game loop entry | Inits systems in order, calls update(ctx) on each per frame |
Sprint up the plateau to the Aurora Spire and glide off the edge at dusk —
the orange sun disc over the water, the ginkgo canopies catching the last light,
and the spire's neon starting to glow is the best view in the valley.
Run the game locally with python3 -m http.server 8000 from the project folder.