[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f1zl3odsrakrvm":3},{"_id":4,"slug":5,"title":6,"subtitle":7,"kind":8,"cards":9,"tags":59,"categories":61,"source":63,"lang":66,"author":67,"audioState":70,"stats":71,"publishedAt":74,"renderer":75},"6abcc84eca21c797c7ea11d7","i-built-a-marble-run-physics-sandbox-in-the-browser-and-the-9b199849","I built a marble run physics sandbox in the browser, and the export was the hard part","I made this one myself, so putting that up front.","news",[10,14,19,24,29,34,39,44,49,54],{"headline":11,"body":12,"imageUrl":13,"sourceImageUrl":13},"I built a marble run physics sandbox in the browser, and the export was the…","I made this one myself, so putting that up front. It is my project.","https:\u002F\u002Fmedia2.dev.to\u002Fdynamic\u002Fimage\u002Fwidth=1200,height=627,fit=cover,gravity=auto,format=auto\u002Fhttps%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsnhsciwtgyjob5nxvcou.png",{"headline":15,"body":16,"imageUrl":17,"images":18},"https:\u002F\u002Fwww.marblerun.online is a 3D marble run playground. You","https:\u002F\u002Fwww.marblerun.online is a 3D marble run playground. You place ramps, walls, pegs, spinners, boxes and balls on a lit wall, press play, a real rigid body simulation runs, and you can export a vertical 9:16 MP4 with sound.","\u002Fapi\u002Fmedia\u002Fposts\u002Fi-built-a-marble-run-physics-sandbox-in-the-browser-and-the-9b199849\u002F1.webp",{"local":17},{"headline":20,"body":21,"imageUrl":22,"images":23},"The whole thing runs client side. No signup","The whole thing runs client side. No signup, no login, nothing uploaded, no AI anywhere in the build or at runtime. Desktop only by design, because the scene is drawn in 3D and phones get a short message instead of a janky version of it. The export is what took three times longer than the editor.","\u002Fapi\u002Fmedia\u002Fposts\u002Fi-built-a-marble-run-physics-sandbox-in-the-browser-and-the-9b199849\u002F2.webp",{"local":22},{"headline":25,"body":26,"imageUrl":27,"images":28},"My first instinct was MediaRecorder on the canvas","My first instinct was MediaRecorder on the canvas, since it is about fifteen lines of code. I threw it away. Screen capture of a WebGL canvas gives you the wrong aspect ratio, whatever framerate the machine happens to be managing that second, and audio that has to be muxed in afterwards. It also looks flat, which defeats the point of a 3D scene.","\u002Fapi\u002Fmedia\u002Fposts\u002Fi-built-a-marble-run-physics-sandbox-in-the-browser-and-the-9b199849\u002F3.webp",{"local":27},{"headline":30,"body":31,"imageUrl":32,"images":33},"What I do instead is re-render the same","What I do instead is re-render the same scene camera through an offscreen pass at 1080x1920, locked to 30fps, and push frames straight into a video encoder. During export the simulation steps on a deterministic clock, so the same level produces the same video every time you run it. The audio is a generated click track placed where the impacts occur, not a microphone, so it lands frame for frame with what you see. A few smaller things worth writing down.","\u002Fapi\u002Fmedia\u002Fposts\u002Fi-built-a-marble-run-physics-sandbox-in-the-browser-and-the-9b199849\u002F4.webp",{"local":32},{"headline":35,"body":36,"imageUrl":37,"images":38},"Fixed timestep with an accumulator. Running physics off","Fixed timestep with an accumulator. Running physics off requestAnimationFrame deltas directly means the same level plays differently on a 60Hz laptop and a 144Hz monitor. Step at a fixed rate and render the interpolated result. Substepped integration for the balls, because a fast marble that tunnels through a thin peg looks completely broken.","\u002Fapi\u002Fmedia\u002Fposts\u002Fi-built-a-marble-run-physics-sandbox-in-the-browser-and-the-9b199849\u002F5.webp",{"local":37},{"headline":40,"body":41,"imageUrl":42,"images":43},"Restitution and friction per material. A steel ball","Restitution and friction per material. A steel ball on a wooden ramp and a rubber ball on the same ramp have to behave like two different toys, so the defaults are close to real values but not exactly real values, because exact real values feel dead on screen.","\u002Fapi\u002Fmedia\u002Fposts\u002Fi-built-a-marble-run-physics-sandbox-in-the-browser-and-the-9b199849\u002F6.webp",{"local":42},{"headline":45,"body":46,"imageUrl":47,"images":48},"Lighting mattered more than I expected. One directional","Lighting mattered more than I expected. One directional light, a soft fill, and a subtle texture on the wall. Without that the whole thing reads as a flat 2D canvas even though the geometry is genuinely 3D.","\u002Fapi\u002Fmedia\u002Fposts\u002Fi-built-a-marble-run-physics-sandbox-in-the-browser-and-the-9b199849\u002F7.webp",{"local":47},{"headline":50,"body":51,"imageUrl":52,"images":53},"What I would do differently is start with","What I would do differently is start with the export, because I had not thought about determinism up front and that is what made the export hard.","\u002Fapi\u002Fmedia\u002Fposts\u002Fi-built-a-marble-run-physics-sandbox-in-the-browser-and-the-9b199849\u002F8.webp",{"local":52},{"headline":55,"body":56,"imageUrl":57,"images":58},"If you want to try it, it needs","If you want to try it, it needs a desktop browser. Happy to answer questions about the physics stepping or the encoding. For further actions, you may consider blocking this person and\u002For reporting abuse","\u002Fapi\u002Fmedia\u002Fposts\u002Fi-built-a-marble-run-physics-sandbox-in-the-browser-and-the-9b199849\u002F9.webp",{"local":57},[60],"dev",[62],"Technology",{"name":64,"url":65},"Dev.to","https:\u002F\u002Fdev.to\u002Fambar_anandmallik_b5f09d\u002Fi-built-a-marble-run-physics-sandbox-in-the-browser-and-the-export-was-the-hard-part-1gcm","en",{"handle":68,"displayName":69},"spots","Spots","queued",{"views":72,"likes":73,"saves":73,"shares":73,"completions":73,"opens":73,"skips":73,"depthSum":73},1,0,"2026-09-30T08:29:02.417Z","local"]