WebGPU · three.js TSL
Flower Field
1.8 million plants over a procedural landscape, with a floating cube that grows its own vegetation. Not a single position is stored on the CPU. The GPU decides where everything goes.

An evening project. I wanted to know what a browser can actually do with WebGPU once you stop treating the GPU as something you hand finished geometry to, and start letting it decide what exists.
One height function, shared by everything
The same TSL function feeds the terrain mesh and every single plant. There's no noise implementation on the CPU at all, so the ground and what grows on it cannot drift apart. The mountains live in that same function as a radial mask over the plane. No separate mesh, and it hides the hard horizon line for free.
Indexed geometry, and a field cut into chunks
Merging geometry demands non-indexed input, which blew one flower head up from 42 vertices to 240. At 70,000 instances that's 14 million extra vertex invocations a frame, each running a fractal noise: 13 fps against 47, for an identical image. Cutting the field into 12×12 meshes so the camera can throw most of it away took it to 73.
Per-instance work belongs in a compute pass
Terrain height is a 7-octave fractal noise that belongs to the instance, but a vertex shader has no per-instance stage, so it re-ran the whole thing for each of a blade's ten vertices. A compute pass now writes position, size, colour and angle into a storage buffer once, and a second pass refreshes only the wind angle each frame. The plant vertex shader went from 3 noise calls and 339 lines to zero and 129.
Measured on Apple Silicon at 1456×826, pixelRatio 2: 99 fps against a 100 fps vsync ceiling, so the real headroom is larger than the number admits.
Started from this reference. Same low sun, same floating cube, but where that one was modelled, every flower here is placed by a shader at runtime.
WebGPU · three.js r185 · TSL · compute shaders