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ụ.

1 lượt tải Tải file, 10.2 KB
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));
}