Paw Trail
của MusicBar, thanh tiến trình
Bé mèo lon ton đi tới chỗ đang phát, để lại dấu chân mờ dần phía sau, cứ tới nhịp là nhảy lên một cái và bật ra một trái tim nhỏ.
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 94d39cf30cdad24dcb0da6af34a1bad1029b72c76f4bc263ee8b4ff265a2c78f
//! name: Paw Trail
//! author: MusicBar
//! kind: progress
//! description: A little cat trots to the playhead leaving a trail of paw prints that fade behind it, and on every beat it hops and a heart pops up.
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);
}
// Smooth minimum: melts the head into the body so there is a neck.
float smin(float a, float b, float k) { float h = saturate(0.5 + 0.5 * (b - a) / k); return lerp(b, a, h) - k * h * (1.0 - h); }
// Distance to a capsule from a to b with radius r.
float capsule(float2 p, float2 a, float2 b, float r)
{
float2 pa = p - a;
float2 ba = b - a;
return length(pa - ba * saturate(dot(pa, ba) / dot(ba, ba))) - r;
}
// Distance to a triangle (negative inside).
float tri(float2 p, float2 p0, float2 p1, float2 p2)
{
float2 e0 = p1 - p0, e1 = p2 - p1, e2 = p0 - p2;
float2 v0 = p - p0, v1 = p - p1, v2 = p - p2;
float2 q0 = v0 - e0 * saturate(dot(v0, e0) / dot(e0, e0));
float2 q1 = v1 - e1 * saturate(dot(v1, e1) / dot(e1, e1));
float2 q2 = v2 - e2 * saturate(dot(v2, e2) / dot(e2, e2));
float s = sign(e0.x * e2.y - e0.y * e2.x);
float2 d = min(min(float2(dot(q0, q0), s * (v0.x * e0.y - v0.y * e0.x)), float2(dot(q1, q1), s * (v1.x * e1.y - v1.y * e1.x))), float2(dot(q2, q2), s * (v2.x * e2.y - v2.y * e2.x)));
return -sqrt(d.x) * sign(d.y);
}
// One leg: hip to paw with a bend, the paw lifting while it swings forward.
float leg(float2 p, float2 hip, float phase, float bendX, float r)
{
float2 paw = float2(hip.x + 0.02 + 0.085 * cos(phase), 0.035 + 0.07 * max(0.0, -sin(phase)));
float2 knee = (hip + paw) * 0.5 + float2(bendX, 0.0);
float d = min(capsule(p, hip, knee, r * 1.25), capsule(p, knee, paw, r));
return min(d, length((p - paw - float2(0.015, -0.005)) / float2(1.0, 0.7)) * 0.7 - 0.03);
}
// A heart, about one unit tall from its tip at the origin.
float heart(float2 p)
{
p.x = abs(p.x);
float2 a = p - float2(0.25, 0.75);
float2 b = p - 0.5 * max(p.x + p.y, 0.0);
float2 c = p - float2(0.0, 1.0);
return p.y + p.x > 1.0 ? length(a) - 0.3536 : sqrt(min(dot(c, c), dot(b, b))) * sign(p.x - p.y);
}
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 aa = 0.6 / u; // half a pixel, in bar heights
float stepT = time * 9.0;
float hop = 0.17 * 4.0 * beat * (1.0 - beat);
float2 p = (px - float2(head, u * 0.1)) / u - float2(0.0, hop + 0.012 * cos(stepT * 2.0));
float3 acc = float3(0, 0, 0);
float cover = 0;
// The trail: paw prints alternating left and right, toes forward, fading with age and pulsing with the music.
float ps = u * 0.36;
float n = floor(px.x / ps);
float side = frac(n * 0.5) < 0.25 ? 1.0 : -1.0;
float pulse = 1.0 + 0.3 * spectrum(frac(n * 0.618) * 0.5);
float2 pq = (px - float2((n + 0.5) * ps, u * (0.27 + 0.08 * side))) / (u * pulse);
float padD = length(pq * float2(1.15, 0.95)) - 0.055;
float toes = 1e4;
[unroll] for (int t = 0; t < 4; t++)
{
float ang = -0.95 + t * 0.633;
toes = min(toes, length(pq - float2(cos(ang), sin(ang)) * 0.1) - 0.026);
}
float printD = min(padD, toes);
float printA = smoothstep(aa, -aa, printD) * step((n + 0.5) * ps, head - u * 0.75);
float age = saturate((head - px.x) / (u * 16.0));
float3 ink = lerp(colorB.rgb, colorA.rgb, 0.3 + 0.3 * age);
ink = lerp(ink, colorA.rgb * 0.5, smoothstep(-2.5 * aa, 0.0, printD) * 0.7);
layer(acc, cover, ink, printA * lerp(0.92, 0.28, age));
// The rest of the song: a faint dotted path ahead.
float dots = smoothstep(1.3, 0.3, length(float2((frac(px.x / ps) - 0.5) * ps, px.y - u * 0.27)));
layer(acc, cover, lerp(colorB.rgb, colorA.rgb, 0.5), dots * step(head + u * 0.45, px.x) * 0.3);
// The far legs, a shade darker, behind the body.
float farD = min(leg(p, float2(-0.1, 0.27), stepT + 3.1416, 0.012, 0.036), leg(p, float2(-0.38, 0.28), stepT, -0.035, 0.04));
// The cat: body, head, ears, near legs and a curling tail that swishes.
float body = capsule(p, float2(-0.4, 0.3), float2(-0.08, 0.32), 0.12);
float headD = (length((p - float2(0.07, 0.44)) / float2(0.15, 0.13)) - 1.0) * 0.13;
float earB = tri(p, float2(-0.06, 0.52), float2(0.07, 0.55), float2(-0.02, 0.67)) - 0.012;
float earF = tri(p, float2(0.07, 0.55), float2(0.19, 0.52), float2(0.16, 0.66)) - 0.012;
float tail = 1e4;
float2 tp = float2(-0.5, 0.34);
float ta = 2.3;
[unroll] for (int i = 0; i < 4; i++)
{
ta -= 0.42 - 0.28 * sin(time * 3.4 - i * 0.9 + 0.6 * level);
float2 tn = tp + float2(cos(ta), sin(ta)) * 0.1;
tail = min(tail, capsule(p, tp, tn, 0.042 - i * 0.004));
tp = tn;
}
float nearD = min(leg(p, float2(-0.08, 0.27), stepT, 0.012, 0.038), leg(p, float2(-0.4, 0.28), stepT + 3.1416, -0.035, 0.042));
float cat = min(min(smin(body, headD, 0.06), min(earB, earF)), min(tail, nearD));
// A soft light behind the cat so it holds up on a dark taskbar, and a shadow on the ground.
layer(acc, cover, colorA.rgb, exp(-max(min(cat, farD), 0.0) / 0.07) * 0.22 * step(0.0, min(cat, farD)));
layer(acc, cover, float3(0, 0, 0), smoothstep(0.02, -0.02, length((p + float2(0.17, hop + 0.012)) / float2(0.32, 0.035)) - 1.0) * 0.25);
float3 fur = colorA.rgb, outline = colorA.rgb * 0.32;
layer(acc, cover, fur * 0.62, smoothstep(aa, -aa, farD));
layer(acc, cover, outline, smoothstep(aa, -aa, farD) * smoothstep(-2.0 * aa, 0.0, farD) * 0.8);
// Fur shading: lit along the back, a lighter belly and muzzle, tabby stripes across the back.
float belly = smoothstep(0.31, 0.2, p.y) * step(p.x, 0.0) + smoothstep(0.1, 0.17, p.x) * smoothstep(0.47, 0.4, p.y);
float3 c = lerp(fur, lerp(fur, float3(1, 0.97, 0.92), 0.65), saturate(belly));
float stripe = smoothstep(0.24, 0.1, abs(frac(p.x * 7.0 + p.y * 1.8) - 0.5)) * smoothstep(0.35, 0.42, p.y) * step(p.x, 0.0) * step(0.0, tail);
c = lerp(c, fur * 0.68, stripe * 0.8);
c *= 0.88 + 0.22 * smoothstep(0.25, 0.5, p.y);
layer(acc, cover, c, smoothstep(aa, -aa, cat));
// Inner ears, cheek blush, eye (it blinks now and then), nose and whiskers.
float inner = min(tri(p, float2(-0.03, 0.55), float2(0.05, 0.56), float2(-0.015, 0.63)), tri(p, float2(0.1, 0.555), float2(0.17, 0.54), float2(0.155, 0.62)));
layer(acc, cover, lerp(colorC.rgb, float3(1, 0.75, 0.8), 0.5), smoothstep(aa, -aa, inner) * 0.85);
layer(acc, cover, colorC.rgb, smoothstep(0.035, 0.0, length(p - float2(0.11, 0.395))) * 0.45);
float blink = lerp(1.0, 0.15, step(0.95, frac(time * 0.31)));
float eye = length((p - float2(0.135, 0.465)) / float2(0.026, 0.034 * blink)) - 1.0;
layer(acc, cover, float3(0.07, 0.05, 0.05), smoothstep(aa, -aa, eye * 0.028));
layer(acc, cover, float3(1, 1, 1), smoothstep(aa * 1.6, 0.0, length(p - float2(0.142, 0.478)) - 0.006) * blink);
layer(acc, cover, lerp(colorC.rgb, float3(1, 0.6, 0.7), 0.5), smoothstep(aa, -aa, length((p - float2(0.218, 0.43)) / float2(1.0, 0.75)) - 0.018));
float wh = min(capsule(p, float2(0.2, 0.415), float2(0.34, 0.44), 0.0), capsule(p, float2(0.2, 0.405), float2(0.33, 0.38), 0.0));
layer(acc, cover, float3(1, 1, 1), smoothstep(aa * 1.6, 0.0, wh) * 0.7);
layer(acc, cover, outline, smoothstep(aa, -aa, cat) * smoothstep(-2.2 * aa, -0.2 * aa, cat) * 0.85);
// On the beat a heart pops up in front of the face and floats away.
float hs = 0.22 * (0.6 + 0.4 * sqrt(beat));
float2 hq = ((px - float2(head, 0.0)) / u - float2(0.47, 0.4 + 0.2 * (1.0 - beat))) / hs;
float hd = heart(hq) * hs;
float hon = saturate(beat * 3.0);
layer(acc, cover, colorC.rgb, exp(-max(hd, 0.0) / 0.05) * beat * 0.5);
layer(acc, cover, colorC.rgb * 0.45, smoothstep(aa, -aa, hd - 1.6 * aa) * hon);
float3 hc = lerp(colorC.rgb, float3(1, 1, 1), 0.45 * smoothstep(0.03, 0.0, length(hq - float2(-0.22, 0.72)) * hs));
layer(acc, cover, hc, smoothstep(aa, -aa, hd + 0.4 * aa) * hon);
return paint(acc / max(cover, 0.001), cover);
}