Hey everyone! I built an endless downhill skiing game in vanilla Three.js (no framework — just three 0.171 + TypeScript + Vite) and I’d love your eyes on it.
Play it here: https://skiing.net — desktop or mobile, ~30 seconds to your first Yeti encounter.
You carve down a procedurally generated mountain through five biomes (alpine → pine forest → glacier → moonlit ridge → ice caverns), chain aerial tricks, thread slalom gates, and outrun the Yeti. Day/night cycle, dynamic weather, and a golden-hour dusk with a warm rim light on the skier and powder rooster tails off hard carves.
Some things under the hood that might interest this crowd:
- Post pipeline: EffectComposer with UnrealBloom + GTAO. I subclassed
GTAOPassto hide transparent/particle/sprite/line objects during its depth+normal pre-pass — otherwise the sky dome, glowing cavern ice, and trail particles stamp AO halos onto the scene. - Seamless endless terrain: chunks share UV 0..1 along their length with integer texture repeats, so snow albedo/normal/roughness wrap exactly at chunk seams. Biomes crossfade with a smoothstep band, so grading, fog, and props blend rather than pop.
- Phones get the real pipeline: quality is picked by device capability, not form factor — recent iPhones/flagship GPUs get shadows, bloom, GTAO, and 2× pixel ratio. A runtime FPS guard watches the first ~10 s and sheds pixel ratio + heavy passes if the device can’t hold frame rate (verdict remembered in localStorage).
- Verified leaderboard: every submission carries a run log (event timeline + physics samples) and the server rejects physically impossible runs.
Two things I’d genuinely love feedback on:
- Mobile quality selection — is a capability probe + 10 s FPS guard a reasonable approach, or do you use something better than shedding post passes at runtime?
- Frame pacing on your hardware — if you hit stutters (especially mid-range Android), I’d love to know the device.
Any and all criticism welcome. Thanks for playing!
