Firefly Field
by MusicBar, visualizer
Fireflies drift in lazy loops over dark swaying grass, each blinking in its own time, more of them out when the music is loud and a swarm flashing together 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 a6238d335bc4c31b5a0ddd43476c201b7130c60c418c19b3c097b326a99b713e
//! name: Firefly Field
//! author: MusicBar
//! kind: visualizer
//! description: Fireflies drift in lazy loops over dark swaying grass, each blinking in its own time, more of them out when the music is loud and a swarm flashing together on every beat.
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);
}
// Lays a color over what is there (premultiplied light, and how much of the pixel it covers).
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 blade from cell k, curved along the wind: returns how much it covers, how far up the blade we are
// and which side of its fold we are on.
float3 blade(float2 px, float k, float cw, float bend, float hmin, float hr, float seed, float H)
{
float h = hash2(float2(k, seed));
float tall = hash2(float2(k * 1.7, seed + 3.1));
float bx = (k + 0.5 + 0.7 * (h - 0.5)) * cw;
float bh = H * (hmin + hr * tall + 0.3 * step(0.88, tall));
float lean = bend * (0.75 + 0.5 * h);
float t = px.y / bh;
float cx = bx + lean * px.y * px.y / H;
float hw = cw * 0.45 * pow(saturate(1.0 - t), 0.85);
float slope = 2.0 * lean * px.y / H;
float d = (abs(px.x - cx) - hw) / sqrt(1.0 + slope * slope);
return float3(smoothstep(0.5, -0.5, d) * step(0.0, px.y) * step(t, 1.0), saturate(t), step(px.x, cx));
}
// A row of grass: the three blades that can reach this pixel, darker at the root, lit at the tips.
void grass(inout float3 acc, inout float cover, float2 px, float cw, float bend, float hmin, float hr, float seed, float H, float3 root, float3 tip, float alpha)
{
float k = floor((px.x - bend * px.y * px.y / H) / cw);
float3 g = float3(0, 0, 0);
for (int n = -1; n <= 1; n++)
{
float3 b = blade(px, k + n, cw, bend, hmin, hr, seed, H);
g = b.x > g.x ? b : g;
}
layer(acc, cover, lerp(root, tip, g.y * g.y) * (0.75 + 0.5 * g.z), g.x * alpha);
}
// Fireflies, one per cell when the cell has one: a lazy loop, a blink of its own, and the beat's swarm flash.
void flies(inout float3 acc, inout float cover, float2 px, float cs, float seed, float density, float rad, float bright)
{
float2 q = px / cs + float2(time * 0.07, 0.0);
float2 c0 = floor(q);
float2 f = frac(q);
float2 o = float2(f.x > 0.5 ? 1.0 : -1.0, f.y > 0.5 ? 1.0 : -1.0);
for (int n = 0; n < 4; n++)
{
float2 c = c0 + float2(fmod(n, 2) * o.x, floor(n / 2.0) * o.y);
float h = hash2(c + seed);
float h2 = hash2(c * 1.37 + seed + 5.0);
float2 w = float2(0.4 + 0.5 * h2, 0.5 + 0.6 * h);
float2 ph0 = float2(h * 6.28, h2 * 6.28) + time * w;
float2 at = c + 0.5 + float2(0.3, 0.25) * sin(ph0);
float2 dir = normalize(float2(0.3, 0.25) * w * cos(ph0) + 0.001);
// The glow trails back along the loop it is flying.
float2 rel = (q - at) * cs;
float along = dot(rel, dir);
float across = dot(rel, float2(-dir.y, dir.x));
float d = length(rel);
float trail = exp(-across * across / (rad * rad * 0.8)) * exp(max(along, -cs) / (cs * 0.22)) * step(along, 0.0);
float ph = frac(time * (0.22 + 0.3 * h2) + h * 7.0);
float flash = sin(3.14159 * saturate(ph / 0.5));
float on = saturate(flash * flash + beat * step(h2, 0.7) * 1.3) * smoothstep(h - 0.08, h + 0.08, density) * bright;
float g = d / (cs * 0.28);
layer(acc, cover, float3(0.06, 0.06, 0.04), smoothstep(rad + 0.5, rad - 0.5, d) * smoothstep(h - 0.08, h + 0.08, density) * bright * 0.6);
layer(acc, cover, colorA.rgb, (exp(-g * g * 2.5) * 0.5 + exp(-d / (rad * 1.8)) * 0.6 + trail * 0.45) * on);
layer(acc, cover, lerp(colorA.rgb, colorC.rgb, 0.75), smoothstep(rad + 0.6, rad - 0.6, d) * on * 1.4);
}
}
float4 main(float2 uv : TEXCOORD) : COLOR
{
// Pixels: along the bar, and up from the screen edge.
float H = size.y;
float2 px = float2(uv.x * size.x, rise(uv) * H);
float sp = spectrum(abs(uv.x - 0.5) * 2.0);
float density = 0.12 + 0.45 * level + 0.35 * sp;
// The wind: a slow wave along the field, wider with the loudness, gusting on the beat.
float bend = (0.15 + 0.55 * level) * sin(time * 1.3 - px.x / (5.0 * H)) + 0.3 * beat;
float3 acc = float3(0, 0, 0);
float cover = 0;
// A soft glow hanging over the field.
layer(acc, cover, colorA.rgb, exp(-px.y / (0.3 * H)) * (0.07 + 0.12 * level + 0.1 * beat));
// Far fireflies, then the back grass, the near fireflies and the front grass.
flies(acc, cover, px, 0.28 * H, 17.0, density * 0.8, max(0.6, 0.018 * H), 0.5);
grass(acc, cover, px, 0.11 * H, bend * 0.7, 0.25, 0.3, 3.0, H, float3(0.04, 0.08, 0.06), colorB.rgb * 0.6, 0.55);
flies(acc, cover, px, 0.5 * H, 41.0, density, max(1.0, 0.04 * H), 1.0);
grass(acc, cover, px, 0.15 * H, bend, 0.14, 0.3, 9.0, H, float3(0.015, 0.035, 0.02), colorB.rgb * 0.45, 0.95);
return paint(acc / max(cover, 0.001), cover);
}