Fireworks Night
by MusicBar, visualizer
Rockets climb and burst into peonies and chrysanthemums all along the bar, blooming bigger with the music, flaring and popping glitter salutes 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 a64a3df1c0d23bbffff89f5aff3cc823042d01b835f8d9d4a7e44a5b50792653
//! name: Fireworks Night
//! author: MusicBar
//! kind: visualizer
//! description: Rockets climb and burst into peonies and chrysanthemums all along the bar, blooming bigger with the music, flaring and popping salutes on every beat.
// A steady random number for a cell.
float hash2(float2 p)
{
float3 q = frac(float3(p.x, p.y, p.x) * 0.1031);
q += dot(q, q.yzx + 33.33);
return frac((q.x + q.y) * q.z);
}
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);
}
// The spark of one ring flying in this pixel's direction (found from its angle bucket): its streak and head, and how far along it.
// fill 1 spreads the sparks through the ball like a peony, 0 rings them out like a chrysanthemum. Late in life they crackle.
float2 spark(float2 rel, float a, float n, float key, float R, float ag, float g, float tailT, float w, float fill)
{
float b = floor((a + 3.14159) / 6.28318 * n);
float hb = hash2(float2(b, key));
float ang = (b + 0.25 + 0.5 * hb) / n * 6.28318 - 3.14159;
float2 dir = float2(cos(ang), sin(ang));
float sp = R * lerp(0.8 + 0.3 * hb, 0.4 + 0.65 * sqrt(frac(hb * 17.0)), fill);
float t0 = max(ag - tailT, 0.0);
float2 e1 = dir * sp * (1.0 - exp(-ag * 5.0));
float2 e0 = dir * sp * (1.0 - exp(-t0 * 5.0)) + float2(0.0, g * (ag * ag - t0 * t0));
float2 pa = rel - e0;
float2 ba = e1 - e0;
float hh = saturate(dot(pa, ba) / max(dot(ba, ba), 0.001));
float tail = smoothstep(w + 0.7, w - 0.3, length(pa - ba * hh)) * lerp(0.12, 1.0, hh * hh);
float spot = length(rel - e1);
float tip = smoothstep(w * 1.6 + 0.6, w * 1.6 - 0.4, spot) + 0.35 * exp(-spot / (w * 3.0));
float crackle = lerp(1.0, step(0.5, hash2(float2(b + key, floor(time * 24.0)))) * 1.7, smoothstep(0.55, 0.95, ag));
return float2((tail + tip) * crackle, hh);
}
// The shell of one column of the sky: its rocket climbs, it bursts, the sparks droop and crackle out, and it comes again.
void shell(inout float3 acc, inout float cover, float2 P, float col, float cw, float H, float power, float flare)
{
float period = 1.8 + 1.3 * hash2(float2(col, 1.7));
float ph = time / period + hash2(float2(col, 8.3));
float id = floor(ph);
float tt = frac(ph) * period;
float s1 = hash2(float2(col, id));
float s2 = hash2(float2(id, col + 4.4));
float s3 = hash2(float2(col + id, 9.1));
float3 tint = s3 < 0.45 ? colorA.rgb : (s3 < 0.8 ? colorB.rgb : colorC.rgb);
float2 c = float2((col + 0.2 + 0.6 * s1) * cw, H * (0.5 + 0.2 * s2));
float climb = 0.45;
// The rocket on its flickering trail.
float rp = saturate(tt / climb);
float ry = c.y * (1.0 - (1.0 - rp) * (1.0 - rp));
float below = ry - P.y;
float trail = smoothstep(1.3, 0.3, abs(P.x - c.x)) * step(0.0, below) * exp(-below / (0.15 * H)) * step(tt, climb);
trail *= 0.55 + 0.45 * step(0.5, hash2(float2(floor(P.y / 2.0), floor(time * 30.0) + col)));
layer(acc, cover, lerp(float3(1.0, 0.8, 0.5), tint, 0.3), trail * 0.9);
layer(acc, cover, float3(1.0, 0.95, 0.85), exp(-length(P - float2(c.x, ry)) / (0.03 * H + 0.5)) * step(tt, climb));
// The burst, seen in a frame that falls with the sparks so each one is found from this pixel's angle.
float age = tt - climb;
float ag = max(age, 0.0);
float live = step(0.0, age) * smoothstep(1.6, 0.8, age);
float chrys = step(0.5, s2);
float R = H * (0.4 + 0.22 * s1) * power;
float g = 0.32 * H;
float2 rel = P - c + float2(0.0, g * ag * ag);
float a = atan2(rel.y, rel.x);
float w = max(0.6, 0.016 * H) * lerp(1.5, 1.0, chrys);
float2 outer = spark(rel, a, 20.0, id + col * 3.1, R, ag, g, lerp(0.08, 0.32, chrys), w, 1.0 - chrys);
float2 inner = spark(rel, a, 11.0, id * 1.7 + col, R * 0.5, ag, g, 0.06, w, 0.0) * step(0.45, s1);
float3 core = s3 < 0.8 ? colorC.rgb : colorA.rgb;
float dc = length(rel);
layer(acc, cover, float3(0.55, 0.53, 0.58), exp(-dc / (R * 0.6)) * 0.07 * smoothstep(0.1, 0.6, ag) * live);
layer(acc, cover, tint, exp(-dc / (R * 0.5)) * 0.12 * live * flare * smoothstep(1.0, 0.2, ag));
layer(acc, cover, lerp(tint, float3(1, 1, 1), 0.6 * outer.y * smoothstep(0.9, 0.0, age)), outer.x * live * flare);
layer(acc, cover, lerp(core, float3(1, 1, 1), 0.35), inner.x * live * flare);
layer(acc, cover, lerp(tint, float3(1, 1, 1), 0.65), exp(-dc / (0.16 * H)) * exp(-ag * 9.0) * step(0.0, age));
}
float4 main(float2 uv : TEXCOORD) : COLOR
{
float H = size.y;
float2 px = float2(uv.x * size.x, rise(uv) * size.y); // pixels: along the bar, up from the screen edge
float cw = 2.3 * H;
float col = floor(px.x / cw);
float side = frac(px.x / cw) < 0.5 ? -1.0 : 1.0;
float power = 0.8 + 0.45 * level;
float flare = 1.0 + 0.8 * beat;
float3 acc = float3(0, 0, 0);
float cover = 0;
// This column's shell and the nearer neighbour's, whose sparks can reach over.
shell(acc, cover, px, col + side, cw, H, power, flare);
shell(acc, cover, px, col, cw, H, power, flare);
// Beat salutes: a quick ring of white glitter that pops open where the beat lands.
float sid = floor(time * 2.0);
float2 sc = float2((col + 0.2 + 0.6 * hash2(float2(sid, col))) * cw, H * (0.35 + 0.35 * hash2(float2(col, sid + 5.0))));
float2 sr = px - sc;
float sb = floor((atan2(sr.y, sr.x) + 3.14159) / 6.28318 * 12.0);
float sang = (sb + 0.5) / 12.0 * 6.28318 - 3.14159;
float ring = (1.15 - beat) * 0.38 * H;
float glitter = exp(-length(sr - float2(cos(sang), sin(sang)) * ring) / (0.025 * H + 0.4));
layer(acc, cover, lerp(colorC.rgb, float3(1, 1, 1), 0.6), glitter * step(hash2(float2(col, sid * 1.3)), 0.4) * beat * step(0.05, beat));
return paint(acc / max(cover, 0.001), cover);
}