VIA MCP

呑み込む闇に抗う光

by touyou

PROMPT

宇宙の神秘、全てを呑み込むブラックホールと争う光。重力レンズに歪む星空と渦巻く降着円盤の中心で、事象の地平面に吸い込まれまいと外へ走る光条が引力に抗い続ける。

DATE
2026/6/13
SOURCE
VIA MCP
MODEL
claude-opus-4-8
LIKES
0
VIEW SHADER CODE
float hash(vec2 p) {
    p = fract(p * vec2(123.34, 456.21));
    p += dot(p, p + 45.32);
    return fract(p.x * p.y);
}

float noise(vec2 p) {
    vec2 i = floor(p);
    vec2 f = fract(p);
    f = f * f * (3.0 - 2.0 * f);
    float a = hash(i);
    float b = hash(i + vec2(1.0, 0.0));
    float c = hash(i + vec2(0.0, 1.0));
    float d = hash(i + vec2(1.0, 1.0));
    return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
}

float fbm(vec2 p) {
    float v = 0.0;
    float a = 0.5;
    for (int i = 0; i < 5; i++) {
        v += a * noise(p);
        p = p * 2.1 + vec2(13.7, 7.3);
        a *= 0.5;
    }
    return v;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
    float t = iTime;

    float r = length(uv);
    float ang = atan(uv.y, uv.x);

    // 重力レンズ: 中心に近いほど空間が歪む
    float lens = 0.18 / (r + 0.08);
    vec2 wuv = uv * (1.0 + lens * 0.35);
    float wr = length(wuv);
    float wang = atan(wuv.y, wuv.x);

    vec3 col = vec3(0.0);

    // レンズで渦巻く星空
    float swirl = ang + lens * 2.2 + t * 0.02;
    vec2 sp = vec2(cos(swirl), sin(swirl)) * r;
    vec2 grid = sp * 28.0;
    vec2 gid = floor(grid);
    float star = hash(gid);
    float sd = length(fract(grid) - 0.5);
    float twinkle = 0.5 + 0.5 * sin(t * 3.0 + star * 40.0);
    float stars = smoothstep(0.12, 0.0, sd) * step(0.93, star) * twinkle;
    col += vec3(0.7, 0.8, 1.0) * stars * smoothstep(0.16, 0.4, r);

    // 星雲
    float neb = fbm(uv * 3.0 + vec2(t * 0.03, -t * 0.02));
    col += mix(vec3(0.02, 0.01, 0.06), vec3(0.1, 0.03, 0.16), neb) * smoothstep(0.15, 0.6, r);

    // 降着円盤: 渦巻く高温ガス
    float spiral = sin(wang * 3.0 - t * 1.6 + 12.0 / (wr + 0.25));
    float diskBand = exp(-pow((wr - 0.34) * 7.0, 2.0));
    float diskNoise = fbm(vec2(wang * 2.0 + t * 0.4, wr * 9.0 - t * 0.9));
    float disk = diskBand * (0.6 + 0.5 * spiral) * (0.5 + 0.8 * diskNoise);
    vec3 hot = mix(vec3(1.0, 0.45, 0.1), vec3(0.4, 0.7, 1.0), smoothstep(-1.0, 1.0, sin(wang - t * 0.7)));
    col += hot * disk * 2.2;

    // 抗う光: 引力に逆らって外へ走る光条
    float rayPulse = 0.5 + 0.5 * sin(t * 2.4);
    float rays = pow(abs(sin(ang * 7.0 + t * 1.3 + fbm(vec2(ang * 3.0, t * 0.5)) * 4.0)), 18.0);
    float rayReach = smoothstep(0.95, 0.18, r) * smoothstep(0.14, 0.3, r);
    col += vec3(1.0, 0.9, 0.6) * rays * rayReach * (0.6 + 0.9 * rayPulse);

    // 光子リング
    float ring = exp(-pow((r - 0.17) * 60.0, 2.0));
    col += vec3(1.0, 0.85, 0.55) * ring * 2.5;

    // 事象の地平面: すべてを呑み込む
    float horizon = smoothstep(0.165, 0.13, r);
    col = mix(col, vec3(0.0), horizon);

    // 吸い込まれる青い微光
    float infall = exp(-r * 3.0) * (0.5 + 0.5 * sin(ang * 2.0 - t * 3.0));
    col += vec3(0.15, 0.25, 0.6) * infall * (1.0 - horizon);

    // 周辺減光
    col *= 1.0 - 0.4 * smoothstep(0.6, 1.2, r);

    // トーンマップ
    col = col / (1.0 + col);
    col = pow(col, vec3(0.85));

    fragColor = vec4(col, 1.0);
}

ZIP を展開して .playground を Xcode でダブルクリックし、Live View を表示して ▶ を押すとシェーダーがアニメーションします。Metal ソースは Resources/Shader.metal に独立ファイルとして入っているので、Xcode 上で直接編集できます。