Hố Đen
của Rinz, thanh tiến trình
Hố đen siêu khối lượng chuẩn điện ảnh với đĩa bồi tụ tương đối tính, thấu kính hấp dẫn và nền vũ trụ.
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 9d3a1c37eed6b0a19cc9cbb92ac13292b15c4545f5b3e29942c1664f025c3f98
//! name: Black Hole
//! author: Rinz
//! kind: progress
//! description: Cinematic supermassive black hole with relativistic accretion disk, gravitational lensing, and cosmic background.
static const float USE_APP_COLOR = 0.0;
float hash1(float n)
{
n = frac(n * 0.1031);
n *= n + 33.33;
n *= n + n;
return frac(n);
}
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);
}
float2 rot(float2 p, float a)
{
float c = cos(a), s = sin(a);
return float2(c * p.x + s * p.y, -s * p.x + c * p.y);
}
float hash21(float2 p)
{
return hash1(dot(p, float2(127.1, 311.7)));
}
float vnoise(float2 p)
{
float2 i = floor(p);
float2 f = frac(p);
f = f * f * (3.0 - 2.0 * f);
float a = hash21(i);
float b = hash21(i + float2(1.0, 0.0));
float c = hash21(i + float2(0.0, 1.0));
float d = hash21(i + float2(1.0, 1.0));
return lerp(lerp(a, b, f.x), lerp(c, d, f.x), f.y);
}
float fbm(float2 p)
{
float v = 0.0;
float amp = 0.5;
[unroll]
for (int i = 0; i < 3; i++)
{
v += amp * vnoise(p);
p = p * 2.03 + float2(15.7, 8.9);
amp *= 0.5;
}
return v;
}
float3 renderStarLayer(float2 p, float cellScale, float seed, float3 tintA, float3 tintB)
{
float2 grid = p / cellScale;
float2 id = floor(grid);
float2 gv = frac(grid) - 0.5;
float nId = dot(id, float2(41.0, 289.0)) + seed * 113.0;
float h1 = hash1(nId);
float h2 = hash1(nId + 17.3);
float h3 = hash1(nId + 31.7);
float present = step(0.70, h1);
float2 offset = (float2(h2, h3) - 0.5) * 0.52;
float2 d = (gv - offset) * cellScale;
float r2 = dot(d, d);
float sz = lerp(0.75, 1.50, h2);
float core = exp(-r2 / (sz * sz));
float halo = 0.22 * exp(-r2 / (sz * sz * 7.0));
float flareMask = step(0.92, h1);
float crossFlare = (exp(-abs(d.x) * 1.4) * exp(-abs(d.y) * 0.35) + exp(-abs(d.y) * 1.4) * exp(-abs(d.x) * 0.35)) * 0.35 * flareMask;
float twinkle = 0.72 + 0.28 * sin(time * (1.1 + h3 * 1.6) + h1 * 45.0);
float3 col = lerp(tintA, tintB, h3);
col = lerp(col, float3(1.0, 0.99, 0.96), saturate(core + crossFlare));
return col * (core + halo + crossFlare) * present * twinkle;
}
float4 main(float2 uv : TEXCOORD) : COLOR
{
float w = size.x;
float u = size.y;
float2 px = float2(uv.x * w, rise(uv) * u);
float live = saturate(playing);
float vol = saturate(level) * live;
float flick = saturate(beat) * live;
float head = saturate(progress) * w;
float margin = u * 1.35;
float hx = clamp(head, margin, max(w - margin, margin));
float hy = u * 0.50;
float edge = smoothstep(0.0, u * 0.12, px.y) * smoothstep(u, u * 0.88, px.y);
float played = smoothstep(head + u * 0.25, head - u * 0.65, px.x);
float trackAlpha = lerp(0.15, 0.78, played) * edge;
float3 spaceDark = float3(0.025, 0.035, 0.075);
float3 nebCyan = float3(0.06, 0.38, 0.68);
float3 nebViolet = float3(0.42, 0.12, 0.52);
float3 nebAmber = float3(0.88, 0.42, 0.14);
float3 diskOuter = lerp(float3(0.80, 0.18, 0.03), colorA.rgb, USE_APP_COLOR * 0.65);
float3 diskMid = lerp(float3(1.00, 0.56, 0.12), colorC.rgb, USE_APP_COLOR * 0.65);
float3 diskHot = float3(1.00, 0.96, 0.88);
float3 acc = float3(0.0, 0.0, 0.0);
float cover = 0.0;
float2 d = px - float2(hx, hy);
float2 q = d / u;
float r = length(q);
float lensPull = 0.13 / (r * r + 0.048) * smoothstep(2.4, 0.18, r);
float2 lensedPx = px - d * lensPull;
float2 nebUV = float2((lensedPx.x - time * u * 0.16) / (u * 2.1), (lensedPx.y - hy) / (u * 0.90));
float warp = fbm(nebUV * 1.35 - float2(time * 0.05, 0.0));
float cloud = fbm(nebUV * 2.3 + warp * 1.5);
float ridge = 1.0 - abs(2.0 * vnoise(nebUV * 3.8 + warp * 1.4) - 1.0);
float filament = pow(saturate(ridge), 4.5) * smoothstep(0.35, 0.70, cloud);
float dustLane = smoothstep(0.42, 0.72, fbm(nebUV * 3.2 - warp + 5.1));
float3 bgCol = spaceDark;
float nebMask = smoothstep(0.30, 0.76, cloud);
float3 nebMix = lerp(nebCyan, nebViolet, smoothstep(0.25, 0.75, warp));
nebMix = lerp(nebMix, nebAmber, pow(nebMask, 2.2) * 0.75);
bgCol += nebMix * nebMask * 0.80;
bgCol += lerp(nebAmber, diskHot, 0.45) * filament * (0.55 + 0.35 * vol);
bgCol *= lerp(1.0, 0.28, dustLane * smoothstep(0.85, 0.0, abs(q.y)));
layer(acc, cover, bgCol, trackAlpha);
float2 starPx1 = float2(lensedPx.x - time * u * 0.11, lensedPx.y);
float2 starPx2 = float2(lensedPx.x - time * u * 0.25, lensedPx.y);
float3 stars = renderStarLayer(starPx1, u * 0.44, 1.0, float3(0.60, 0.82, 1.0), float3(1.0, 0.86, 0.65));
stars += renderStarLayer(starPx2, u * 0.30, 2.0, float3(0.55, 0.75, 1.0), float3(1.0, 0.72, 0.55)) * 0.70;
float starVis = smoothstep(0.22, 0.38, r) * lerp(0.25, 1.0, played) * edge;
layer(acc, cover, stars, saturate(max(stars.r, max(stars.g, stars.b))) * starVis);
[unroll]
for (int i = 0; i < 3; i++)
{
float fi = (float)i + 1.0;
float hA = hash1(fi * 23.1);
float hB = hash1(fi * 53.7);
float hC = hash1(fi * 83.9);
float dir = (i == 1) ? -1.0 : 1.0;
float speed = u * lerp(0.65, 1.15, hA) * dir;
float period = max(w * 0.65, u * 12.0);
float worldPhase = (px.x - time * speed + hB * period) / period;
float relX = (frac(worldPhase) - 0.5) * period;
float waveFreq = 0.8 + 0.4 * hA;
float waveArg = time * waveFreq + fi * 2.3;
float cy = u * lerp(0.24, 0.76, hC) + sin(waveArg) * (u * 0.09);
float slope = cos(waveArg) * 0.11 * dir;
float2 cd = rot(float2(relX * dir, px.y - cy), slope);
float cometSz = u * lerp(0.022, 0.036, hA);
float headGlow = exp(-dot(cd, cd) / (cometSz * cometSz));
float tailX = clamp(-cd.x, 0.0, u * 0.95);
float tailW = cometSz * (0.45 + tailX / (u * 0.65));
float tailCurve = sin(tailX / (u * 0.25)) * cometSz * 0.35;
float tailGlow = exp(-pow((cd.y - tailCurve) / tailW, 2.0)) * exp(-tailX / (u * 0.28)) * smoothstep(cometSz * 0.5, -cometSz * 0.5, cd.x);
float3 cometCol = lerp(float3(0.55, 0.85, 1.0), float3(1.0, 0.80, 0.50), hB);
float cometAlpha = saturate(headGlow + tailGlow * 0.48) * smoothstep(0.32, 0.58, r) * lerp(0.20, 0.88, played) * edge;
layer(acc, cover, lerp(cometCol, diskHot, headGlow * 0.75), cometAlpha);
}
float rEH = 0.195 * (1.0 + 0.04 * vol + 0.05 * flick);
float2 shCoord = float2(q.x + 0.28, q.y * 1.40);
float gravShadow = exp(-dot(shCoord, shCoord) * 1.35) * 0.70 + exp(-r * r * 2.2) * 0.80;
layer(acc, cover, float3(0.01, 0.015, 0.03), saturate(gravShadow) * edge);
if (q.x < 0.15)
{
float wakeLen = clamp(-q.x, 0.0, 4.2);
float targetY = -q.x * 0.14 - 0.02 + sin(q.x * 4.2 - time * 3.6) * 0.055 * smoothstep(0.0, 1.2, wakeLen);
float streamDist = abs(q.y - targetY);
float streamWidth = 0.036 + wakeLen * 0.028;
float streamCore = exp(-(streamDist * streamDist) / (streamWidth * streamWidth));
float streamFade = exp(-wakeLen * 0.62) * smoothstep(0.05, -0.32, q.x);
float plasmaFlow = 0.68 + 0.32 * sin(q.x * 15.0 - time * 8.5 + streamDist * 12.0);
float3 wakeCol = lerp(diskOuter, diskMid, streamCore * plasmaFlow);
wakeCol = lerp(wakeCol, diskHot, pow(streamCore, 2.8) * (0.45 + 0.35 * vol));
float wakeAlpha = streamCore * streamFade * (0.68 + 0.22 * vol + 0.20 * flick) * played * edge;
layer(acc, cover, wakeCol, wakeAlpha);
}
float pulseR = (1.0 - flick) * 1.10 + rEH * 1.15;
float ringWave = exp(-pow((r - pulseR) / 0.038, 2.0)) * flick;
layer(acc, cover, lerp(diskMid, diskHot, 0.65), ringWave * 0.65 * edge);
float archR = length(float2(q.x * 0.90, q.y * 1.16));
float archBand = exp(-pow((archR - rEH * 1.24) / (0.078 + 0.020 * vol), 2.0));
float2 qRotBack = rot(q, -time * 1.5);
float angBack = atan2(qRotBack.y, qRotBack.x);
float spiralBack = 0.72 + 0.28 * sin(angBack * 7.0 + archR * 22.0 - time * 3.0);
float doppler = smoothstep(0.55, -0.45, q.x);
float3 archCol = lerp(diskOuter, diskMid, saturate(archBand * 1.15 * spiralBack + doppler * 0.35));
archCol = lerp(archCol, diskHot, pow(archBand, 2.4) * (0.50 + 0.35 * doppler + 0.25 * flick));
float archAlpha = archBand * (0.82 + 0.18 * spiralBack) * (0.88 + 0.22 * vol) * edge;
layer(acc, cover, archCol, archAlpha);
float ehMask = smoothstep(rEH + 0.012, rEH - 0.012, r);
float3 voidCol = float3(0.018, 0.026, 0.052) * (1.0 - 0.5 * smoothstep(rEH, 0.0, r));
layer(acc, cover, voidCol, ehMask * 0.90 * edge);
float photon1 = exp(-pow((r - rEH * 1.015) / 0.014, 2.0));
float photon2 = exp(-pow((r - rEH * 1.085) / 0.022, 2.0)) * 0.45;
float photonTotal = saturate(photon1 + photon2);
float3 photonCol = lerp(diskMid, diskHot, 0.82 + 0.18 * doppler);
layer(acc, cover, photonCol * (1.25 + 0.35 * flick), photonTotal * (0.95 + 0.20 * vol) * edge);
float2 dq = rot(q, -0.14);
dq.y += 0.020;
float2 diskEll = float2(dq.x * 0.35, dq.y * 2.85);
float rDisk = length(diskEll);
float frontMask = smoothstep(0.065, -0.025, dq.y);
float outsideSphere = smoothstep(rEH * 0.90, rEH * 1.06, r);
float frontOcclusion = max(frontMask, outsideSphere);
float diskAng = atan2(diskEll.y, diskEll.x);
float spiralWave1 = sin(diskAng * 5.0 - log(max(rDisk, 0.04)) * 9.0 - time * 4.2);
float spiralWave2 = cos(diskAng * 8.0 - rDisk * 26.0 - time * 5.5);
float diskTex = 0.72 + 0.18 * spiralWave1 + 0.10 * spiralWave2;
float diskProfile = smoothstep(0.065, 0.13, rDisk) * exp(-pow(max(rDisk - 0.135, 0.0) / (0.20 + 0.045 * vol), 1.60));
float innerHotRim = exp(-pow((rDisk - 0.115) / 0.038, 2.0));
float3 frontCol = lerp(diskOuter, diskMid, saturate(diskProfile * diskTex * 1.15 + doppler * 0.32));
frontCol = lerp(frontCol, diskHot, saturate(innerHotRim * 0.90 + pow(diskProfile, 2.0) * doppler * 0.55 + flick * 0.25));
float frontAlpha = saturate(diskProfile * (0.88 + 0.25 * diskTex) + innerHotRim * 0.55) * frontOcclusion * edge;
layer(acc, cover, frontCol, frontAlpha);
return paint(acc / max(cover, 0.001), saturate(cover));
}