click to wipe

·Playground

Displacement wipe.

Click to transition. A shader that wipes between two grades of the same image along an edge torn by noise, with a bright seam running the boundary.

How it works

01 Two grades from one texture

There is only one image loaded, a single sampler2D. Grade A is the plain sampled colour. Grade B is a duotone derived from the same sample: each pixel's luminance is remapped to a two-colour palette (deep aubergine in the shadows, warm cream in the highlights). The grades live entirely in the fragment shader; no second asset, no second draw call.

02 Noise-displaced wipe edge

The wipe progresses left to right via u_progress (0 = A, 1 = B). The transition edge is not a straight vertical line. It is displaced by a four-octave fractional Brownian motion field. Each pixel computes its own threshold (uv.x + fbm(uv)), so the boundary tears and flows organically. A smoothstep window on either side of the edge gives a soft blend zone. A thin bright seam sits exactly at the wipe front and carries an animated shimmer that pulses along its length, then fades as the transition completes.

// One texture, two grades ─────────────────────────────────
vec3 colorA = texture2D(u_image, uv).rgb;    // plain sample
vec3 colorB = duotone(colorA);               // aubergine → cream

// Noise-displaced wipe edge (4-octave FBM on the diagonal)
float disp   = fbm(uv * 3.5) * 0.35;
float edge   = uv.x + disp;
float reveal = smoothstep(edge - 0.025, edge + 0.025, u_progress);

// Thin seam with an animated shimmer — disappears at 0 and 1
float seam   = smoothstep(0.04, 0.0, abs(u_progress - edge))
             * smoothstep(0.01, 0.06, u_progress)
             * smoothstep(0.99, 0.94, u_progress);
vec3 col = mix(colorA, colorB, reveal);
col = mix(col, vec3(1.0, 0.97, 0.88), seam * 0.90);

03 Eased toggle

Clicking captures the current interpolated position as the new start, flips the target, and records a timestamp. Each RAF frame calls an ease-in-out cubic to interpolate from start to target over 0.9 seconds, so you can click mid-transition and it reverses smoothly from wherever it is. Under prefers-reduced-motion the jump is instant; the shader draws once and the RAF loop is never started.

A self-contained Svelte action, <canvas use:wipe>. One texture, one pass, FBM-displaced edge. Open to borrow.