It's really impressive that the author was able to implement rendering papers and physics sim papers with such regularity. It really is a feat. Makes me curious to see what their background is.
I aspire to build cool stuff like this in WebGPU.
Very excited for the future of the web.
Right now your options are basically having a GLES renderer that you can restrict to WebGL2 (so no compute shaders, etc. and other things that make desktop OpenGL acceptable for writing a modern renderer) or having to abstract over Vulkan/WebGPU yourself, which are similar but different enough to increase your code complexity considerably.
There's abstractions like wgpu and bgfx you can commit to, and of course you can just use game engine middleware and have it all done for you, but overall things fall short of just being able to "write once, run anywhere" a renderer, sadly.
I know in older games, the recommendation was to keep gravity low (~6 m/s^2 iirc) to help with simulation stability and make things look better, that might contribute to your idea of things being floaty.
I don't find the examples in the git repo to be especially floaty, but I work with a lot of simulators so I might just be used to it.
https://github.com/user-attachments/assets/f61714a2-8df6-4b7d-b22e-c3722155fe17
This project is an experimental WebGPU rigid-body / soft-body physics prototype centered on an AVBD-style (Augmented Vertex Block Descent by Giles et al. (2025)) solver. I ❤ working on advanced¹ web graphics² open source experiments³, so if you'd like to see more projects like these, please support my work.️
npm install
npm run dev
Build for production:
npm run build
Note: This is not a plug-and-play module yet and browser support (Chrome only for now) is limited, it's an initial proof of concept.
The current rigid-body pipeline follows the structure of Algorithm 1 from the AVBD paper, with broad phase, narrow phase, warm-started contact state, colored body solves, dual updates, and final velocity reconstruction. Reference paper: Augmented Vertex Block Descent by Giles et al. (2025)
Collision detection from the current state x^t
The paper starts each time step with collision detection from the current positions, before the solver iterations begin. In this codebase that starts in the main substep orchestration in src/physics/PhysicsEngine.ts, then flows into broad phase and narrow phase.
Broad phase candidate generation As described in Section 4 of the paper, we first build and traverse an LBVH to get candidate body pairs. Code:
Narrow phase manifold generation and warm-start persistence Once candidate pairs exist, discrete narrow-phase contact generation builds manifolds and preserves per-contact state used for warm starting and friction handling, matching Sections 3.3, 3.7, and 4 of the paper. Code:
Per-body constraint list construction Algorithm 1 is written as “for each body / vertex, iterate over each force affecting it.” The runtime representation of that step is the per-body constraint gather built from contacts, joints, and springs. Code:
Coloring The paper uses greedy coloring so all bodies of a given color can be processed in parallel during the primal step. That preparation happens in:
Inertial target and primal initialization
Algorithm 1 next builds the inertial target y, initializes the primal state, and warm-starts dual / stiffness variables with the alpha and gamma scaling discussed in Sections 3.6 and 3.7. Code:
Main AVBD iteration: colored primal body solve For each iteration, and for each color, the solver accumulates inertial and constraint contributions for a body, assembles the local rigid-body system, and applies the AVBD primal update. This corresponds to Algorithm 1 lines 7-25 and the approximate-Hessian discussion in Section 3.5. Code:
Dual and stiffness update After each primal sweep, dual variables and stiffness values are updated in parallel, corresponding to the augmented-Lagrangian / stiffness-ramp rules from the paper. Code:
Finalize velocities After the AVBD position solve is complete, velocities are reconstructed from the updated state, matching the final stage of Algorithm 1. Code:
Optional post-processing Sleep and diagnostics are outside the core AVBD paper loop and are optional runtime features in this project. The main orchestration remains in:
The broad pipeline matches the paper closely:
collision detection -> coloring -> inertial/primal init -> repeated colored primal solves -> dual updates -> finalize velocities
This is an initial experimental release and further updates will be focused on stability, performance and ease of use. One important implementation difference is that the paper explicitly describes double-buffered position updates for rare same-color conflicts, whereas the current path is still fundamentally an in-place colored body solve in src/physics/gpu/avbdState.ts.
I don't understand this complaint. What's worse about using WebGPU over using GLES? Seems like a strict improvement. You can use WebGPU anywhere, you're not required to "abstract" over Vulkan. If you're talking about using it outside of the web, you just choose wgpu or Dawn as your implementation, it's the same API and even the same implementation as you'd get in a browser.