Koi Pond

by MusicBar, progress bar

A lucky koi swims calmly to the playhead through a teal pond with lily pads and floating petals, leaving ripples behind it.

70 downloads Download file, 7.7 KB
How it installs, its SHA-256 and its code

Click Apply: MusicBar downloads it, checks its SHA-256 and puts it on the taskbar, or just puts it on if it already has it. Needs MusicBar 1.8 or newer.

SHA-256 26d5e7393fc85ab446a3de7502cd293095520f77941fde7921afe7b0ff1b6661

//! name: Koi Pond
//! author: MusicBar
//! kind: progress
//! description: A lucky koi swims calmly to the playhead through a teal pond with lily pads and floating petals, leaving ripples behind it.

float hash1(float n)
{
    n = frac(n * 0.1031);
    n *= n + 33.33;
    n *= n + n;
    return frac(n);
}

void layer(inout float3 acc, inout float cover, float3 rgb, float a)
{
    a = saturate(a);
    acc = rgb * a + acc * (1.0 - a);
    cover = a + cover * (1.0 - a);
}

float2 rot(float2 p, float a)
{
    float c = cos(a);
    float s = sin(a);
    return float2(c * p.x + s * p.y, -s * p.x + c * p.y);
}

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float2 px = float2(uv.x * size.x, rise(uv) * size.y);   // pixels: along the bar, up from the screen edge (seen from above)
    float u = size.y;
    float head = progress * size.x;
    float L = u * 1.9;                                        // koi length, nose to tail root
    float2 nose = float2(head, u * (0.5 + 0.08 * sin(time * 0.7)));

    float3 acc = float3(0, 0, 0);
    float cover = 0;

    // The pond: deep teal where the koi has been, only a thin wash ahead, with caustic light dancing on it.
    float played = smoothstep(head + u * 0.2, head - L * 0.4, px.x);
    float2 w = px / u;
    float cau = abs(sin(w.x * 2.7 + sin(w.y * 3.1 + time * 0.9) * 1.4 + time * 0.5) + sin(w.y * 3.7 - sin(w.x * 2.3 - time * 0.7) * 1.3));
    cau = pow(saturate(1.0 - cau * 0.6), 4.0) * 0.85;
    float edge = smoothstep(0.0, u * 0.12, px.y) * smoothstep(u, u * 0.88, px.y);
    float3 water = lerp(float3(0.02, 0.2, 0.24), float3(0.05, 0.36, 0.4), smoothstep(0.0, u, px.y));
    water = lerp(water, colorB.rgb * 0.35, 0.3);
    layer(acc, cover, water, edge * lerp(0.16, 0.8, played));
    layer(acc, cover, lerp(float3(0.55, 0.95, 0.9), colorB.rgb, 0.25), cau * edge * lerp(0.08, 0.32, played));

    // Ripple rings left behind in the played part, one ring set per cell, spreading and fading.
    float rc = floor(px.x / (u * 1.3));
    float rh = hash1(rc * 4.3 + 1.0);
    float2 rcen = float2((rc + 0.5) * u * 1.3, u * (0.3 + 0.4 * hash1(rc * 2.1)));
    float rph = frac(time * 0.35 + rh);
    float rd = length(px - rcen) - rph * u * 0.9;
    float rings = smoothstep(1.4, 0.0, abs(rd)) + 0.5 * smoothstep(1.2, 0.0, abs(rd + u * 0.12));
    layer(acc, cover, float3(0.75, 1.0, 0.97), rings * (1.0 - rph) * step(rcen.x, head - L) * 0.4 * edge);

    // The koi's body frame: s runs from the nose (0) to the tail root (1), the spine swims in an S
    // that grows toward the tail.
    float2 q = px - nose;
    float s = -q.x / L;
    float swim = time * 3.6;                                    // an unhurried swim, whatever the music does
    float bend = u * (0.03 + 0.17 * s * s) ;
    float spine = bend * sin(s * 4.2 - swim);
    float t = saturate(s);
    float hw = u * 0.21 * sqrt(t) * pow(saturate(1.0 - t * 0.8), 1.2) / 0.6;
    float v = (q.y - spine) / max(hw, 0.001);
    float bodyD = abs(q.y - spine) - hw;
    bodyD = s < 0.0 ? length(float2(q.x, q.y - spine)) : bodyD;
    bodyD = s > 1.0 ? length(float2(q.x + L, q.y - spine)) - hw : bodyD;

    // The shadow on the pond floor.
    float shD = abs(q.y + u * 0.1 - spine) - hw;
    layer(acc, cover, float3(0.0, 0.05, 0.07), smoothstep(u * 0.08, -u * 0.04, shD) * step(-0.05, s) * step(s, 1.05) * 0.4);

    // Tail fin: a fan past the tail root that sways with the spine.
    float tAng = cos(4.2 - swim) * 0.35;
    float2 tq = rot(q - float2(-L * 0.97, bend * sin(4.2 - swim)), -tAng);
    float fan = -tq.x;
    float ay = abs(tq.y);
    float lobe = length(float2(fan - u * 0.19, (ay - u * 0.12) * 1.3)) - u * 0.145;
    float tailD = max(min(lobe, max(ay - u * 0.06 - fan * 0.9, fan - u * 0.2)), -fan);
    float tail = smoothstep(0.6, -0.6, tailD);
    float rays = 0.9 + 0.1 * sin(atan2(tq.y, fan + u * 0.05) * 16.0);
    float tip = saturate(fan / (u * 0.36));
    layer(acc, cover, lerp(float3(1, 1, 1), colorA.rgb, 0.08 + 0.3 * tip * tip) * rays, tail * (1.0 - 0.3 * tip));

    // Pectoral fins: two soft fans behind the head, sweeping in and out.
    float fa = 2.1 + 0.3 * sin(time * 2.2);
    float2 fq = q - float2(-L * 0.3, spine);
    float2 f1 = rot(float2(fq.x, abs(fq.y) - hw * 0.0), fa);
    float fin = length(float2(f1.x - u * 0.13, f1.y * 2.0)) - u * 0.12;
    float fins = smoothstep(0.6, -0.6, fin);
    float finRay = 0.8 + 0.2 * sin(atan2(f1.y, f1.x) * 12.0);
    layer(acc, cover, lerp(float3(1, 1, 1), colorA.rgb, 0.2) * finRay, fins * 0.7);

    // The body: white, rounded (lit along the back), with colorA patches and a few ink spots.
    float body = smoothstep(0.6, -0.6, bodyD);
    float round = sqrt(saturate(1.0 - v * v));
    float patch = sin(s * 13.0 - 1.9) + 0.55 * sin(v * 2.4 + s * 9.0) - 0.9 * v * v - 0.3;
    patch = max(patch * step(s, 0.82), 1.6 - length(float2((s - 0.1) * 6.0, v * 1.3)) * 1.6);
    float red = smoothstep(0.1, 0.3, patch);
    float ink = smoothstep(0.075, 0.045, length(float2(s - 0.55, (v - 0.35) * 0.18))) + smoothstep(0.06, 0.035, length(float2(s - 0.72, (v + 0.3) * 0.16)));
    float3 kc = lerp(float3(0.97, 0.96, 0.93), colorA.rgb, red);
    kc = lerp(kc, float3(0.08, 0.08, 0.1), saturate(ink));
    kc *= 0.62 + 0.38 * round;
    kc += float3(1, 1, 1) * smoothstep(0.25, 0.0, abs(v + 0.15)) * 0.22 * step(0.05, s);
    layer(acc, cover, kc, body);

    // Eyes on either side of the head, and a darker rim so the koi holds its shape on a light taskbar.
    float eye = smoothstep(u * 0.04, u * 0.02, length(float2(q.x + L * 0.1, abs(q.y - spine) - hw * 0.62)));
    layer(acc, cover, float3(0.05, 0.05, 0.06), eye * body);
    layer(acc, cover, lerp(float3(0.2, 0.25, 0.28), colorA.rgb * 0.4, red), smoothstep(1.2, 0.2, abs(bodyD + 0.5)) * 0.45);


    // Lily pads near the banks, with a notch and veins; some carry a small lotus bud.
    float pc = floor(px.x / (u * 2.3));
    float ph = hash1(pc * 5.7 + 3.0);
    float pr = u * (0.2 + 0.1 * hash1(pc * 1.3));
    float2 pcen = float2((pc + 0.25 + 0.5 * hash1(pc * 8.1)) * u * 2.3, lerp(u * 0.1, u * 0.9, step(0.5, ph)) + sin(time * 0.6 + ph * 9.0) * u * 0.02);
    float2 pq = rot(px - pcen, ph * 6.28 + 0.15 * sin(time * 0.5 + ph * 7.0));
    float pl = length(pq);
    float pang = atan2(pq.y, pq.x);
    float pd = max(pl - pr, -pl * sin(min(abs(pang) - 0.3, 1.5)));
    float hasPad = step(0.25, ph);
    float pad = smoothstep(0.6, -0.6, pd) * hasPad;
    float vein = smoothstep(0.9, 0.0, abs(frac(pang / 6.2832 * 9.0) - 0.5) * pl * 0.7) * smoothstep(pr * 0.15, pr * 0.4, pl) * 0.3;
    float3 padC = lerp(float3(0.14, 0.4, 0.17), float3(0.38, 0.68, 0.3), saturate(pq.y / pr * 0.5 + 0.5)) * (1.0 - vein);
    layer(acc, cover, float3(0.0, 0.08, 0.06), smoothstep(u * 0.05, -u * 0.02, length(pq + float2(u * 0.03, u * 0.05)) - pr) * 0.35 * hasPad);
    layer(acc, cover, padC, pad);
    layer(acc, cover, float3(0.62, 0.88, 0.5), smoothstep(1.2, 0.0, abs(pd + 0.8)) * pad * 0.6);
    float lotus = length(pq) - pr * 0.42 * (0.62 + 0.38 * abs(cos(pang * 3.0 + time * 0.3)));
    float bloom = smoothstep(0.6, -0.6, lotus) * step(0.78, ph);
    layer(acc, cover, lerp(colorC.rgb, float3(1, 1, 1), 0.45 - 0.4 * saturate(length(pq) / (pr * 0.42))), bloom);
    layer(acc, cover, float3(1.0, 0.85, 0.3), smoothstep(pr * 0.12, pr * 0.06, length(pq)) * step(0.78, ph));

    // Petals adrift on the surface, slowly turning.
    float2 dp = px + float2(time * u * 0.12, 0.0);
    float dc = floor(dp.x / (u * 0.9));
    float dh = hash1(dc * 6.1 + 7.0);
    float2 dq = rot(dp - float2((dc + 0.5) * u * 0.9, u * (0.15 + 0.7 * hash1(dc * 3.3))), time * (0.4 + dh) + dh * 6.0);
    float petal = smoothstep(0.6, -0.6, length(float2(dq.x, dq.y * 1.8)) - u * 0.07);
    layer(acc, cover, lerp(colorC.rgb, float3(1, 1, 1), 0.2), petal * step(0.45, dh) * edge * 0.9);

    return paint(acc / max(cover, 0.001), cover);
}