GPGPU Name Particle Morph

A word is rasterized, sampled into target positions and handed to a pair of GPU ping-pong textures. Every particle carries its own spring, curl wander and pointer impulse. Type a different word and the same population is re-targeted; it scatters and finds the new letterforms.

How this is built

Runtime
Three.js r185, added as the route’s first runtime dependency. Its GPUComputationRenderer supplies the float-texture ping-pong and dependency wiring; the route imports only the renderer, points, shader and math modules it uses so the bundler can drop the rest. WebGL2 is required, device pixel ratio is capped at 2, and context loss stops the loop and rebuilds the GPU graph if the browser restores the context.
Targets
The submitted word is rasterized offscreen with the site’s existing Roboto Flex subset — a 34 200-byte woff2 (public/fonts/roboto-flex-v1.woff2, measured on this repository 2026-09-02), and no new font is downloaded. Filled pixels are collected and rejection-sampled to exactly the requested particle count, then uploaded as a float texture. Width is set through ctx.fontStretch immediately after ctx.font, because assigning the font resets the stretch.
Motion
A velocity kernel combines a spring toward the target, a divergence-free curl perturbation, a Gaussian pointer repulsor and a radial scatter impulse; a position kernel integrates it at a fixed 1/60 s step with a 4-step frame ceiling. Particle count is live-switchable from 50,000 to 250,000, so its cost is visible in the HUD rather than hidden in a preset.
Input and state
The word field accepts 1–12 Basic Latin characters, matching the shipped font subset. Every mutation has a keyboard path: Enter submits the word, arrow keys change count, Space or Enter activates Scatter as the keyboard equivalent of pointer force, and the panel’s move handle takes the arrow keys. The word and count are written to lab.gpgpu-name-morph.v1 and the panel’s position to lab.gpgpu-name-morph.panel.v1, both inside a try/catch and both restored on the next visit; storage failure leaves the instrument running with defaults. Reset arms, then confirms, and returns all three to their defaults.
Reduced motion
Under prefers-reduced-motion: reduce there is no continuous loop. The simulation runs a discrete settling burst and presents one composed frame; typing or scattering triggers another burst. The preference is watched live and the HUD reports static.
Measurement
The single requestAnimationFrame loop calls the shared metrics collector once per rendered frame; the HUD owns no loop of its own. Its averaging and percentile windows are declared in lib/perf/frame-metrics.ts, which every route in the lab shares, so they are not restated here. KB transfer sums real navigation and resource entries.

Set the word

1–12 Basic Latin characters. Press Enter to submit.

Scatter is the keyboard path for the pointer force: focus the button and press Space or Enter. Focus the move handle and press arrow keys to nudge this panel 16 px.

GPU simulation live.

FPS
measuring
ms/frame p95
measuring
KB transfer
—