Eclipse contours
Inside a heavy ring, noise contours bunch where a disc’s surface drops away. A faint ring sits outside.
Made with Claude Opus 5.5
- Technique
- flow fields and contours
- Shape
- Any screen
- Added
- 27 September 2026
Colours
- #1C1B1Abackground
- #DAD8CEforeground
- #CF6A4Caccent
Export
FormatThis browser can’t make WebP files.
Shapecropped from 16:9
Crop
SizeThis browser can’t draw a file that large.
Sources
- Marching squares.
- Inigo Quilez, FBM.
Source code
wallpapers/eclipse-contours/design.py, 46 lines
"""Noise contour lines confined to a disc inside two rings: an fBm field traced by marching squares and clipped."""
import numpy as np
from numpy.typing import NDArray
from walldye import ACCENT, ACCENT_4, BG, UI, Canvas, P, design, ladder
from walldye.field import iso_lines, sample_field
R, CELL = 330, 6 # disc radius; field sample spacing
SPAN = 420 # px per noise unit
AT = (1240 / SPAN, 540 / SPAN) # the noise-plane point under the disc centre
LEVELS = [-0.3 + k * 0.035 for k in range(18)]
# one tone per level, skipping the near-background end of the ladder so every line reads
TONES = ladder((BG, ACCENT_4, ACCENT), len(LEVELS) + 4)[4:]
@design(aspects="any")
def draw(s: Canvas) -> None:
# about 0.65 along the long axis (clear of the left-side windows on a desktop, below the
# clock on a phone), centred on the short axis
c = s.pick(landscape=(0.646, 0.5), portrait=(0.5, 0.6))
noise = s.noise(7)
# Sample only the disc's bounding box, relative to its centre, so every aspect shows the
# same planet.
half = int(np.ceil((R + 2 * CELL) / CELL))
def height(i: NDArray[np.int64], j: NDArray[np.int64]) -> NDArray[np.float64]:
dx, dy = (i - half) * CELL, (j - half) * CELL
d = np.hypot(dx, dy) / R
# the negative falloff past 0.85 R bunches the lines against the rim, like a limb
return noise.fbm(AT[0] + dx / SPAN, AT[1] + dy / SPAN, 4) - 0.9 * np.maximum(0.0, d - 0.85)
field = sample_field(height, 2 * half, 2 * half)
origin = c - (half * CELL, half * CELL)
with s.clip() as disc:
disc.add(P().circle(c, R))
with (
s.group(clip_path=disc.ref),
s.buckets(TONES, "stroke", stroke_width=1.6, stroke_linejoin="round") as lines,
):
for k, level in enumerate(LEVELS):
for line in iso_lines(field, level, cell=CELL, origin=origin):
if len(line) > 3:
lines[k].poly(line)
s.stroke(P().circle(c, R + 18), UI, 2)
s.stroke(P().circle(c, R), ACCENT, 3)"""Noise contour lines confined to a disc inside two rings: an fBm field traced by marching squares and clipped."""
import numpy as np
from numpy.typing import NDArray
from walldye import ACCENT, ACCENT_4, BG, UI, Canvas, P, design, ladder
from walldye.field import iso_lines, sample_field
R, CELL = 330, 6 # disc radius; field sample spacing
SPAN = 420 # px per noise unit
AT = (1240 / SPAN, 540 / SPAN) # the noise-plane point under the disc centre
LEVELS = [-0.3 + k * 0.035 for k in range(18)]
# one tone per level, skipping the near-background end of the ladder so every line reads
TONES = ladder((BG, ACCENT_4, ACCENT), len(LEVELS) + 4)[4:]
@design(aspects="any")
def draw(s: Canvas) -> None:
# about 0.65 along the long axis (clear of the left-side windows on a desktop, below the
# clock on a phone), centred on the short axis
c = s.pick(landscape=(0.646, 0.5), portrait=(0.5, 0.6))
noise = s.noise(7)
# Sample only the disc's bounding box, relative to its centre, so every aspect shows the
# same planet.
half = int(np.ceil((R + 2 * CELL) / CELL))
def height(i: NDArray[np.int64], j: NDArray[np.int64]) -> NDArray[np.float64]:
dx, dy = (i - half) * CELL, (j - half) * CELL
d = np.hypot(dx, dy) / R
# the negative falloff past 0.85 R bunches the lines against the rim, like a limb
return noise.fbm(AT[0] + dx / SPAN, AT[1] + dy / SPAN, 4) - 0.9 * np.maximum(0.0, d - 0.85)
field = sample_field(height, 2 * half, 2 * half)
origin = c - (half * CELL, half * CELL)
with s.clip() as disc:
disc.add(P().circle(c, R))
with (
s.group(clip_path=disc.ref),
s.buckets(TONES, "stroke", stroke_width=1.6, stroke_linejoin="round") as lines,
):
for k, level in enumerate(LEVELS):
for line in iso_lines(field, level, cell=CELL, origin=origin):
if len(line) > 3:
lines[k].poly(line)
s.stroke(P().circle(c, R + 18), UI, 2)
s.stroke(P().circle(c, R), ACCENT, 3)
Run it yourself
$ git clone https://github.com/nickolaj-jepsen/walldye && cd walldye$ uv run walldye render eclipse-contours --theme fireproof -o eclipse-contours-fireproof-16x9.svg