Piano Glow
của MusicBar, visualizer
Bàn phím piano chạy dọc mép màn hình, phím tự nhấn và sáng lên theo nhạc, trầm bên trái bổng bên phải, phím nào nhấn là có cột sáng bay lê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 ece622375b69735ccb5f8308cd6ff3d16291f08f8990f8e3f3d73ec55c802aec
//! name: Piano Glow
//! author: MusicBar
//! kind: visualizer
//! description: A piano keyboard runs along the screen edge, its keys pressing down and lighting up with the music, low notes on the left and high on the right, with light rising from every pressed key.
// A steady random number.
float hash1(float n) { return frac(sin(n * 43.758) * 24634.6345); }
// How hard key k is held down now. The music in its range (s) makes a note more likely; each note
// strikes, rings down and lets go before the next one, and every key keeps its own timing.
// Returns how hard, and how long ago the note struck (0 to 1 of its slot).
float2 press(float k, float s)
{
float ph = time * 2.3 + hash1(k * 1.37) * 8.0;
float slot = floor(ph);
float local = frac(ph);
float chance = saturate((s - 0.28) * 1.8 + 0.35 * beat);
float r = hash1(k * 0.731 + slot * 3.17);
float on = smoothstep(r - 0.015, r + 0.015, chance);
return float2(on * (0.55 + 0.45 * exp(-local * 3.0)) * smoothstep(0.0, 0.05, local) * smoothstep(1.0, 0.82, local), local);
}
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
{
float2 px = float2(uv.x * size.x, rise(uv) * size.y); // pixels: along the bar, up from the screen edge
float H = size.y;
float W = max(5.0, 0.21 * H); // one white key
float Kh = 0.4 * H; // how deep the keyboard is
// White keys repeat C D E F G A B. A black key sits on the line between two white keys,
// except after E and after B, which gives the groups of two and three.
float wi = floor(px.x / W);
float lx = px.x / W - wi;
float b = wi + step(0.5, lx);
float nl = (b - 1.0) - floor((b - 1.0) / 7.0) * 7.0;
float hasBlack = (1.0 - step(abs(nl - 2.0), 0.1)) * (1.0 - step(abs(nl - 6.0), 0.1));
float shift = nl < 0.5 ? -0.1 : (nl < 1.5 ? 0.1 : (nl < 3.5 ? -0.12 : (nl < 4.5 ? 0.0 : 0.12)));
float bx = (b + shift) * W;
// Each key listens to its own part of the spectrum, low on the left.
float2 kw = press(wi * 2.0, spectrum((wi + 0.5) * W / size.x));
float2 kb = press(b * 2.0 + 1.0, spectrum(bx / size.x));
float pw = kw.x;
float pb = kb.x * hasBlack;
float3 acc = float3(0, 0, 0);
float cover = 0;
// Light columns shoot up from each key as it strikes, with light flowing up inside them;
// then sparkles drifting up through them.
float above = px.y - Kh;
float shootW = smoothstep(0.5, -0.5, above - H * saturate(kw.y * 5.0));
float shootB = smoothstep(0.5, -0.5, above - H * saturate(kb.y * 5.0));
float colW = smoothstep(0.5, 0.2, abs(lx - 0.5)) * saturate(pw * 1.8) * shootW;
float colB = smoothstep(0.32 * W, 0.12 * W, abs(px.x - bx)) * saturate(pb * 1.8) * shootB;
float fade = exp(-max(above, 0.0) / (0.45 * H * (0.6 + 0.6 * level)));
float flow = 0.7 + 0.3 * sin((above - time * 0.9 * H) / (0.07 * H) + wi * 2.1);
float rays = step(0.0, above) * fade * flow;
float3 beam = (colW * colorA.rgb + colB * colorB.rgb) / max(colW + colB, 0.001);
float coreW = exp(-pow((lx - 0.5) / 0.12, 2.0)) * colW + exp(-pow((px.x - bx) / (0.08 * W), 2.0)) * colB;
layer(acc, cover, lerp(beam, float3(1, 1, 1), 0.2 * fade) * 1.2, rays * saturate((colW + colB) * 1.2));
layer(acc, cover, lerp(beam, float3(1, 1, 1), 0.6), rays * saturate(coreW) * 0.9);
float ch = 0.2 * H;
float sy = above - time * 0.45 * H;
float cy = floor(sy / ch);
float2 sp = float2(lx - (0.25 + 0.5 * hash1(wi * 3.1 + cy * 7.3)), (sy / ch - cy) - 0.5);
float twinkle = 0.5 + 0.5 * sin(time * 9.0 + hash1(wi + cy * 1.9) * 30.0);
float star = exp(-abs(sp.x) * W / 0.7) * exp(-abs(sp.y) * ch / 1.6) + exp(-abs(sp.y) * ch / 0.7) * exp(-abs(sp.x) * W / 1.6);
layer(acc, cover, lerp(colorC.rgb, float3(1, 1, 1), 0.4), saturate(star) * step(hash1(wi * 5.7 + cy * 2.3), 0.4) * step(0.0, above) * smoothstep(0.15, 0.5, pw) * twinkle * exp(-max(above, 0.0) / (0.5 * H)));
// The white keys: ivory, a darker front lip that shrinks when the key goes down, lit in the main color.
float gapW = smoothstep(0.5, 1.5, min(lx, 1.0 - lx) * W);
float lip = 0.075 * H * (1.0 - 0.6 * saturate(pw * 1.5));
float onKey = step(px.y, Kh) * gapW;
float alongW = px.y / Kh;
float3 ivory = float3(0.9, 0.89, 0.86) * (0.78 + 0.22 * alongW);
ivory = lerp(ivory, ivory * 0.62, step(px.y, lip));
float3 lit = lerp(colorA.rgb, float3(1, 1, 1), 0.35 * (1.0 - alongW));
float3 white = lerp(ivory, lit * (1.0 - 0.3 * step(px.y, lip)), saturate(pw * 1.3));
float shadow = smoothstep(0.05 * H, 0.0, 0.4 * Kh - px.y) * step(px.y, 0.4 * Kh + 1.0) * hasBlack * smoothstep(0.36 * W, 0.22 * W, abs(px.x - bx + 0.04 * W));
white *= 1.0 - 0.3 * shadow;
layer(acc, cover, float3(0.06, 0.06, 0.08), step(px.y, Kh) * (1.0 - gapW) * 0.7);
layer(acc, cover, white, onKey * lerp(0.78, 0.98, saturate(pw * 1.5)));
// The black keys: glossy, rimmed so they read on a dark taskbar, lit in the second color.
float2 bq = float2(px.x - bx, px.y - (Kh * 0.7 + 0.02 * H * (1.0 - pb)));
float2 bs = float2(0.3 * W, Kh * 0.3);
float2 bd2 = abs(bq) - bs + 0.12 * W;
float dBk = length(max(bd2, 0.0)) + min(max(bd2.x, bd2.y), 0.0) - 0.12 * W;
float3 ebony = float3(0.07, 0.07, 0.09) + 0.22 * exp(-pow((bq.x + 0.1 * W) / (0.08 * W), 2.0)) * smoothstep(-bs.y, bs.y, bq.y);
ebony = lerp(ebony, colorB.rgb * (0.8 + 0.4 * smoothstep(-bs.y, bs.y, bq.y)), saturate(pb * 1.3));
ebony = lerp(ebony, float3(0.55, 0.55, 0.6), smoothstep(-1.2, 0.0, dBk) * 0.6 * (1.0 - pb));
layer(acc, cover, ebony, smoothstep(0.5, -0.5, dBk) * hasBlack);
// The felt rail behind the keys, with a thin highlight on top.
float rail = step(Kh - 0.5, px.y) * step(px.y, Kh + 0.045 * H);
float railTop = smoothstep(Kh + 0.045 * H - 1.5, Kh + 0.045 * H - 0.5, px.y);
layer(acc, cover, lerp(float3(0.09, 0.08, 0.11), lerp(colorC.rgb, float3(1, 1, 1), 0.3) * 0.5, railTop), rail * 0.92);
// A bloom where a pressed key meets its light column.
float bloom = exp(-abs(above) / (0.06 * H)) * saturate(colW + colB);
layer(acc, cover, lerp(beam, float3(1, 1, 1), 0.5), bloom * 0.7 * (0.8 + 0.4 * beat));
return paint(acc / max(cover, 0.001), cover);
}