Skip to content

Drop

A drop of radius rr falls at centre CC. Everything already on the water is pushed outward so that the area it occupies is conserved: a ring at distance ρ\rho from the centre moves to ρ2+r2\sqrt{\rho^2 + r^2}. The inverse lookup the shader evaluates, for points outside the new drop, is

Psrc=C+(P−C) 1−r2∥P−C∥2for ∥P−C∥≥r,P_{src} = C + (P - C)\,\sqrt{1 - \frac{r^2}{\lVert P - C \rVert^2}} \qquad \text{for } \lVert P - C \rVert \ge r ,

and for ∥P−C∥<r\lVert P - C \rVert < r the pass writes the new ink phase and the local radial coordinate directly — the fresh ink, not a lookup.

Six drops of radius r on each cluster, one per step — watch every earlier ring thin and spread as the next lands.open full size ↗
  • Exact and area-preserving. The map is a closed form; there is no step size and nothing to sub-step. The area displaced outward is exactly πr2\pi r^2, which is what makes concentric drops read as rings of equal area, thinner as they go out — the suminagashi look.
  • Strike → radius ∝ √velocity. Perceptual scaling: ink area tracks velocity, so a doubled velocity doubles the splash, not the diameter.
  • Ink phase in parity form. The texel stores ink=1+(counter mod 2)+radial∈[1,3)\text{ink} = 1 + (\text{counter} \bmod 2) + \text{radial} \in [1, 3), water = 0. Any two field values interpolate across at most one band threshold, so half-float filtering never speckles a seam however many drops fall. The hue selector rides in the fourth channel from the drop counter, which re-bases on every paper dip.
  • Strike (Note On) on every layout — the drop at the note’s position, or at all three echo rows on Jankó.

  • Pressure feed (channel pressure with press_mode = 0, the default): while pressure > 0 the voice’s drop keeps growing. Because a centre expansion of radius rr moves an existing boundary RR only to R2+r2\sqrt{R^2 + r^2}, fixed steps would visibly stall; the voice tracks its nominal boundary RR and converts the wanted growth ΔR\Delta R into the emitted pass radius r=(R+ΔR)2−R2r = \sqrt{(R + \Delta R)^2 - R^2}. Same operator, physically meaningful growth rate, deliberately unbounded — sustained pressure can flood the sheet, which is the Osmose behaviour.

    Same operator, two behaviours. Top-left: a note re-struck five times — separate drops, rings. Bottom-right: one note held under channel pressure — one band whose boundary keeps growing, no new ring.open full size ↗

    The difference is the whole point of the feed: a re-struck note lays a new ring each time (new parity, new hue), while a held note grows the ring it already owns — the expansion is emitted at the voice’s own centre with the boundary-growth radius, so the band widens instead of multiplying.

  • Breath (wind mode) uses the same conversion but relaxes toward a breath-proportional width: a twenty-second legato line stays a line.

  • Marble mode: a tap or a click. And, since v0.6, the pressure gesture: a long press (Shift + right drag with a mouse) lays a drop and then feeds it — hold or push up and the band widens by the same boundary growth; the pass is sumi_add_drop with the FEED layer, whose interior inherits the band already under the centre instead of laying a new ring.

r is the drop radius in canvas heights; n is how many drops fall on each cluster in turn. In the feed scene v is the strike velocity (the initial radius), p the channel-pressure value held, t how many frames it is held. Every scene has ⏱, the frames between steps — set it to 0 for the result alone, raise it to watch the mathematics work.

midi-sink 2.0.0-rc.5 · AGPL-3.0 · source