Voronoi

Voronoi / Worley cellular noise

Initializing WebGPU...
Mode
Metric

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.

  • targetGPUTexture to write into (must have STORAGE_BINDING usage, format rgba8unorm)
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: change format: 'rgba8unorm' to format: 'rg32float' in the bind group layout
  • In voronoi.wgsl: change texture_storage_2d<rgba8unorm, write> to texture_storage_2d<rg32float, write>, and store vec4f(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

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