Skip to content
AsumaCodes
Menu

Sukhna Lake 3D

A winter-morning jog along the dam at Sukhna Lake, Chandigarh, at the lake's real shape and scale. It runs in the browser, on a phone too.

Sunrise over Sukhna Lake from the dam, the stone embankment curving away.

Loads 464 KB of code, gzipped, when you press play

You jog, walk or sit on the dam at Sukhna Lake among the morning crowd: joggers, a laughter club, yoga on the grass, a chai stall. The clock runs from civil dawn at 06:55, and the sun rises where and when it does in mid-January.

The brief had one rule for every detail: OpenStreetMap decides the layout, reference photos of the lake decide the look, and where neither confirms something, keep it generic. So the promenade is the real one, measured to the metre, and the chai stall is a sketch.

Status
Live
Built
26 to 27 September 2026, live on Kick (opens in a new tab)
Scale
1:1, from OpenStreetMap
Stack
three.js, Vite, OpenStreetMap, elevation tiles
Role
Idea, brief, direction and launch. Built with Claude Code.

A lake at its real shape and scale

The drawing below uses the same data the game loads. If the two ever disagree, the build that makes the drawing fails.
2,209 m by 1,305 m, from OpenStreetMap

The lake, its four islands and the 2.5 km promenade along the dam come straight from OpenStreetMap, projected to metres. The Shivalik hills beyond the far shore come from elevation tiles.

A build script fetches all of it once and writes two files the game ships with: 211 KB of map vectors and 247 KB of terrain. Nothing is fetched while you play.

Plan of Sukhna Lake from OpenStreetMap: 2,209 m east to west, 1,305 m north to south, with the 2.5 km dam promenade along its shore.2,209 m1,305 m500 mN
The heavy line is the dam promenade, 2.5 km. Lake area 1.363 km², shoreline 8.51 km, four islands. Drawn to one scale from the same data the game uses.© OpenStreetMap contributors, ODbL

What's in the morning

Clips recorded from the live build
  1. 1 of 4

    The morning crowd

    Joggers, walkers, a laughter club, yoga on the grass and a chai stall. Press E to greet someone, have a cutting chai, join the yoga or step into the laughter club's circle.

    A laughter club in a circle on the lawn beside the promenade, the jogger joining them.
  2. 2 of 4

    Time and weather

    The clock starts at civil dawn and runs at four times real speed through sunrise and golden hour. T jumps between times of day; K brings rain or winter fog.

    A time-lapse from the dam: the lake goes from pre-dawn blue to sunrise orange.
  3. 3 of 4

    On the water

    Buy a ticket at the boat club, take a swan from its berth and pedal out. The boat can go anywhere on the real lake and docks only at the jetty.

    The jogger pedalling a swan boat across the lake.
  4. 4 of 4

    Sit down

    Sit on a bench or the steps down to the water and a lo-fi loop starts. Every sound in the game is generated in the browser; there are no audio files.

    Rain on the stone water steps, the jogger sitting at the bottom looking out at the lake.

It started as a planet

Drag the line to compare the first build with the lake today.
Phase 1, then today

The engine it grew from wraps its world around a small planet, so the first plan did the same: the promenade as the equator of a sphere.

After Phase 1 the plan changed to a flat world at the lake's real scale. That call is in the history as its own commit, at 11:43 on the first day.

Today: the dam promenade at sunrise, joggers on the path and palms along the edge.
Phase 1: the first build, a flat-shaded green planet on a pale sky.
Phase 1Today

From plan to Phase 8 between 10:42 and 14:50

4 h 08 m from the Phase 0 plan to the Phase 8 commit

It was built live on Kick (opens in a new tab). Each phase ended with a build, a commit and a written summary before the next began. These times are straight from the git history, in India Standard Time.

4 h 08 m

Phase 0 plan to Phase 8 commitSource: Commit times from the project's git history

14 h 50 m

First commit to launch polishSource: Commit times from the project's git history

46

Commits in the repositorySource: git log
  1. First commit: reference photos of the lakeecd07d3 · feat: reference images
  2. Phase 0: the planf2ffc9a · Phase 0: plan for Sukhna, a sunrise jog around Sukhna Lake
  3. Phase 1: scaffold and engine port4c528c4 · Phase 1: scaffold and engine port
  4. Re-plan: a flat world at real scale instead of a planetb0b37b1 · docs: re-plan for a flat, real-scale Sukhna
  5. Phase 2: real map and terrain data pipelineea43aa5 · Phase 2: flat real-data pipeline and world scaffold
  6. Phase 3: the dam on its real curve, trees, level of detaile223b7a · Phase 3: world layout, LOD and self-checks
  7. Phase 4: the jogger, camera, controls and touch05b5fe7 · Phase 4: the jogger, camera, HUD, hint bar, controls and touch
  8. Phase 5: the morning crowd, rowing and birds4764b4f · Phase 5: NPCs, interactions, rowing, birds
  9. Phase 6: time of day, weather and signs0cf3487 · Phase 6: time of day, haze, mist, weather, signage
  10. Phase 7: sound, generated in the browser470c8a0 · Phase 7: sound, music on the water steps
  11. Phase 8: quality tiers and verification3034911 · Phase 8: quality tiers, verification, compare.md
  12. An automated playtest bot, and the fixes it foundbfb2412 · Playtest: automated bot and the fixes it found
  13. Boating from the jetty77298d7 · Boating from the jetty, and joining a circle
  14. Director mode: scripted shots recorded as video33bd544 · Director mode: scripted cinematic shots, recorded as video
  15. Launch polishee09553 · Launch polish: link previews, favicon, touch controls off the start card

Decisions

Each one measured on the build, not estimated
  1. Real data, baked at build time

    OpenStreetMap and elevation tiles are fetched once by a script, projected to metres and written to two files. The game never calls an API.

    211 KB + 247 KB

    Map vectors and terrain grids, the only data the game loadsSource: the project's data pipeline notes (docs/plan.md)
  2. Instance everything that repeats

    Trees come from two instanced pools refilled by distance: full trees near you, simple blobs far away. The same rule covers lamps, benches, railings and markers.

    25,898 trees in 5 draw calls

    Vegetation, Phase 3Source: docs/plan.md, Phase 3
  3. A budget for every frame

    Three quality tiers, picked from the device and stepped down if frames stay slow. The low tier has a hard ceiling on draw calls.

    251 to 329 draw calls

    Low tier, three worst views, under its 350 budgetSource: docs/plan.md, performance after the boat polish
  4. No model, texture or sound files

    Every shape, texture and sound is generated in code, so the whole game is one small download. The only image files are the icons and the link preview.

    464 KB

    All JavaScript including map data, gzippedSource: measured from the production build of 27 September 2026
  5. People fade instead of blocking the view

    Anyone who walks into the camera dissolves with an ordered dither in the crowd's shader, so the view stays clear and it costs no extra draw calls.

    2.0 m to 1.0 m

    Distance from the lens over which people fade outSource: docs/plan.md, playtest fixes
  6. A bot plays it before people do

    An automated playtest drives headed Chrome on the real GPU through eleven scenarios. At start-up, a check drives the boat's own physics at random against the shoreline.

    36,028 positions, 0 within 2 m of the shore

    Boat physics check, 4.3 km drivenSource: docs/plan.md, boating checks

Credits

Third-party code and data keep their own licences
  • Engine and look started from sakura-crossing (opens in a new tab) by Kenton Wang (MIT): the cel materials, the ink and grade passes, the sky, outlines and utilities.
  • Map data © OpenStreetMap contributors, ODbL. Terrain from Mapzen and AWS Terrain Tiles.
  • three.js and Vite, both MIT.
  • Look reference: photos of the real lake.