Pixel Inferno
của MusicBar, visualizer
Lửa pixel kiểu demoscene cháy khắp thanh, ngọn lửa nhảy theo phổ nhạc với bass ở giữa, tới nhịp là tàn lửa pixel bắn tung 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 e2abb59b74af35d45c53ceb6091be8bd89f5cd127ce522b72ab2073a89ce55b0
//! name: Pixel Inferno
//! author: MusicBar
//! kind: visualizer
//! description: A chunky demoscene pixel fire roars along the bar, its flames leaping with the spectrum, bass in the middle, and pixel embers popping out 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);
}
// Smooth value noise.
float vnoise(float2 p)
{
float2 i = floor(p);
float2 f = frac(p);
f = f * f * (3.0 - 2.0 * f);
return lerp(lerp(hash2(i), hash2(i + float2(1, 0)), f.x), lerp(hash2(i + float2(0, 1)), hash2(i + float2(1, 1)), f.x), f.y);
}
// The fire in eight flat steps, black to white; the middle steps lean a little toward the palette.
float3 ramp(float k)
{
float3 c = float3(0.20, 0.03, 0.05);
c = lerp(c, float3(0.48, 0.05, 0.05), step(1.5, k));
c = lerp(c, float3(0.80, 0.11, 0.05), step(2.5, k));
c = lerp(c, float3(0.97, 0.34, 0.06), step(3.5, k));
c = lerp(c, float3(1.00, 0.56, 0.10), step(4.5, k));
c = lerp(c, float3(1.00, 0.80, 0.24), step(5.5, k));
c = lerp(c, float3(1.00, 0.97, 0.80), step(6.5, k));
float mids = step(1.5, k) * step(k, 4.5);
return lerp(c, colorA.rgb, 0.3 * mids);
}
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
{
// Everything snaps to chunky pixels: c counts them along the bar and up from the screen edge.
float p = max(2.0, floor(size.y / 10.0));
float rows = floor(size.y / p);
float cols = floor(size.x / p);
float2 c = floor(float2(uv.x * size.x, rise(uv) * size.y) / p);
float q = (c.y + 0.5) / rows;
// Each column burns as high as its band of the spectrum, mirrored with the bass in the middle.
float x = (c.x + 0.5) / cols;
float sv = spectrum(abs(x - 0.5) * 2.0);
float env = (0.14 + 1.05 * sv + 0.1 * level) * (0.7 + 0.4 * (1.0 - abs(x - 0.5) * 2.0)) * (1.0 + 0.3 * beat);
// Tongues rising fast and swaying sideways, plus a small per-pixel flicker that changes 15 times a second.
float tick = floor(time * 15.0);
float n1 = vnoise(float2(c.x * 0.28 + 0.7 * sin(c.y * 0.35 + time * 1.7), c.y * 0.3 - time * 6.0));
float n2 = vnoise(float2(c.x * 0.7, c.y * 0.6 - time * 10.0));
float flick = hash2(c + float2(tick * 7.3, tick * 3.1));
float hq = q / env;
float heat = (1.0 - hq) * (0.6 + 0.45 * sv) + (n1 * 0.75 + n2 * 0.25 - 0.5) * (0.35 + 1.1 * hq) + (flick - 0.5) * 0.08;
float k = floor(saturate(heat) * 7.99);
float3 acc = float3(0, 0, 0);
float cover = 0;
// The fire itself, the darkest step a little see-through.
layer(acc, cover, ramp(k), step(0.5, k) * lerp(0.7, 1.0, step(1.5, k)));
// Pixel embers rising out of the fire, popping out in a crowd on the beat.
float2 ec = float2(c.x, c.y - floor(time * 9.0));
float er = hash2(ec * float2(1.0, 1.7) + 11.0);
float swarm = step(1.0 - (0.012 + 0.03 * level + 0.12 * beat), er);
float above = step(k, 0.5) * step(env * 0.5, q) * step(q / env, 1.1 + 0.9 * frac(er * 53.0));
float tw = step(0.3, frac(time * 6.0 + er * 13.0));
float3 emberColor = lerp(float3(1.0, 0.85, 0.3), colorC.rgb, 0.4);
emberColor = lerp(emberColor, lerp(float3(1.0, 0.4, 0.1), colorA.rgb, 0.4), step(1.25, q / env));
emberColor = lerp(emberColor, float3(1, 1, 1), step(0.6, beat) * step(0.5, frac(er * 37.0)));
layer(acc, cover, emberColor, swarm * above * tw);
return paint(acc / max(cover, 0.001), cover);
}