Koi Pond

của MusicBar, thanh tiến trình

Một chú cá chép koi thong thả bơi tới chỗ đang phát giữa hồ nước xanh có lá sen và cánh hoa trôi, để lại những vòng gợn sóng phía sau.

70 lượt tải Tải file, 7.7 KB
Cách cài, mã SHA-256 và mã nguồn

Bấm Áp dụng: MusicBar tự tải về, kiểm tra mã SHA-256 rồi mặc lên taskbar; có rồi thì mặc luôn. Cần MusicBar 1.8 trở lên.

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);
}