Domino Run

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

Hàng domino bóng loáng đổ dần tới chỗ đang phát, quân nào ngã xuống cũng lóe sáng một cái, chấm trên quân sáng theo nhạc, mấy quân còn đứng thì nảy lên theo nhịp.

8 lượt tải Tải file, 6.0 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 c6b14c9e811ffadd3bca2fb913a2c451b83e167b8cf53852807452d122c7e336

//! name: Domino Run
//! author: MusicBar
//! kind: progress
//! description: A row of glossy dominoes topples up to the playhead, each one landing with a clack of light, the pips glowing with the music and the tiles still standing hopping on the beat.

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

float box(float2 p, float2 b, float r)
{
    float2 q = abs(p) - b + r;
    return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - r;
}

// Is the pip at grid spot g (-1..1 each way) shown for a face with n pips, like real dice faces.
float pipOn(float2 g, float n)
{
    float odd = step(0.5, frac(n * 0.5));
    float diag = g.x * g.y;
    float on = (g.x == 0.0 && g.y == 0.0) ? odd : 0.0;
    on += (g.y == 0.0 && g.x != 0.0) ? step(5.5, n) : 0.0;
    on += diag < -0.5 ? step(1.5, n) : 0.0;
    on += diag > 0.5 ? step(3.5, n) : 0.0;
    return on;
}

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float2 px = float2(uv.x * size.x, (1.0 - uv.y) * size.y);  // pixels: along the bar, and up the screen so gravity holds on a top taskbar too
    float u = size.y;
    float head = progress * size.x;
    float w = u * 0.3;                                        // tile width, height and spacing
    float h = u * 0.62;
    float s = u * 0.58;
    float base = u * 0.1;

    // The chain: tile k is falling (gravity eases it in); each tile behind leans on the next one.
    float k = floor(head / s);
    float f = frac(head / s);
    float b0 = asin((s - w) / h) * f * f;
    float b1 = b0 + asin((s * cos(b0) - w) / h);
    float b2 = b1 + asin((s * cos(b1) - w) / h);
    float b3 = b2 + asin((s * cos(b2) - w) / h);
    float b4 = b3 + asin((s * cos(b3) - w) / h);
    float flat = acos(w / s);

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

    // A soft shadow along the ground under the row.
    layer(acc, cover, float3(0, 0, 0), smoothstep(u * 0.08, 0.0, abs(px.y - base + u * 0.01)) * 0.25);

    float cell = floor(px.x / s);
    [unroll] for (int stage = 0; stage < 2; stage++)
    {
        [unroll] for (int i = 0; i < 2; i++)
        {
            float j = cell - i;
            float n = k - j;
            float ang = n < 0.0 ? 0.0 : (n < 1.0 ? b0 : (n < 2.0 ? b1 : (n < 3.0 ? b2 : (n < 4.0 ? b3 : (n < 5.0 ? b4 : flat)))));
            float ahead = step(n, -0.5);
            float hop = ahead * u * 0.1 * beat * exp((n + 2.0) / 4.0) * step(n, -1.5);
            float2 pivot = float2(j * s + w, base + hop);
            float pick = frac(j / 3.0 + 0.01);
            float3 col = pick < 0.33 ? colorA.rgb : (pick < 0.66 ? colorB.rgb : colorC.rgb);
            float light = dot(col, float3(0.3, 0.59, 0.11));
            col *= lerp(1.0, 0.58, ahead);
            float sing = spectrum(frac(j * 0.123) * 0.6);

            if (stage == 0)
            {
                // The tile's depth: a darker slab just behind it, so it reads as a solid block.
                float2 lb = rot(px - pivot - float2(u * 0.04, u * 0.035), -ang) - float2(-w * 0.5, h * 0.5);
                layer(acc, cover, col * 0.42, smoothstep(0.6, -0.6, box(lb, float2(w, h) * 0.5, u * 0.05)));
            }
            else
            {
                float2 lp = rot(px - pivot, -ang) - float2(-w * 0.5, h * 0.5);
                float d = box(lp, float2(w, h) * 0.5, u * 0.05);
                float face = smoothstep(0.6, -0.6, d);

                // Glossy face: lighter toward the top, a bevel along the edge, a sheen across the upper corner.
                float3 c = col * (0.78 + 0.32 * (lp.y / h + 0.5));
                c = lerp(c, float3(1, 1, 1), smoothstep(-u * 0.03, 0.0, d) * 0.3);
                c = lerp(c, float3(1, 1, 1), smoothstep(u * 0.05, 0.0, abs(lp.x + lp.y * 0.6 - u * 0.12)) * 0.22);

                // The divider groove, its brass pin, and the pips (white, glowing with the music).
                float groove = smoothstep(1.2, 0.2, abs(lp.y)) * step(abs(lp.x), w * 0.36);
                c = lerp(c, col * 0.35, groove);
                c = lerp(c, lerp(colorC.rgb, float3(1, 0.9, 0.6), 0.5), smoothstep(u * 0.028, u * 0.016, length(lp)));
                float halfSign = lp.y > 0.0 ? 1.0 : -1.0;
                float count = floor(hash1(j * 7.3 + halfSign * 1.7 + 3.0) * 6.99);
                float sp = w * 0.27;
                float2 hq = float2(lp.x, lp.y - halfSign * h * 0.25);
                float2 g = clamp(floor(hq / sp + 0.5), -1.0, 1.0);
                float pd = length(hq - g * sp);
                float pip = smoothstep(u * 0.04, u * 0.028, pd) * pipOn(g, count);
                float3 pipC = light > 0.62 ? col * 0.28 : float3(1, 1, 1);
                pipC = lerp(pipC, float3(1, 1, 1), smoothstep(u * 0.02, 0.0, length(hq - g * sp + u * 0.01)) * 0.5);
                c = lerp(c, lerp(pipC, colorC.rgb, 0.25 * sing * (1.0 - ahead)), pip * lerp(1.0, 0.7, ahead));
                layer(acc, cover, c, face * lerp(1.0, 0.9, ahead));
                layer(acc, cover, lerp(colorC.rgb, float3(1, 1, 1), 0.6), exp(-pd / (u * 0.03)) * pipOn(g, count) * face * sing * 0.45 * (1.0 - ahead));
            }
        }
    }

    // The clack: a flash where the last tile just landed, brighter on the beat.
    float2 hit = float2((k - 1.0) * s + w, base) + float2(sin(b1), cos(b1)) * h;
    float2 hd = abs(px - hit);
    float clack = exp(-f * 5.0) * 0.8 + beat;
    float reach = u * (0.12 + 0.12 * beat);
    float star = exp(-length(hd) / (u * 0.07)) + (exp(-(hd.x * 7.0 + hd.y) / reach) + exp(-(hd.y * 7.0 + hd.x) / reach)) * 0.8;
    layer(acc, cover, colorC.rgb, exp(-length(hd) / (u * 0.2)) * clack * 0.35 * step(1.0, k));
    layer(acc, cover, lerp(colorC.rgb, float3(1, 1, 1), 0.65), star * clack * step(1.0, k));

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