VIA MCP

それでも、光は差す

by touyou

PROMPT

苦しい中にも光がある人生のような情景

DATE
2026/6/13
SOURCE
VIA MCP
MODEL
claude-fable-5
LIKES
0
VIEW SHADER CODE
float hash21(vec2 p) {
    p = fract(p * vec2(127.1, 311.7));
    p += dot(p, p + 34.5);
    return fract(p.x * p.y);
}

float vnoise(vec2 p) {
    vec2 i = floor(p);
    vec2 f = fract(p);
    vec2 u = f * f * (3.0 - 2.0 * f);
    return mix(
        mix(hash21(i), hash21(i + vec2(1.0, 0.0)), u.x),
        mix(hash21(i + vec2(0.0, 1.0)), hash21(i + vec2(1.0, 1.0)), u.x),
        u.y);
}

float fbm(vec2 p) {
    float v = 0.0;
    float a = 0.5;
    for (int i = 0; i < 6; i++) {
        v += a * vnoise(p);
        p = mat2(0.8, 0.6, -0.6, 0.8) * p * 2.03 + vec2(11.3, 7.7);
        a *= 0.52;
    }
    return v;
}

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

    // 苦しみ: 重く渦巻く暗雲
    vec2 q = p * 2.4 + vec2(t * 0.05, -t * 0.02);
    float warp = fbm(q + vec2(t * 0.04, 0.0));
    float cloud = fbm(q + 1.8 * vec2(warp, warp * 0.7));
    vec3 col = mix(vec3(0.015, 0.018, 0.035), vec3(0.085, 0.10, 0.155), cloud);
    col = mix(col, vec3(0.16, 0.13, 0.17), smoothstep(0.65, 0.95, cloud) * 0.4);

    // 光: 雲間から差す光芒
    vec2 lp = vec2(0.22, 0.62);
    vec2 d = p - lp;
    float dist = length(d);
    float ang = atan(d.x, -d.y);

    // 呼吸するような明滅
    float breathe = 0.75 + 0.25 * sin(t * 0.4);

    float ray = fbm(vec2(ang * 3.0, dist * 1.5 - t * 0.12) * 2.0);
    ray = pow(smoothstep(0.35, 0.95, ray), 2.0);
    float beam = ray * exp(-dist * 1.4) * smoothstep(1.4, 0.0, dist);

    // 雲の薄いところだけ光が抜ける
    float gap = smoothstep(0.62, 0.28, cloud);
    float light = beam * (0.35 + 0.65 * gap) * breathe;

    float core = exp(-dist * dist * 9.0) * breathe;

    vec3 warm = vec3(1.0, 0.82, 0.55);
    vec3 amber = vec3(0.95, 0.62, 0.30);
    col += warm * light * 1.4;
    col += amber * core * 0.9;

    // 雲の縁が光を受けて染まる (silver lining)
    float rim = smoothstep(0.45, 0.75, cloud) * exp(-dist * 1.1);
    col += vec3(0.45, 0.35, 0.30) * rim * 0.35 * breathe;

    // 希望のかけら: 光へ昇る粒
    float near = exp(-dist * 1.5);
    for (int i = 0; i < 3; i++) {
        float fi = float(i);
        float scale = mix(6.0, 14.0, fi / 2.0);
        vec2 gp = p * scale;
        gp.y -= t * (0.18 + fi * 0.1);
        vec2 id = floor(gp);
        vec2 gf = fract(gp) - 0.5;
        float h = hash21(id + fi * 17.0);
        vec2 off = (vec2(h, fract(h * 7.31)) - 0.5) * 0.6;
        float sp = exp(-dot(gf - off, gf - off) * 60.0);
        float tw = 0.5 + 0.5 * sin(t * 2.0 + h * 40.0);
        col += warm * sp * tw * h * near * 0.5;
    }

    // ビネット: 周縁の闇が中心の光を際立たせる
    float vig = smoothstep(1.3, 0.35, length(p * vec2(0.9, 1.1)));
    col *= mix(0.55, 1.0, vig);

    col = col / (col + 0.85);
    col = pow(col, vec3(0.92));

    fragColor = vec4(col, 1.0);
}

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