Jewel-tone paint rivers bleed from the image's own colors, flowing from a light stain to a full digital flood.
GLSL fragment shader
The effect's own code. The uniforms and helpers above it — uTex, uFeedback, the depth proxy, the frame ring, depthAt(), timeAt() — are the same header every Ether-MOSH shader opens with, and are documented once on the registry rather than reprinted on all 143 pages.
void main(){ vec4 src = texture2D(uTex, vUv); // Local detail/edge density stands in for "how photoreal is this patch": // busy, high-contrast areas read as real; flat regions read as flat. // Rivers concentrate on the former until uAmount pushes into the top of // its range, where the gate relaxes and paint floods everywhere. vec2 texel = 1.0 / uResolution; float lx = dot(texture2D(uTex, vUv + vec2(texel.x, 0.0)).rgb - src.rgb, vec3(0.299,0.587,0.114)); float ly = dot(texture2D(uTex, vUv + vec2(0.0, texel.y)).rgb - src.rgb, vec3(0.299,0.587,0.114)); float detail = clamp((abs(lx) + abs(ly)) * 6.0, 0.0, 1.0); float detailGate = mix(detail, 1.0, smoothstep(0.75, 1.0, uAmount)); // Viscosity trades flow speed for river thickness: thin, fast rivers at // the low default (a "low viscosity liquid"), slow heavy pours as it climbs. float speed = mix(0.5, 0.08, uViscosity); float thick = mix(0.045, 0.14, uViscosity); float sc = mix(2.0, 5.0, 1.0 - uViscosity); float t = uTime * speed; float e = 0.02; // Curl of a scalar noise field is divergence-free, so paint advects along // smooth closed streamlines in every direction instead of smearing along // one axis -- see Ink Flow above for the same technique. vec2 p = vUv * sc; vec2 curl = vec2(noise(p + vec2(0.0, e) + t) - noise(p - vec2(0.0, e) + t), -(noise(p + vec2(e, 0.0) - t) - noise(p - vec2(e, 0.0) - t))) / (2.0 * e); float flow = noise(vUv * sc * 1.4 + curl * 1.8); // Coverage ramps steeply, not linearly, so low amounts stay a light // stain and only the top of the range floods the frame. float coverage = pow(uAmount, 1.6); float edge = mix(0.15, 0.85, coverage); float mask = (1.0 - smoothstep(edge - thick, edge + thick, flow)) * detailGate; // The trailing edge breaks into isolated puddle-drops instead of a hard // cutoff -- a bump just past the river's own reach. vec2 dc = floor(vUv * 22.0); float dropletHit = step(0.55, rand(dc)); float dropletBand = smoothstep(edge, edge + thick, flow) * (1.0 - smoothstep(edge + thick, edge + thick * 3.0, flow)); mask = clamp(mask + dropletHit * dropletBand * detailGate * smoothstep(0.12, 0.5, uAmount), 0.0, 1.0); // Colour re-samples live from a point advected along the same current, // so a river's hue drifts as it crosses different-coloured parts of the // image -- then snaps to the nearest of six jewel-tone primaries. vec2 pickUv = clamp(vUv + curl * 0.05, 0.0, 1.0); vec3 hsv = rgb2hsv(texture2D(uTex, pickUv).rgb); hsv.x = floor(hsv.x * 6.0 + 0.5) / 6.0; hsv.y = clamp(mix(hsv.y, 1.0, 0.65 + coverage * 0.35), 0.0, 1.0); hsv.z = clamp(mix(hsv.z, 1.0, 0.3), 0.0, 1.0); vec3 jewel = hsv2rgb(hsv); // Photoreal <-> 8-bit VHS glitch is its own dial, independent of // coverage -- but the very top of uAmount also forces it in, so the // flood regime looks like it's coming apart rather than just bigger. float glitchAmt = clamp(uGlitch + smoothstep(0.72, 1.0, uAmount) * 0.6, 0.0, 1.0); vec3 posterized = floor(jewel * 5.0) / 4.0; vec3 split = vec3( texture2D(uTex, pickUv + vec2(0.006, 0.0) * glitchAmt).r, texture2D(uTex, pickUv).g, texture2D(uTex, pickUv - vec2(0.006, 0.0) * glitchAmt).b ); float scan = step(0.5, fract((vUv.y + uTime * 0.6) * uResolution.y * 0.12)); vec3 glitchLook = mix(posterized, split, 0.4) * mix(1.0, 0.3 + scan * 1.3, glitchAmt); vec3 paint = mix(jewel, glitchLook, glitchAmt); gl_FragColor = vec4(mix(src.rgb, paint, mask * clamp(uAmount * 1.4, 0.0, 1.0)), src.a); }