Making an image ripple is easy. Making one behave like cloth requires motion to travel across the surface: a pull at one point should move its neighbors, and a fold should change how the wind catches it.
flag-cloth builds that behavior from a small particle grid. The image and the grid are independent. A high-resolution texture stays sharp even when the simulation uses only a few hundred particles; WebGL fills the image between them.
Motion stored between frames
Each particle remembers two positions: where it is now and where it was on the previous step. Their difference acts like velocity. Wind and gravity add acceleration, and damping gradually removes energy.
next = current + (current - previous) × damping + acceleration × time²This is Verlet integration. It needs little state and works naturally with position constraints. A pinned particle simply has no movable mass, so the solver leaves it in place.
Connections create the material
Particles alone would scatter. Three families of distance constraints give the grid its shape:
- Structural connections hold neighboring rows and columns together.
- Shear connections cross each cell diagonally and resist skewing.
- Bend connections span two cells and keep the cloth from folding like paper at every edge.
The solver corrects those distances several times per step. Each correction is small, but together they carry motion from one particle into the rest of the flag.
Drag a white particle, change the pinned edge, or hide a constraint family. The diagram runs the same solver as the rendered flag, without the texture and lighting.
Wind follows the folds
Every grid cell is rendered as two triangles. A triangle gives the solver two useful facts: its area and the direction its surface faces. Comparing that direction with the local wind tells us how much air the triangle catches.
The resulting force is shared by the triangle's three particles. As those particles move, the triangle turns. A new orientation catches a different amount of wind, so the cloth responds to its own changing shape rather than following a predefined wave.
Turbulence only varies the local wind. It never places a particle directly.
A steady simulation, a responsive render
The physics advances in fixed increments even when display frames arrive unevenly. The renderer then copies the latest particle positions into an existing WebGL buffer. It does not rebuild the grid, create a particle for each image pixel, or ask React to render every frame.
That separation is the useful core of the library: a small connected simulation controls the motion, while the GPU keeps the image and lighting smooth.