Skip to content
Sample of Dreamscape Field (Refik Anadol — Dreams / Nature Dreams)

anadol_webgpu · dreamscapeField

Dreamscape Field (Refik Anadol — Dreams / Nature Dreams)

Inspired by Refik Anadol Studio's Dreams series (Nature Dreams, Urban Dreams, Space Dreams and the MoMA Fluid Dreams algorithm): a smooth low-frequency Perlin noise field drives slow global drift while a finer detail octave adds turbulent perturbation — Anadol's fluid solver aesthetic realised with cheap numpy. N agents follow the 2-octave flow F(p,t) = A1 n1(p*s1 + d(t)) + A2 n2(p*s2 + d'(t)), depositing fading coloured trails on a canvas to produce a slow-evolving data-pigment landscape.

Original: https://www.nvidia.com/en-us/research/ai-art-gallery/artists/refik-anadol/

▶ 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.

Family
anadol_webgpu
Source
anadol · webgpu
Evolution
noise_field
Render
fading_trails
Complexity
medium
Agents
4000
Year
2024
Author
Refik Anadol Studio (concept)

Math essence

Each step: v = v*drag + F(pos, t); pos += v with toroidal wrap. F is two octaves of Perlin gradient noise sampled at independent (scale, drift) parameters per octave. The canvas fades geometrically each step and agents additively splat with an HSV rainbow tied to a per-agent phase plus the shared time-drift.

Parameters

Name Type Default Range Description
dim int 600 200–1500 Square canvas side length.
num_agents int 4000 100–30000 Number of agents N.
coarse_scale float 0.01 0.001–0.1 Base octave spatial frequency.
detail_scale float 0.055 0.005–0.3 Detail octave spatial frequency.
coarse_weight float 0.55 0–2 Base octave amplitude.
detail_weight float 0.18 0–1.5 Detail octave amplitude.
flow_speed float 1.2 0.1–5 Velocity scale per step.
drag float 0.96 0.5–1 Per-step velocity damping.
time_drift float 0.0025 0–0.05 Field advection speed.
fade float 0.992 0.85–1 Per-step canvas fade.

Reference

First 60 lines of reference.py. Full source: library_external/anadol_webgpu/dreamscapeField/reference.py

"""dreamscapeField — Refik Anadol inspired dream flow field.

Inspired by Refik Anadol Studio's *Dreams* series (*Nature Dreams*,
*Urban Dreams*, *Space Dreams*, the *Dreams — F* installation): a
smooth low-frequency noise field drives a global slow drift of agents,
while a high-frequency noise layer adds turbulent detail.  Agents
deposit a fading trail on the canvas — the viewer sees a fluid
"data-pigment" landscape like Anadol's GPU-accelerated fluid
simulations, but generated here with cheap numpy.

The mathematical backbone is two-octave Perlin-like gradient noise:
    F(x, y, t) = A1 * n1(x*s1 + dx(t), y*s1 + dy(t))
              +  A2 * n2(x*s2 + dx(t), y*s2 + dy(t))
where ``n1`` is a coarse 2D Perlin noise (smooth base flow) and ``n2``
is a finer noise (perturbation layer).  At each step we advance N
agents with v += F(p, t), v *= drag, p += v.

Reference:
- https://www.nvidia.com/en-us/research/ai-art-gallery/artists/refik-anadol/
  (Nature Dreams, Space Dreams — fluid-dynamics inspired work)
- https://refikanadol.com/works/coraldreams/  (Fluid Dreams algorithm)
"""
from __future__ import annotations

from typing import ClassVar

import numpy as np


def _fade(t: np.ndarray) -> np.ndarray:
    # Perlin's fade curve: 6t^5 - 15t^4 + 10t^3
    return t * t * t * (t * (t * 6 - 15) + 10)


def _perlin2(perm: np.ndarray, x: np.ndarray, y: np.ndarray) -> np.ndarray:
    """Fast 2D Perlin noise (vectorised) for arrays of (x, y) positions.

    Parameters
    ----------
    perm : (512,) array of ints in [0, 255]
        Doubled permutation table (Perlin's classic trick).
    x, y : (...) arrays of float coordinates (any shape).
    Returns
    -------
    (...) array of float values in roughly [-1, 1].
    """
    xi = np.floor(x).astype(np.int64) & 255
    yi = np.floor(y).astype(np.int64) & 255
    xf = x - np.floor(x)
    yf = y - np.floor(y)

    u = _fade(xf)
    v = _fade(yf)

    # Hash function of Perlin: choose a gradient (8 directions on 2D).
    def grad(hashval: np.ndarray, x: np.ndarray, y: np.ndarray) -> np.ndarray:
        h = hashval & 7
        # map to one of 8 directions on the unit circle
        dirs = np.array(
            [(1, 1), (1, 0), (1, -1), (0, -1), (-1, -1), (-1, 0), (-1, 1), (0, 1)],

Try running it locally

The reference implementation is self-contained Python with numpy. Install the package and run:

python library_external/anadol_webgpu/dreamscapeField/reference.py

Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.

More from anadol · webgpu

Sample of 2D FFT Texture Spectrum (WebGPU butterfly FFT)

2D FFT Texture Spectrum (WebGPU butterfly FFT)

anadol_webgpu · fft2dTexture

The WebGPU butterfly 2D FFT pattern: stage by stage, a @compute shader reads two texels per output (input[p] and twiddle-weighted input[q]) and writes the combined result; after log2(N) horizontal stages, transpose, and log2(N) vertical stages, the 2D FFT is complete.

View →
Sample of Compute Particle System (WebGPU @compute pattern)

Compute Particle System (WebGPU @compute pattern)

anadol_webgpu · computeParticleSystem

The canonical WebGPU 'compute-to-render' pattern: a @compute shader updates N particles in a storage buffer (one thread per particle, simple Verlet-style integration: v += gravity; v *= drag; p += v; bounce off walls; life++; respawn if life>max), and a render pass consumes the same buffer as vertex data to draw point sprites.

View →
Sample of Data Particle Field (Refik Anadol — Machine Hallucinations / AI Data Sculptures)

Data Particle Field (Refik Anadol — Machine Hallucinations / AI Data Sculptures)

anadol_webgpu · dataParticleField

Inspired by Refik Anadol Studio's AI Data Sculptures and 'data universe' portraits (e.g.

View →
Sample of Latent Walk (Refik Anadol — Unsupervised / Machine Hallucinations)

Latent Walk (Refik Anadol — Unsupervised / Machine Hallucinations)

anadol_webgpu · latentWalk

Inspired by Refik Anadol Studio's Unsupervised — Machine Hallucinations — MoMA (2022): a chain of N points is sampled from a synthetic 64-dimensional latent space (a smoothed random walk) and projected to 2D via a fixed random matrix; the path is integrated step-by-step with spherical-linear interpolation between adjacent chain points, so the rendered trail visualises the path the 'latent space browser' would take through the embedding.

View →
Sample of Parallel Reduction (WebGPU workgroup-shared-memory tree reduction)

Parallel Reduction (WebGPU workgroup-shared-memory tree reduction)

anadol_webgpu · parallelReduction

The classic WebGPU parallel-reduction pattern: load N values into workgroup-shared memory, workgroupBarrier(), tree-reduce by stride (shared[lid.x] = op(shared[lid.x], shared[lid.x + stride]); stride /= 2), workgroupBarrier(), and emit per-workgroup partials from thread 0.

View →
Sample of Tile Blur (WebGPU separable Gaussian tile-shared-memory blur)

Tile Blur (WebGPU separable Gaussian tile-shared-memory blur)

anadol_webgpu · tileBlur

The WebGPU separable Gaussian blur primitive: a workgroup of TILE×TILE threads loads a tile+halo of the source image into workgroup-shared memory, workgroupBarrier(), convolves each pixel with a 1D Gaussian along the row, writes to a ping-pong texture; then a second compute pass applies the column-direction Gaussian on the intermediate texture.

View →

See all anadol_webgpu artworks →