hodgin_iquilezles · Mulberry32RNG
Mulberry32 PRNG (stratified scatter)
Mulberry32 is a tiny 32-bit-state pseudo-random number generator popularised in the demoscene and used pervasively by Quilez and other graphics programmers as the RNG inside procedural sketches. Here it drives a stratified 2D scatter: every (col,row) cell of a base lattice receives one point whose offset and colour are produced by three sequential Mulberry32 draws, giving the classic Quilez-style noise-jittered lattice pattern.
Original: https://gist.github.com/tommyettinger/46a874533244883189143505d203312c
▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.
Math essence
State update: a += 0x6D2B79F5 (mod 2^32); t = imul(a^(a>>15), 1|a); t = t + imul(t^(t>>7), 61|t) ^ t; output = (t ^ (t>>14)) / 2^32. Each step advances the seed by seed_walk Mulberry32 iterations and uses the next 3*N draws to jitter, hue and place N stratified points on a cols x rows grid.
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 400 | 120–800 | Square output size in pixels. |
cols | int | 24 | 4–80 | Number of lattice columns. |
rows | int | 24 | 4–80 | Number of lattice rows. |
jitter | float | 0.45 | 0–1 | Fraction of a cell size by which each point is randomly displaced. |
point_size | int | 4 | 1–12 | Radius of each rendered point (in pixels). |
seed_walk | int | 1 | -5–12 | Number of Mulberry32 advances per step (negative rewinds). |
palette | string | iq | null–null | Colour palette: iq, viridis, or magma. |
Reference
First 60 lines of reference.py. Full source:
library_external/hodgin_iquilezles/Mulberry32RNG/reference.py
from __future__ import annotations
from typing import ClassVar
import numpy as np
class Mulberry32RNG:
"""Mulberry32 — Inigo Quilez / Tommy Ettinger (32-bit PRNG foundation).
Mulberry32 is a tiny, fast, 32-bit-state pseudo-random number generator
popularised by Tommy Ettinger in the demoscene and graphics communities
and used pervasively by Quilez and others as the RNG inside shadertoy
and procedural sketches:
uint32_t mulberry32(uint32_t a) {
a |= 0; a = a + 0x6D2B79F5 | 0;
uint32_t t = Math.imul(a ^ a >>> 15, 1 | a);
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
return ((t ^ t >>> 14) >>> 0) / 4294967296;
}
Here we use the state machine to drive a layered "stratified" 2D
scatter pattern (a classic Quilez visual idiom: pick a base lattice
with N "bins", then perturb every point by a small mulberry32 noise
vector). Each ``step`` advances the seed and re-rolls the points,
producing a deterministic noise pattern that changes by tiny, smooth
amounts as the seed is mixed through Mulberry32's Weyl sequence.
"""
family: ClassVar[str] = "hodgin_iquilezles"
sketch: ClassVar[str] = "mulberry32rng"
def __init__(
self,
dim: int = 400,
cols: int = 24,
rows: int = 24,
jitter: float = 0.45,
point_size: int = 4,
seed_walk: int = 1,
palette: str = "iq",
**_,
) -> None:
self.dim = dim
self.cols = int(cols)
self.rows = int(rows)
self.jitter = float(jitter)
self.point_size = int(point_size)
self.seed_walk = int(seed_walk)
self.palette = palette
self.reset()
@staticmethod
def _u32(x: int) -> int:
return x & 0xFFFFFFFF
def _next_state(self, state: int) -> tuple[int, float]:
a = self._u32(state + 0x6D2B79F5)
t = np.uint32(a) Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/hodgin_iquilezles/Mulberry32RNG/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from hodgin × iquilezles
Boids Flock (Hodgin Murmuration)
hodgin_iquilezles · BoidsFlock
A 2D flock of boids steered by Craig Reynolds' three classic rules (separation, alignment, cohesion) over a coarse spatial-hash neighbor query.
Fractional Brownian Motion noise
hodgin_iquilezles · FBMNoise
Quilez's canonical fBM: a 2D value-noise base summed over N octaves whose frequency doubles and amplitude is multiplied by G = exp2(-H) per octave.
Magneto Particles (Hodgin Magnetosphere)
hodgin_iquilezles · MagnetoParticles
Particles pulled and pushed by N orbiting magnetic anchors whose charges flip sign over time.
Saturn Rings (orbital resonance)
hodgin_iquilezles · SaturnRings
Thousands of particles are initialized in an annulus between inner_radius and outer_radius around a central mass, with circular orbital velocities v = sqrt(M/r).
Smooth-Minimum SDF field
hodgin_iquilezles · SmoothMinSDF
Two animated 2D SDF primitives (a moving circle and a translating slab) are blended with Quilez's quadratic-polynomial smooth-minimum and rendered as a scalar field.
Worley / Cellular Noise
hodgin_iquilezles · WorleyNoise
Quilez's classic 2D Worley noise: a unit grid of cells, each containing one pseudo-random feature point placed by a 2D integer hash.