Voronoi
Voronoi / Worley cellular noise
Quick Start
Loading...
Source
Loading...
Documentation
Voronoi
GPU-accelerated Voronoi / Worley noise generator. Writes animated cellular noise to a caller-provided GPUTexture via a compute shader — no render pass required.
Usage
import { createVoronoi } from './voronoi';
const voronoi = createVoronoi(device);
const texture = device.createTexture({
size: [512, 512],
format: 'rgba8unorm',
usage: GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING
});
// Per frame
voronoi.update(texture, { time: elapsed, scale: 8, mode: 'f1', metric: 'euclidean', jitter: 0.9 });
// texture is now filled — bind it in your pipeline
// Clean up when done
voronoi.destroy();
API
createVoronoi(device)
Returns a Voronoi instance. No options — dimensions come from the target texture.
voronoi.update(target, options?)
Dispatches the compute shader to write cellular noise into the target texture.
target—GPUTextureto write into (must haveSTORAGE_BINDINGusage, formatrgba8unorm)
| Option | Type | Default | Description |
|---|---|---|---|
time |
number |
0 |
Animation time (drives feature point movement) |
scale |
number |
8.0 |
Number of cells across the texture |
jitter |
number |
0.9 |
Point randomness (0 = grid, 1 = fully random) |
mode |
'f1' | 'f2' | 'f2-f1' |
'f1' |
Distance output mode |
metric |
'euclidean' | 'manhattan' | 'chebyshev' |
'euclidean' |
Distance function |
voronoi.destroy()
Releases the uniform buffer. Does not destroy the target texture (you own it).
Algorithm
Voronoi / Worley noise scatters random feature points across a grid, then evaluates each pixel based on its distance to the nearest points. The grid is divided into cells, and each cell contains one random feature point whose position is determined by a hash function.
For each pixel, the shader searches the 3x3 neighborhood of cells (the pixel's own cell plus all 8 adjacent cells) and tracks the two closest feature points. This is sufficient because a feature point more than one cell away can never be closer than one in an adjacent cell.
Output modes:
- F1 — Distance to the nearest point. Produces rounded cell shapes, dark at cell centers and bright at edges.
- F2 — Distance to the second nearest point. Produces a different cellular pattern with larger bright regions.
- F2-F1 — Difference between F2 and F1. Highlights cell boundaries as thin bright lines (approaches zero at cell edges where two points are equidistant).
Distance metrics change the cell shape:
- Euclidean — Circular cells (standard L2 norm)
- Manhattan — Diamond-shaped cells (L1 norm:
|dx| + |dy|) - Chebyshev — Square cells (L-infinity norm:
max(|dx|, |dy|))
Animation works by incorporating time into the hash seed, causing feature points to drift smoothly within their cells.
WGSL loading
The default import uses Vite's ?raw suffix:
import shaderSource from './voronoi.wgsl?raw';
If you're not using a bundler, load via fetch:
const shaderSource = await fetch(new URL('./voronoi.wgsl', import.meta.url)).then((r) => r.text());
Modifying
Change the texture format
Edit the storageTexture format in voronoi.ts and the textureStore output in voronoi.wgsl. For example, to output raw float distances:
- In
voronoi.ts: changeformat: 'rgba8unorm'toformat: 'rg32float'in the bind group layout - In
voronoi.wgsl: changetexture_storage_2d<rgba8unorm, write>totexture_storage_2d<rg32float, write>, and storevec4f(f1, f2, 0.0, 1.0)to preserve both distances
Output color instead of grayscale
Replace the final textureStore line in voronoi.wgsl to map the value to a color. For example, use the cell ID (the integer coordinate of the nearest feature point's cell) as a hash input to generate a unique color per cell.
Add 3D Voronoi
Extend the 2D algorithm to 3D by searching a 3x3x3 cube of cells (27 neighbors). The hash function already supports arbitrary vec2f inputs — pass vec3f to a 3D hash variant. The third coordinate can be driven by time for smooth volumetric animation.
Combine with other noise
Use the Voronoi texture as a mask or blend layer. For example, multiply with Perlin noise to add organic variation within each cell, or use the F2-F1 edge pattern as a displacement map.
Use a custom hash function
Replace the hash2 function in voronoi.wgsl. Any function mapping vec2f -> vec2f with good distribution will work. The current implementation uses Dave Hoskins' hash-without-sine approach for GPU portability.
Further Reading
Resources on Voronoi noise, Worley noise, and cellular texture generation.
Original Research
Steven Worley, "A Cellular Texture Basis Function" (SIGGRAPH 1996) The original paper introducing cellular noise. Defines the F1, F2, F3, F4 distance basis functions and demonstrates their use for procedural textures like stone, water caustics, and organic patterns. https://dl.acm.org/doi/10.1145/237170.237267
Georgy Voronoi, "Nouvelles applications des parametres continus a la theorie des formes quadratiques" (1908) The mathematical foundation of Voronoi diagrams — partitioning a plane into regions based on distance to a set of seed points. Worley noise is essentially a rasterized Voronoi diagram with distance-based output.
Practical Guides
Inigo Quilez, "Voronoi Edges" GPU-friendly Voronoi implementation with exact edge distance computation. Shows how to efficiently compute F1, F2, and cell edges in a fragment shader. https://iquilezles.org/articles/voronoilines/
Inigo Quilez, "Smooth Voronoi" Technique for computing smooth (differentiable) Voronoi patterns by blending distance contributions instead of taking a hard minimum. https://iquilezles.org/articles/smoothvoronoi/
The Book of Shaders, "Cellular Noise" chapter by Patricio Gonzalez Vivo and Jen Lowe Interactive tutorial covering Voronoi patterns in shaders, with live code examples showing F1, F2, and distance metric variations. https://thebookofshaders.com/12/
Distance Metrics
- Wikipedia, "Minkowski Distance" The generalized distance metric that encompasses Euclidean (p=2), Manhattan (p=1), and Chebyshev (p=infinity) as special cases. Understanding the Lp norm family helps when experimenting with non-standard cell shapes. https://en.wikipedia.org/wiki/Minkowski_distance
Hash Functions
- Dave Hoskins, "Hash without Sine" (Shadertoy) The arithmetic hash functions used in this module. Avoids trigonometric functions for better GPU performance and cross-platform consistency. https://www.shadertoy.com/view/4djSRW
Applications
GPU Gems 2, Chapter 12: "Tile-Based Texture Mapping" Uses Voronoi-based approaches for non-repeating texture synthesis, demonstrating how cellular noise serves as a building block for complex materials. https://developer.nvidia.com/gpugems/gpugems2/part-iii-high-quality-rendering/chapter-12-tile-based-texture-mapping
Inigo Quilez, "Voronoi — Metric" (Shadertoy) Interactive demo showing how different distance metrics (Euclidean, Manhattan, Chebyshev, triangular) affect Voronoi cell shapes. https://www.shadertoy.com/view/MdSGRc
General References
Texture & Modeling: A Procedural Approach (Ebert et al., 3rd edition) Chapter on cellular textures covers Worley noise in depth, including multi-frequency layering, distance combinations, and practical applications in procedural material design.
Stefan Gustavson, "Simplex noise demystified" (2005) While focused on simplex noise, includes discussion of the relationship between different noise types and how cellular noise complements gradient-based approaches. https://weber.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf