Hi everyone! ![]()
I’d like to share Nitro Legends, an arcade racing game I’ve been building solo on Babylon.js 9. It features 14 cars, 9 tracks, AI races, and real-time multiplayer for up to 5 players—running smoothly on both desktop and mobile.
Play: https://nitro-legends.netlify.app
Video: https://youtu.be/FCvEguJn8Ik?si=Xq6M_lE9m37X4b-x
Stack: Vite 5 + @babylonjs/core 9, custom arcade physics (no physics engine), WebGL by default.
Technical Highlights & R&D
Much of the core visual and customization pipeline builds directly on top of earlier standalone R&D experiments I’ve revisited and re-architected for production:
-
The showroom and garage lighting environment adapts and evolves my earlier studio setup R&D (Koenigsegg Showroom Demo).
-
Tuned for neutral reflections, high-contrast rim lighting, and clean ground contact shadows without washing out car silhouettes.
-
The livery/decal projection system builds upon my previous multi-mesh decal projection prototype (Multi-Mesh Decal Demo).
-
Re-engineered to seamlessly project livery graphics across complex split car panels, doors, and spoilers without UV stretching or boundary clipping seams.
Changing material properties triggers an asynchronous shader recompile, causing a brief flicker or glitch.
-
Fix: Pre-compile the target shader on an offscreen cloned material instance, swapping references only once ready. Frequent customization combinations are pre-warmed when the garage UI opens.
-
Shader Plugin: Implemented via MaterialPluginBase hooking into CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS. Matte is driven by roughness (≥ 0.62) with metallic scaled by 0.35. Compatible with both GLSL and WGSL (WebGPU-ready).
-
Fixed 60Hz physics timestep decoupled from display refresh rates (30Hz, 60Hz, 144Hz) with render interpolation.
-
Drift mechanics decouple the vehicle’s heading vector from its linear velocity vector.
-
Networking: Client-authoritative binary protocol (18-byte car state + 6-byte user input @ 20Hz), hosted on Cloudflare Workers Durable Objects via WebRTC DataChannels.
-
Static track structures utilize freezeWorldMatrix.
-
Hundreds of trackside props (trees, street lamps, barriers) are batched into Thin Instances with custom distance + view frustum culling evaluated every 6 frames.
-
Automatic LOD pipeline powered by gltf-transform (only the player’s active vehicle loads at LOD 0).
-
Quality tier auto-selected via GPU string regex patterns (adjusts shadow cascades, prop density, and draw distance).
-
Adaptive resolution downscaling triggers automatically whenever sustained frame rates dip below 27 FPS.
-
Rendering: PBR metallic-roughness, CascadedShadowGenerator, DefaultRenderingPipeline + custom post-process chain (AgX tonemapping, motion blur, bloom, chromatic aberration), MSAA/FXAA, and Poly Haven HDRIs.
A big thank you to the Babylon.js team and this community—countless forum discussions helped turn these experiments into a finished game. ![]()
I’d especially love feedback on:
- Performance on your device (GPU, fps, desktop vs. mobile)
- Vehicle handling feel (especially drifting balance and nitro response)
Thanks for playing! ![]()
