Boba Time
by MusicBar, progress bar
Milk tea with a cream swirl fills the bar up to a wide straw at the playhead, the pearls bounce on the bass and the straw slurps one up 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 77b906976e3ab1b8ab2c31c2a9fcc5ca0e29a0a9a9ee815487677f173680c36a
//! name: Boba Time
//! author: MusicBar
//! kind: progress
//! description: Milk tea with a cream swirl fills the bar up to a wide straw at the playhead, the pearls bounce on the bass and the straw slurps one up on every 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);
}
// One glossy tapioca pearl: dark and glassy, amber where light passes through its lower rim.
void pearl(inout float3 acc, inout float cover, float2 q, float rp)
{
float d = length(q);
float body = smoothstep(rp + 0.6, rp - 0.6, d);
float t = d / rp;
float3 c = lerp(float3(0.09, 0.05, 0.035), float3(0.2, 0.11, 0.06), t * t);
c += float3(0.55, 0.3, 0.12) * smoothstep(0.55, 1.0, t) * saturate(-q.y / rp + 0.2) * 0.8;
float spot = smoothstep(0.26, 0.1, length(q / rp - float2(-0.32, 0.36)));
float dot2 = smoothstep(0.12, 0.04, length(q / rp - float2(0.38, -0.3)));
c += float3(1, 0.95, 0.9) * (spot * 0.9 + dot2 * 0.35);
layer(acc, cover, c, body);
}
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 floorY = u * 0.07;
float bass = spectrum(0.04);
// The tea's surface: a gentle slosh that grows with the music.
float surf = u * 0.74 + u * 0.022 * sin(px.x / u * 2.6 - time * 2.2) * (0.6 + level) + u * 0.012 * sin(px.x / u * 6.1 + time * 1.4);
float teaD = max(max(px.y - surf, floorY - px.y), px.x - head - u * 0.08);
float tea = smoothstep(0.6, -0.6, teaD);
float3 acc = float3(0, 0, 0);
float cover = 0;
// The rest of the song: the cup's base and a dotted fill line, barely there.
float ahead = smoothstep(head, head + u * 0.5, px.x);
float dots = smoothstep(1.2, 0.2, length(float2(frac(px.x / (u * 0.3)) - 0.5, 0.0) * u * 0.3 + float2(0.0, px.y - u * 0.74)));
float base = smoothstep(1.0, 0.0, abs(px.y - floorY + 0.5));
layer(acc, cover, colorB.rgb, ahead * (dots * 0.28 + base * 0.2));
// Milk tea: beige near the top to caramel below, pulled toward colorA for the flavor,
// with streaks of dark syrup curling down from the top like brown sugar on the cup wall.
float h = saturate((px.y - floorY) / (surf - floorY));
float3 teaTop = lerp(float3(0.95, 0.84, 0.7), colorA.rgb, 0.35);
float3 teaLow = lerp(float3(0.7, 0.45, 0.25), colorA.rgb * 0.75, 0.45);
float3 c = lerp(teaLow, teaTop, smoothstep(0.0, 1.0, h));
float syrup = sin(px.x / u * 1.7 - px.y / u * 2.4 + 1.2 * sin(px.y / u * 3.0 + px.x / u * 0.9) - time * 0.25);
c = lerp(c, colorA.rgb * float3(0.5, 0.36, 0.3), smoothstep(0.45, 0.9, syrup) * smoothstep(0.85, 0.2, h) * 0.85);
// The cream swirl: a light layer on top that curls down into the tea in tendrils.
float swirl = sin(px.x / u * 2.4 + 3.2 * sin(px.y / u * 6.0 + px.x / u * 1.1 + time * 0.5) + time * 0.3);
float creamLine = surf - u * 0.19 + u * 0.035 * sin(px.x / u * 2.1 + time * 0.6);
float cream = smoothstep(-0.12, 0.12, swirl * 0.75 + (px.y - creamLine) / (u * 0.08));
float3 creamC = lerp(colorB.rgb, float3(1, 0.97, 0.92), 0.4) * 0.97;
c = lerp(c, creamC, cream * 0.92);
// Soft light across the cup and a bright lip along the surface.
c *= 0.86 + 0.14 * sin(px.x / u * 0.9 + 0.5);
c += float3(1, 1, 1) * smoothstep(u * 0.04, 0.0, abs(px.y - surf + u * 0.03)) * 0.22;
layer(acc, cover, c, tea * 0.94);
// Pearls resting on the bottom, two loose rows; they bounce with the bass and jump on the beat.
float rp = u * 0.115;
float cw = u * 0.27;
float cell = floor(px.x / cw);
[unroll] for (int i = -1; i <= 1; i++)
{
float k = cell + i;
float hk = hash1(k * 3.7 + 0.5);
float hop = u * (0.07 * bass * (0.5 + 0.5 * sin(time * 8.0 + hk * 6.28)) + 0.12 * beat * hk);
float2 at = float2((k + 0.5) * cw + (hk - 0.5) * u * 0.06, floorY + rp + 0.5 + hop);
float2 q = px - at;
if (at.x < head - rp * 0.5) pearl(acc, cover, q, rp);
float hu = hash1(k * 9.1 + 4.0);
float2 top = float2((k + 1.0) * cw, floorY + rp * 2.65 + hop * 1.3);
if (hu < 0.45 && top.x < head - rp) pearl(acc, cover, px - top, rp * 0.95);
}
// The straw at the playhead: wide, tilted, clear colored plastic. It jolts a little on the beat.
float2 sa = float2(head - u * 0.02, floorY + u * 0.05);
float2 dir = normalize(float2(0.5 + 0.08 * beat, 1.0));
float2 sq = px - sa;
float along = dot(sq, dir);
float across = dot(sq, float2(dir.y, -dir.x));
float sr = u * 0.19;
float strawD = max(abs(across) - sr, -along);
float straw = smoothstep(0.6, -0.6, strawD);
float wallT = abs(across) / sr;
// A ring where the straw breaks the surface.
float ringY = abs(px.y - surf + u * 0.01);
layer(acc, cover, float3(1, 1, 1), smoothstep(u * 0.05, 0.0, ringY) * smoothstep(sr + u * 0.12, sr, abs(across)) * tea * 0.35);
// On the beat a pearl shoots up the straw with a column of tea behind it.
float slurp = step(0.03, beat);
float pAlong = lerp(u * 0.15, u * 1.4, 1.0 - beat);
float teaIn = step(along, max(pAlong * slurp, (surf - sa.y) / dir.y)) * smoothstep(sr - 0.5, sr - 2.0, abs(across)) * straw;
layer(acc, cover, lerp(teaLow, teaTop, 0.55) * (0.8 + 0.2 * (1.0 - wallT)), teaIn * 0.9);
if (slurp > 0.5) pearl(acc, cover, sq - dir * pAlong, sr * 0.8);
// The plastic: a tint over whatever is inside, solid walls, a long highlight down one side.
// Under the surface it is half hidden by the tea.
float sunk = lerp(1.0, 0.5, tea);
float3 sc = lerp(colorC.rgb, float3(1, 1, 1), 0.35 - 0.25 * teaIn);
layer(acc, cover, sc, straw * lerp(0.72, 0.3, teaIn) * sunk);
layer(acc, cover, colorC.rgb * 0.95, straw * smoothstep(0.6, 0.88, wallT) * 0.9 * sunk);
layer(acc, cover, float3(1, 1, 1), straw * smoothstep(0.14, 0.0, abs(across / sr + 0.42)) * 0.75 * sunk);
layer(acc, cover, float3(1, 1, 1), straw * smoothstep(0.06, 0.0, abs(across / sr - 0.55)) * 0.3 * sunk);
layer(acc, cover, colorC.rgb * 0.4, smoothstep(1.3, 0.2, abs(strawD + 0.6)) * 0.85 * sunk);
return paint(acc / max(cover, 0.001), cover);
}