compute_cloth
English | 日本語

Overview
- This sample uses a WebGPU compute shader to update a grid-shaped cloth with a mass-spring model
- Rather than adding a compute-specific API to the
webgcore library, it uses the WebGPUdevice / queue / canvas contextinitialized byWebgAppdirectly inside the sample - Cloth vertices are stored in a storage buffer, and the compute pass reads the previous frame's vertex positions and neighboring vertices, then writes the next frame's positions and velocities
- Because the sample uses a ping-pong structure with separate
srcanddstbuffers, it avoids conflicts where one invocation might overwrite a neighbor value while another vertex is still reading it - Structural spring forces alone allow the cloth to stretch too much, so a strain limit is added that pulls vertices back slightly when the distance to the up / down / left / right neighbors exceeds the allowed length
- The masses of movable vertices are set to match the cumulative load of a 96-row curtain, so gravity stays constant as acceleration while the springs can still support the curtain length
- The collision floor is placed lower than the bottom edge at maximum permitted stretch, so a normally sagging curtain does not intersect the floor
- One frame is divided into 3 substeps, and velocity is recalculated from the actual movement after position constraints, preventing downward velocity from remaining after correction
- Bend springs are added between vertices two steps apart to suppress sharp folding and self-crossing near the lower area
- The wind reverses periodically in the same front-back direction across the whole curtain, while only the amplitude varies by position, preventing both a central fold-back and one-way flow escape
- The fixed top edge is shaped as a gentle arc with the center lowered by 0.18, so the cloth looks suspended rather than like a perfectly straight board
- The render pass reads the post-compute storage buffer in the vertex shader and draws it as either a
line-listortriangle-listdepending onWire / Flat / Smoothmode
How to Run
- Open ./compute_cloth.html
- Use a browser with WebGPU support, and check the help panel and HUD together with the sample when needed
webg Features Used
WebgApp: initializesScreen, diagnostics, and the input foundation togetherWebgAppcompute frame:computeFrame: trueand theonComputeFramehandler skip standard scene drawing and control compute/render orderScreen.resize(): updates the actual canvas pixel size on viewport changes through theScreenheld byWebgAppWebgApp.getGPU(): entry point for building raw WebGPU pipelines on the sample side without changing the core APIbuildHelpPanelOptions() + showOverlayPanel(): displays the operation guide and current state as a collapsible help panelInputController.installTouchControls(): shows1 / 2 / 3 / R / P / Wcontrol buttons on both desktop and smartphones
WebGPU Features Used
storage buffer: keeps cloth vertex positions, fixed flags, and velocities on the GPUvertex mass: stores the mass of each movable vertex and converts spring force, wind force, and velocity damping into acceleration by dividing by massping-pong buffer: alternates a read-only source buffer and a writable destination buffer every framecompute pipeline: calculates neighboring springs, gravity, wind, and damping with one invocation per cloth vertexbend spring: connects vertices two steps apart horizontally and vertically with weak springs, helping support the cloth length while reducing local sharp foldscoherent gust: reverses wind direction across the whole curtain with the same time wave, while varying only amplitude by horizontal position and height to create natural swayingstrain limit: returns adjacent structural-spring distances to within 1.06 times their initial length, suppressing overstretch while keeping motion lightsimulation substeps: repeats integration and position limiting three times per frame, stabilizing the accumulated load of the long curtainline vertex index stream: draws horizontal and vertical grid lines inWiremodetriangle vertex index stream: splits each grid cell into 2 triangles soFlat / Smoothcan share the same high-resolution surfacerender pipeline: reads the storage buffer in the vertex shader and displays the deformed cloth without CPU readbackfixed cloth color: keeps the same fixed orange color forWire / Flat / Smoothinstead of changing vertex color according to wind speedview-space lighting: uses light from the upper-right of the view, with weak ambient, diffuse-dominant shading, and specular highlights to show surface directioncamera-following light: transforms world-space normals into view space by camera rotation and computes lighting in the same coordinate system as the light fixed to the upper right of the screentimestamp query: measures GPU Compute time across all three substeps plus Render Pass time, then displays per-stage and total load
Checkpoints
- Right after startup, confirm that a vertically long
64 x 96cloth grid is fixed at the top and sways under gravity and wind - Confirm that when you rotate the camera by drag, or pan by
Shift + Drag, right-drag, or middle-drag, the cloth simulation still continues entirely on the GPU - On smartphones, confirm that one-finger drag performs orbit, two-finger drag performs pan, and pinch performs zoom
- Confirm that the
1 / 2 / 3 / R / P / Wbuttons shown at the bottom of the screen on both desktop and smartphones can control display mode, reset, pause, and wind - Confirm that
Hor the help-panel button folds the explanation and thatShow Helprestores it - Switch
Wire / Flat / Smoothwith1 / 2 / 3and confirm that line and polygon display can be switched from the same storage buffer - Toggle wind with
Wand confirm that the front-back waving becomes weaker or returns - When
Ppauses the sample, confirm that the compute pass stops and the current storage-buffer state is rendered as-is - Confirm that
Rrestores the cloth to its initial state - Confirm that
GPU compute / GPU render / GPU total / JS timeand their load values update in the help panel and that render time while paused is not included in GPU Compute time
Controls
- Drag: camera orbit
Shift + Drag / right-drag / middle-drag: camera pan- Mouse wheel: zoom
- One-finger drag: camera orbit
- Two-finger drag: camera pan
- Pinch: zoom
1: wire display2: flat polygon display3: smooth polygon displayW: wind on / offP: pause / resumeR: reset clothH: hide / show help
Implementation Details
- The compute shader in
main.jsseparatessrcStateas read-only anddstStateas read-write - Spring calculations read up / down / left / right and diagonal neighbors, and if the distance becomes extremely short they contribute zero instead of being normalized
- Gravity is added as acceleration independent of mass, while spring force, wind force, and velocity drag are divided by vertex mass to obtain acceleration
- After correcting positions with the strain limit and the floor, velocity is recalculated from the difference between the corrected position and the previous substep position, so downward velocity from before the correction is not retained
- The render shader uses a cloth-vertex index passed as a vertex attribute and directly references vertex positions inside the storage buffer
Flat / Smoothshare the same triangle stream.Flatsends the face normal created from the three deformed vertices as a constant value over the triangle with WGSL@interpolate(flat), whileSmoothinterpolates vertex normals created from grid neighbors- The cloth color is fixed, and the motion and surface direction are read from the diffuse and specular highlights produced by the light at the upper right of the view
- Operation guidance and state display are collected in the
OverlayPanelhelp panel instead of a custom HUD, while smartphone single-tap actions are separated into touch buttons - Because vertex coordinates are never returned to the CPU, this sample can be used as an example of keeping rendering-oriented simulations such as cloth or hair entirely on the GPU