#version 300 es precision mediump float; in vec2 vTexCoord; in vec4 vColor; // x = offset strength (composite-UV units), y = ring phase 0 (center) .. 1 (rim) out vec4 fragColor; // one expanding shockwave ring, written as a radial UV-offset field. quads blend additively into // the RG16F distortion map, so overlapping ripples sum void main() { vec2 d = vTexCoord - vec2(0.5); float dist = length(d) * 2.0; // 0 at center, 1 at the quad rim if (dist < 0.001 || dist > 1.0) { fragColor = vec4(0.0); return; } float ring = dist - vColor.g; // signed distance to the ring front float band = exp(-(ring * ring) * 90.0); // thin gaussian shell float fade = 1.0 - vColor.g; // dies out as it reaches the rim // quad v runs top-down, composite v runs bottom-up — flip y so the push points outward on screen vec2 dir = vec2(d.x, -d.y) / (dist * 0.5); fragColor = vec4(dir * (band * fade * vColor.r), 0.0, 0.0); }