Munch Munch
by MusicBar, progress bar
A round little critter chomps its way down a row of glowing pellets to the playhead, snapping its jaw wide on every beat.
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 98938ec4ae7f6e9ef02d0fa61b6b0cf653018ae1b97feef931856097397be6ba
//! name: Munch Munch
//! author: MusicBar
//! kind: progress
//! description: A round little critter chomps its way down a row of glowing pellets to the playhead, snapping its jaw wide on every beat.
// A steady random number for a whole number.
float hash1(float n) { return frac(sin(n * 127.1 + 311.7) * 43758.5453); }
// Turns a point around the origin by a (radians, counterclockwise).
float2 rot(float2 p, float a) { float c = cos(a), s = sin(a); return float2(c * p.x - s * p.y, s * p.x + c * p.y); }
// Signed distance to an ellipse with radii r (close enough near the edge).
float ellipse(float2 p, float2 r)
{
float k0 = length(p / r);
return k0 * (k0 - 1.0) / max(length(p / (r * r)), 0.0001);
}
float sdSeg(float2 p, float2 a, float2 b) { float2 pa = p - a, ba = b - a; return length(pa - ba * saturate(dot(pa, ba) / dot(ba, ba))); }
// Round-body shading: a sphere normal from the ellipse, a key light up front, a rim at the back.
float3 shade(float2 q, float2 c, float2 r, float3 base)
{
float2 s = (q - c) / r;
float z = sqrt(saturate(1.0 - dot(s, s)));
float3 n = normalize(float3(s, z * 0.9 + 0.05));
float dif = saturate(dot(n, normalize(float3(0.35, 0.7, 0.6))));
float spec = pow(saturate(dot(n, normalize(float3(0.25, 0.55, 1.0)))), 28.0);
float rim = pow(1.0 - z, 3.0) * saturate(0.4 - n.x);
return base * (0.34 + 0.85 * dif) + colorB.rgb * rim * 1.1 + spec * 0.55;
}
// Lays a color over what is there (premultiplied light, and how much of the pixel it covers).
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);
}
float4 main(float2 uv : TEXCOORD) : COLOR
{
float u = size.y; // everything is sized from the bar height
float2 px = float2(uv.x * size.x, rise(uv) * size.y); // pixels: along the bar, up from the screen edge
float head = progress * size.x;
float mid = 0.5 * u;
float3 acc = float3(0, 0, 0);
float cover = 0;
// Crumbs the critter leaves: sparkles that fall and fade behind it, then a faint dotted trail.
float gap = 0.5 * u, cw = 0.23 * u;
float k = floor(px.x / gap + 0.5), ci = floor(px.x / cw);
float h1 = hash1(ci), h2 = hash1(ci + 17.3), life = frac(time * 0.8 + h1);
float2 cd = abs(px - float2((ci + 0.2 + 0.6 * h2) * cw, mid + (h1 - 0.5) * 0.5 * u - life * life * 0.3 * u));
float spark = exp(-length(cd) / (0.022 * u)) + exp(-cd.x / 0.8 - cd.y / (0.05 * u)) + exp(-cd.y / 0.8 - cd.x / (0.05 * u));
float back = head - px.x;
float fresh = exp(-max(back, 0.0) / (2.6 * u)) * smoothstep(0.2 * u, 0.6 * u, back) * (1.0 - life);
layer(acc, cover, lerp(colorC.rgb, float3(1, 1, 1), 0.4), spark * fresh * step(0.45, h2) * (0.7 + 0.5 * level));
float ghost = smoothstep(0.03 * u, 0.012 * u, length(px - float2(k * gap, mid)));
layer(acc, cover, colorC.rgb, ghost * 0.22 * step(k * gap, head - 0.3 * u));
// Pellets ahead, bobbing on the center line and swelling with the spectrum; every 8th is a music note.
float spec = spectrum(frac(k / 12.0) * 0.85);
float big = step(frac(k / 8.0 + 0.01), 0.05);
float2 pc = float2(k * gap, mid + 0.025 * u * sin(time * 3.0 + k * 0.8));
float ahead = smoothstep(head + 0.02 * u, head + 0.12 * u, pc.x);
float pr = 0.045 * u * (0.8 + 0.6 * spec), pd = length(px - pc), small = (1.0 - big) * ahead;
float cellFade = smoothstep(0.25 * u, 0.14 * u, abs(px.x - pc.x)); // glows stay inside their own cell
layer(acc, cover, colorC.rgb, small * exp(-pd / (0.07 * u)) * (0.35 + 0.4 * spec) * cellFade);
layer(acc, cover, colorC.rgb * 0.3, small * smoothstep(0.5, -0.5, pd - pr - 1.0));
layer(acc, cover, lerp(colorC.rgb, float3(1, 1, 1), 0.45 * spec), small * smoothstep(0.5, -0.5, pd - pr));
float2 nq = (px - pc) / (u * (1.0 + 0.35 * beat));
float note = ellipse(rot(nq - float2(-0.035, -0.07), 0.45), float2(0.075, 0.052));
note = min(note, min(sdSeg(nq, float2(0.032, -0.065), float2(0.032, 0.15)) - 0.014, sdSeg(nq, float2(0.032, 0.15), float2(0.1, 0.07)) - 0.017));
float nglow = exp(-max(length(nq - float2(0.0, 0.02)) - 0.06, 0.0) / 0.09);
layer(acc, cover, colorC.rgb, big * ahead * nglow * cellFade * (0.45 + 0.45 * beat));
layer(acc, cover, lerp(colorC.rgb, float3(1, 1, 1), 0.3 + 0.4 * beat), big * ahead * smoothstep(0.5, -0.5, note * u));
// The critter: q is in bar heights, origin at the mouth, facing right. It bobs with its steps and squashes on the beat.
float stepT = time * 15.0 + 1.5 * level, bob = abs(sin(stepT));
float2 q = (px - float2(head, 0.55 * u + 0.025 * u * bob)) / u / float2(1.0 + 0.05 * beat, 1.0 - 0.07 * beat);
float2 B = float2(-0.12, -0.03), R = float2(0.38, 0.29), H = float2(-0.2, -0.03); // body center, radii, jaw hinge
// The jaw: opens and snaps shut four times a second, and gapes on a beat.
float c = frac(time * 4.0);
float ang = max(0.42 * smoothstep(0.0, 0.6, c) * (1.0 - smoothstep(0.72, 0.9, c)), 0.8 * beat);
float2 qj = rot(q - H, ang) + H; // the pixel seen in the jaw's closed pose
float dBody = ellipse(q - B, R), dQuad = max(H.x - q.x, q.y - H.y);
float dUpper = max(dBody, -dQuad);
float dJaw = max(ellipse(qj - B, R), max(H.x - qj.x, qj.y - H.y));
float dMouth = max(max(dBody, dQuad), H.y - qj.y);
// Two stubby feet pattering under it, and a sprout with a glowing bud that lags the bobbing and swings on the beat.
float2 fA = float2(0.02 + 0.05 * sin(stepT), -0.35 + 0.05 * saturate(cos(stepT)));
float2 fB = float2(-0.25 - 0.05 * sin(stepT), -0.35 + 0.05 * saturate(-cos(stepT)));
float dFootA = ellipse(q - fA, float2(0.1, 0.06)), dFootB = ellipse(q - fB, float2(0.1, 0.06));
float2 bud = float2(-0.07 + 0.035 * sin(stepT - 1.2) - 0.04 * beat, 0.35 - 0.02 * bob);
float dStem = sdSeg(q, float2(-0.16, 0.22), bud) - 0.016;
// A soft self-lit halo and a dark outline keep it readable on light or dark taskbars.
float dAll = min(min(min(dUpper, dJaw), min(min(dFootA, dFootB), dMouth)), dStem);
layer(acc, cover, colorA.rgb, exp(-max(dAll, 0.0) / 0.1) * (0.28 + 0.25 * level));
layer(acc, cover, colorA.rgb * 0.18, smoothstep(0.5, -0.5, dAll * u - 1.3));
layer(acc, cover, shade(q, fB, float2(0.1, 0.06), colorA.rgb * 0.6), smoothstep(0.5, -0.5, dFootB * u));
layer(acc, cover, shade(q, fA, float2(0.1, 0.06), colorA.rgb * 0.85), smoothstep(0.5, -0.5, dFootA * u));
// Inside the mouth: a dark throat, a tongue on the jaw, and a row of small teeth top and bottom.
float throat = saturate(length(q - H) / 0.32);
float3 mouthCol = lerp(float3(0.16, 0.02, 0.05), float3(0.55, 0.1, 0.16), throat);
float tongue = ellipse(qj - float2(0.04, H.y - 0.025), float2(0.16, 0.05));
mouthCol = lerp(mouthCol, float3(1.0, 0.42, 0.5) * (0.55 + 0.55 * throat), smoothstep(0.5, -0.5, tongue * u));
float tx = abs(frac((q.x - H.x) / 0.07) - 0.5) * 2.0;
float teethUp = step(q.y, H.y) * step(H.y - 0.06 * (1.0 - tx), q.y) * step(H.x + 0.12, q.x);
float tjx = abs(frac((qj.x - H.x) / 0.07) - 0.5) * 2.0;
float teethDn = step(H.y, qj.y) * step(qj.y, H.y + 0.05 * (1.0 - tjx)) * step(H.x + 0.15, qj.x);
mouthCol = lerp(mouthCol, float3(0.97, 0.95, 0.9) * (0.8 + 0.2 * throat), saturate(teethUp + teethDn));
layer(acc, cover, mouthCol, smoothstep(0.5, -0.5, dMouth * u));
// The stem and its bud, behind the head.
layer(acc, cover, colorA.rgb * 0.7, smoothstep(0.5, -0.5, dStem * u));
float dBud = length(q - bud) - 0.045 - 0.015 * beat;
layer(acc, cover, colorC.rgb, exp(-max(dBud, 0.0) / 0.05) * (0.5 + 0.4 * beat));
layer(acc, cover, lerp(colorC.rgb, float3(1, 1, 1), 0.5), smoothstep(0.5, -0.5, dBud * u));
// The lower jaw, then the body over it; the shut mouth shows as a crease.
layer(acc, cover, shade(qj, B, R, colorA.rgb) * (1.0 - 0.25 * saturate(ang / 0.3)), smoothstep(0.5, -0.5, dJaw * u));
float3 bodyCol = shade(q, B, R, colorA.rgb);
bodyCol *= 1.0 - 0.45 * exp(-abs(q.y - H.y) / 0.015) * step(H.x + 0.05, q.x) * (1.0 - saturate(ang / 0.1));
layer(acc, cover, bodyCol, smoothstep(0.5, -0.5, dUpper * u));
// One big eye looking ahead: white, a pupil with a glint, and a blink now and then.
float2 E = float2(0.0, 0.12);
float dEye = length(q - E) - 0.115, blink = step(frac(time / 3.3), 0.04);
float3 eyeCol = lerp(float3(1, 1, 1), float3(0.72, 0.78, 0.9), saturate((E.y - q.y) / 0.16 + 0.3));
eyeCol = lerp(eyeCol, float3(0.06, 0.05, 0.12), smoothstep(0.5, -0.5, (length(q - E - float2(0.048, -0.005)) - 0.058 - 0.012 * beat) * u));
eyeCol = lerp(eyeCol, float3(1, 1, 1), smoothstep(0.5, -0.5, (length(q - E - float2(0.07, 0.02)) - 0.02) * u));
eyeCol = lerp(eyeCol, shade(q, B, R, colorA.rgb * 0.8), blink);
eyeCol = lerp(eyeCol, colorA.rgb * 0.15, blink * smoothstep(0.018, 0.008, abs(q.y - E.y + 0.02 + 0.6 * (q.x - E.x) * (q.x - E.x))));
layer(acc, cover, colorA.rgb * 0.2, smoothstep(0.5, -0.5, dEye * u - 1.1));
layer(acc, cover, eyeCol, smoothstep(0.5, -0.5, dEye * u));
// On a beat a few crumbs spray out of the mouth and fall.
for (int i = 0; i < 5; i++)
{
float t = 1.0 - beat;
float2 v = float2(0.25 + 0.5 * hash1(i + 3.0), 0.35 + 0.9 * hash1(i + 9.0));
float cr = length(q - float2(0.22, -0.08) - v * t * 0.8 + float2(0.0, 2.2 * t * t)) - 0.022 * (1.0 - 0.5 * t);
layer(acc, cover, lerp(colorC.rgb, float3(1, 1, 1), 0.3), step(0.05, beat) * beat * smoothstep(0.5, -0.5, cr * u));
}
return paint(acc / max(cover, 0.001), cover);
}