Fireworks Night
của MusicBar, visualizer
Pháo hoa bắn lên nở khắp thanh, có bông tròn có bông rủ đuôi rồi lấp lánh tắt dần, nhạc càng to nở càng lớn, tới nhịp là bung thêm chùm kim tuyến.
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 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);
}