Kintsugi
Kintsugi, the craft of joining broken pottery with lacquer and powdered metal, leaves the repair visible.
Made with Claude Opus 5.5
- Technique
- flat shapes
- Inspired by
- Japanese art
- Shape
- Any screen
- Added
- 27 September 2026
Export
Shapecropped from 16:9
Across
Down
Scale
Crop
SizeThis browser can’t draw a file that large.
FormatThis browser can’t make WebP files.
Colors
- #1C1B1Abackground
- #DAD8CEforeground
- #CF6A4Caccent
Sources
Source code
wallpapers/
"""A bowl seen from above with kintsugi seams mending its cracks."""
import math
import numpy as np
from numpy.typing import NDArray
from shapely import get_coordinates
from shapely.geometry import LineString, Point
from shapely.ops import substring
from walldye import (
ACCENT,
ACCENT_1,
BG,
BG_ALT,
BG_DEEP,
UI,
UI_HI,
Canvas,
P,
Vec,
clamp,
design,
mix,
polar,
)
from walldye.field import Noise, gauss
from walldye.geom import ribbon
type Pts = NDArray[np.float64]
R, LIP, FOOT = 360, 16, 150 # bowl radius, rim band width, foot ring radius
# rim chip where the tee crack starts: angle (deg), half its span (deg), greatest depth
CHIP, CHIP_HALF, CHIP_DEPTH = 116, math.degrees(40 / R), 16
O = Vec(0, 0) # the bowl center, in the motif's units
def crack(n: Noise, row: float, p0: Vec, p1: Vec, amp: float, step: float = 3.0) -> Pts:
"""Points every ~`step` from p0 to p1, pushed sideways by up to ~`amp` of slow noise
(`n` read along x = `row`) that fades out at both ends."""
d = p1 - p0
length = abs(d)
t = np.linspace(0, 1, max(8, int(length / step)))
u = t * length
off = amp * (n(row, u / 170) + 0.35 * n(row + 9, u / 60)) * np.sin(np.pi * t) ** 0.5
return p0 + np.outer(t, d) + np.outer(off, d.perp() / length)
def tee_into(line: Pts, other: Pts) -> Pts:
"""`line` cut off at its first crossing with `other`, ending exactly on it."""
ls = LineString(line)
hits = get_coordinates(ls.intersection(LineString(other)))
k = min(ls.project(Point(p)) for p in hits)
return np.asarray(substring(ls, 0, k).coords, dtype=np.float64)
def lacquer(
n: Noise, pts: Pts, row: float, *, swell: Pts | None = None, taper: bool = False
) -> Pts:
"""Seam width at each point: about 4 with slow noise (`n` read along x = `row`), bulging over
~18 units around the vertex nearest `swell`, and narrowing toward the end when `taper`."""
along = np.concatenate([[0], np.cumsum(np.hypot(*np.diff(pts, axis=0).T))])
w = 4 + 0.9 * n(row, along / 190)
if swell is not None:
j = int(np.argmin(np.hypot(*(pts - swell).T)))
w += 1.4 * gauss(along - along[j], 18)
if taper:
w *= clamp(1.15 * (1 - along / along[-1]) ** 0.7, 0.3, 1)
return w
@design(aspects="any")
def draw(s: Canvas) -> None:
# right of center on a landscape screen; centered in the upper part of a portrait one
c = s.pick(landscape=(0.65625, 0.5), portrait=(0.5, 0.41))
def rim(deg: float, inset: float = 0) -> Vec:
return polar(O, R - inset, deg=deg)
with s.motif(c, R + 7 + math.hypot(14, 22)): # the cast shadow reaches furthest
s.fill(P().circle(Vec(14, 22), R + 6), BG_DEEP) # cast shadow, down and to the right
s.fill(P().circle(O, R), mix(BG_ALT, UI, 0.2))
s.stroke(P().circle(O, R - LIP / 2), mix(BG_ALT, UI, 0.35), LIP)
# the well: lit near the wall, falling to background tone toward the center, shaded away
# from the upper left
rw = R - LIP
well = s.radial_gradient([(0, BG), (0.4 * R / rw, BG), (1, BG_ALT)], O, rw)
s.fill(P().circle(O, rw), well)
shade = s.radial_gradient(
[(0, BG_DEEP, 0), (0.7, BG_DEEP, 0.1), (1, BG_DEEP, 0.6)], Vec(50, 60), R + 30
)
s.fill(P().circle(O, rw), shade)
foot = P().circle(O, FOOT)
s.fill(foot, BG_DEEP, opacity=0.3)
s.stroke(foot, UI, 1.2, opacity=0.5)
s.stroke(P().circle(O, R), UI, 1.2)
# rim catchlight across the upper left, fading out at both ends
glint = s.linear_gradient(
[(0, UI_HI, 0), (0.5, UI_HI, 0.9), (1, UI_HI, 0)], rim(175, 2.5), rim(275, 2.5)
)
s.stroke(P().arc(O, R - 2.5, deg=(175, 275)), glint, 2.4)
# one long meander rim to rim, one crack teeing into it, one short crack in from the rim
n = s.noise(4)
main = crack(n, 1.3, rim(214), rim(8), amp=34)
tee = tee_into(crack(n, 5.7, rim(CHIP), Vec(90, -200), amp=24), main)
short = crack(n, 8.1, rim(296), rim(296 + math.degrees(0.14), 135), amp=12)
seams = [
(main, lacquer(n, main, 2.2, swell=tee[-1])),
(tee, lacquer(n, tee, 6.4, swell=tee[-1])),
(short, lacquer(n, short, 9.9, taper=True)),
]
groove, seam = P(), P()
for pts, w in seams:
groove.poly(ribbon(pts, w + 2), closed=True)
seam.poly(ribbon(pts, w), closed=True)
s.fill(groove, BG_DEEP)
s.fill(seam, ACCENT)
# a sliver flaked off the rim where the tee crack starts, filled solid; deeper on the
# crack's side
edge = [
rim(
CHIP + CHIP_HALF * (1 - 2 * k),
CHIP_DEPTH * math.sin(math.pi * k) ** 0.9 * (1.05 - 0.1 * k),
)
for k in np.linspace(0, 1, 24)
]
s.fill(P().spline(edge).A(R, R, 0, 0, 1, edge[0]).Z(), ACCENT_1)"""A bowl seen from above with kintsugi seams mending its cracks."""
import math
import numpy as np
from numpy.typing import NDArray
from shapely import get_coordinates
from shapely.geometry import LineString, Point
from shapely.ops import substring
from walldye import (
ACCENT,
ACCENT_1,
BG,
BG_ALT,
BG_DEEP,
UI,
UI_HI,
Canvas,
P,
Vec,
clamp,
design,
mix,
polar,
)
from walldye.field import Noise, gauss
from walldye.geom import ribbon
type Pts = NDArray[np.float64]
R, LIP, FOOT = 360, 16, 150 # bowl radius, rim band width, foot ring radius
# rim chip where the tee crack starts: angle (deg), half its span (deg), greatest depth
CHIP, CHIP_HALF, CHIP_DEPTH = 116, math.degrees(40 / R), 16
O = Vec(0, 0) # the bowl center, in the motif's units
def crack(n: Noise, row: float, p0: Vec, p1: Vec, amp: float, step: float = 3.0) -> Pts:
"""Points every ~`step` from p0 to p1, pushed sideways by up to ~`amp` of slow noise
(`n` read along x = `row`) that fades out at both ends."""
d = p1 - p0
length = abs(d)
t = np.linspace(0, 1, max(8, int(length / step)))
u = t * length
off = amp * (n(row, u / 170) + 0.35 * n(row + 9, u / 60)) * np.sin(np.pi * t) ** 0.5
return p0 + np.outer(t, d) + np.outer(off, d.perp() / length)
def tee_into(line: Pts, other: Pts) -> Pts:
"""`line` cut off at its first crossing with `other`, ending exactly on it."""
ls = LineString(line)
hits = get_coordinates(ls.intersection(LineString(other)))
k = min(ls.project(Point(p)) for p in hits)
return np.asarray(substring(ls, 0, k).coords, dtype=np.float64)
def lacquer(
n: Noise, pts: Pts, row: float, *, swell: Pts | None = None, taper: bool = False
) -> Pts:
"""Seam width at each point: about 4 with slow noise (`n` read along x = `row`), bulging over
~18 units around the vertex nearest `swell`, and narrowing toward the end when `taper`."""
along = np.concatenate([[0], np.cumsum(np.hypot(*np.diff(pts, axis=0).T))])
w = 4 + 0.9 * n(row, along / 190)
if swell is not None:
j = int(np.argmin(np.hypot(*(pts - swell).T)))
w += 1.4 * gauss(along - along[j], 18)
if taper:
w *= clamp(1.15 * (1 - along / along[-1]) ** 0.7, 0.3, 1)
return w
@design(aspects="any")
def draw(s: Canvas) -> None:
# right of center on a landscape screen; centered in the upper part of a portrait one
c = s.pick(landscape=(0.65625, 0.5), portrait=(0.5, 0.41))
def rim(deg: float, inset: float = 0) -> Vec:
return polar(O, R - inset, deg=deg)
with s.motif(c, R + 7 + math.hypot(14, 22)): # the cast shadow reaches furthest
s.fill(P().circle(Vec(14, 22), R + 6), BG_DEEP) # cast shadow, down and to the right
s.fill(P().circle(O, R), mix(BG_ALT, UI, 0.2))
s.stroke(P().circle(O, R - LIP / 2), mix(BG_ALT, UI, 0.35), LIP)
# the well: lit near the wall, falling to background tone toward the center, shaded away
# from the upper left
rw = R - LIP
well = s.radial_gradient([(0, BG), (0.4 * R / rw, BG), (1, BG_ALT)], O, rw)
s.fill(P().circle(O, rw), well)
shade = s.radial_gradient(
[(0, BG_DEEP, 0), (0.7, BG_DEEP, 0.1), (1, BG_DEEP, 0.6)], Vec(50, 60), R + 30
)
s.fill(P().circle(O, rw), shade)
foot = P().circle(O, FOOT)
s.fill(foot, BG_DEEP, opacity=0.3)
s.stroke(foot, UI, 1.2, opacity=0.5)
s.stroke(P().circle(O, R), UI, 1.2)
# rim catchlight across the upper left, fading out at both ends
glint = s.linear_gradient(
[(0, UI_HI, 0), (0.5, UI_HI, 0.9), (1, UI_HI, 0)], rim(175, 2.5), rim(275, 2.5)
)
s.stroke(P().arc(O, R - 2.5, deg=(175, 275)), glint, 2.4)
# one long meander rim to rim, one crack teeing into it, one short crack in from the rim
n = s.noise(4)
main = crack(n, 1.3, rim(214), rim(8), amp=34)
tee = tee_into(crack(n, 5.7, rim(CHIP), Vec(90, -200), amp=24), main)
short = crack(n, 8.1, rim(296), rim(296 + math.degrees(0.14), 135), amp=12)
seams = [
(main, lacquer(n, main, 2.2, swell=tee[-1])),
(tee, lacquer(n, tee, 6.4, swell=tee[-1])),
(short, lacquer(n, short, 9.9, taper=True)),
]
groove, seam = P(), P()
for pts, w in seams:
groove.poly(ribbon(pts, w + 2), closed=True)
seam.poly(ribbon(pts, w), closed=True)
s.fill(groove, BG_DEEP)
s.fill(seam, ACCENT)
# a sliver flaked off the rim where the tee crack starts, filled solid; deeper on the
# crack's side
edge = [
rim(
CHIP + CHIP_HALF * (1 - 2 * k),
CHIP_DEPTH * math.sin(math.pi * k) ** 0.9 * (1.05 - 0.1 * k),
)
for k in np.linspace(0, 1, 24)
]
s.fill(P().spline(edge).A(R, R, 0, 0, 1, edge[0]).Z(), ACCENT_1)
Run it yourself
$ git clone https://github.com/nickolaj-jepsen/walldye && cd walldye$ uv run walldye render kintsugi --theme fireproof -o kintsugi-fireproof-16x9.svg