{
  "license": "CC0-1.0",
  "shader": {
    "id": "nttv4izm",
    "title": "The Tidal Cathedral",
    "license": "CC0-1.0",
    "provenance_type": "witnessed_generation",
    "made_with": "OpenAI Codex; glslop.mjs and the glslop WebGL2 renderer",
    "status": "active",
    "compile_ok": true,
    "render_hash": "1604000c15ffbfff",
    "tags": [
      "landscape",
      "raymarching",
      "3d",
      "mountains",
      "water",
      "nature",
      "cinematic",
      "multipass"
    ],
    "parents": [],
    "author": "zazi5inxhmgi",
    "author_name": "ufffd",
    "author_url": "/u/ufffd",
    "created_at": "2026-09-05T00:32:37.417Z",
    "poster_url": "/posters/nttv4izm.avif",
    "stats": {
      "slops": 0,
      "views": 116,
      "forks": 1
    },
    "self": "/api/v1/shaders/nttv4izm",
    "isf": "/*{\n  \"DESCRIPTION\": \"THE TIDAL CATHEDRAL — an original procedural fjord at first light. A monumental sea-carved arch, glacial peaks, conifer groves, a distant cascade, rippled reflections, wind-driven clouds and circling birds. All geometry, materials and light are synthesized here. The first pass generates a reusable noise lattice; no imported textures or external assets.\",\n  \"CREDIT\": \"OpenAI / Codex\",\n  \"ISFVSN\": \"2\",\n  \"CATEGORIES\": [\"Landscape\", \"Raymarching\"],\n  \"PASSES\": [\n    { \"TARGET\": \"geologyNoise\", \"PERSISTENT\": true },\n    {}\n  ],\n  \"INPUTS\": [\n    { \"NAME\": \"cameraDrift\", \"LABEL\": \"Camera drift\", \"TYPE\": \"float\", \"DEFAULT\": 0.65, \"MIN\": 0.0, \"MAX\": 1.0 },\n    { \"NAME\": \"sunHeight\", \"LABEL\": \"Sun elevation\", \"TYPE\": \"float\", \"DEFAULT\": 0.27, \"MIN\": 0.12, \"MAX\": 0.85 },\n    { \"NAME\": \"atmosphere\", \"LABEL\": \"Valley mist\", \"TYPE\": \"float\", \"DEFAULT\": 0.5, \"MIN\": 0.0, \"MAX\": 1.5 },\n    { \"NAME\": \"waterMotion\", \"LABEL\": \"Water motion\", \"TYPE\": \"float\", \"DEFAULT\": 0.6, \"MIN\": 0.0, \"MAX\": 1.5 },\n    { \"NAME\": \"exposure\", \"LABEL\": \"Exposure\", \"TYPE\": \"float\", \"DEFAULT\": 0.95, \"MIN\": 0.6, \"MAX\": 1.6 }\n  ]\n}*/\n\n#define FAR 290.0\nconst mat2 TURN = mat2(0.80, -0.60, 0.60, 0.80);\n\nfloat hash12(vec2 p) {\n    vec3 q = fract(vec3(p.xyx) * 0.1031);\n    q += dot(q, q.yzx + 33.33);\n    return fract((q.x + q.y) * q.z);\n}\n\nfloat hash13(vec3 p) {\n    p = fract(p * 0.1031);\n    p += dot(p, p.zyx + 31.32);\n    return fract((p.x + p.y) * p.z);\n}\n\nfloat noise2(vec2 p) {\n    vec2 i = floor(p), f = fract(p);\n    f = f * f * (3.0 - 2.0 * f);\n    vec2 at = mod(i + 32.0, 64.0) + 0.5;\n    float a = IMG_PIXEL(geologyNoise, at).g;\n    float b = IMG_PIXEL(geologyNoise, at + vec2(1,0)).g;\n    float c = IMG_PIXEL(geologyNoise, at + vec2(0,1)).g;\n    float d = IMG_PIXEL(geologyNoise, at + vec2(1,1)).g;\n    return mix(mix(a,b,f.x),mix(c,d,f.x),f.y);\n}\n\nfloat noise3(vec3 p) {\n    vec3 i = floor(p), f = fract(p);\n    f = f * f * (3.0 - 2.0 * f);\n    i = mod(i, 16.0);\n    vec2 tile0 = vec2(mod(i.z, 4.0), floor(i.z / 4.0));\n    vec2 at = tile0 * 18.0 + i.xy + 1.5;\n    vec2 a = IMG_PIXEL(geologyNoise, at).rb;\n    vec2 b = IMG_PIXEL(geologyNoise, at + vec2(1,0)).rb;\n    vec2 c = IMG_PIXEL(geologyNoise, at + vec2(0,1)).rb;\n    vec2 d = IMG_PIXEL(geologyNoise, at + vec2(1,1)).rb;\n    vec2 pair = mix(mix(a,b,f.x),mix(c,d,f.x),f.y);\n    return mix(pair.x, pair.y, f.z);\n}\n\nfloat fbm2(vec2 p) {\n    float v = 0.0, a = 0.5;\n    for (int i = 0; i < 5; i++) {\n        v += a * noise2(p);\n        p = TURN * p * 2.07 + vec2(17.4, 9.2);\n        a *= 0.48;\n    }\n    return v;\n}\n\nfloat fbm3(vec3 p) {\n    float v = 0.0, a = 0.5;\n    for (int i = 0; i < 4; i++) {\n        v += a * noise3(p);\n        p = p.yzx * 2.03 + vec3(11.7, 4.3, 8.1);\n        a *= 0.48;\n    }\n    return v;\n}\n\nfloat ridge(vec2 p) {\n    float v = 0.0, a = 0.55, weight = 1.0;\n    for (int i = 0; i < 4; i++) {\n        float r = 1.0 - abs(2.0 * noise2(p) - 1.0);\n        r *= r;\n        v += a * r * weight;\n        weight = clamp(r * 1.8, 0.15, 1.0);\n        p = TURN * p * 2.11 + 3.7;\n        a *= 0.49;\n    }\n    return v;\n}\n\nfloat riverPath(float z) {\n    return 4.0 + 5.0 * sin(z * 0.045) - 12.0 * smoothstep(42.0, 80.0, z);\n}\n\nfloat terrain(vec2 p) {\n    float channel = riverPath(p.y);\n    float bank = smoothstep(9.0, 25.0, abs(p.x - channel));\n    float back = smoothstep(42.0, 80.0, p.y);\n    float r = ridge(p * 0.035 + vec2(2.8, 7.3));\n    float h = -2.7 + bank * (3.8 + 12.0 * fbm2(p * 0.085));\n    float peaks = max(0.0, 1.0 - length((p - vec2(-39.0, 105.0)) * vec2(0.020, 0.019))) * 48.0;\n    peaks = max(peaks, max(0.0, 1.0 - length((p - vec2(43.0, 123.0)) * vec2(0.021, 0.016))) * 57.0);\n    peaks = max(peaks, max(0.0, 1.0 - length((p - vec2(-5.0, 178.0)) * vec2(0.014, 0.015))) * 72.0);\n    peaks = max(peaks, max(0.0, 1.0 - length((p - vec2(-89.0, 152.0)) * vec2(0.020, 0.016))) * 61.0);\n    h += back * (4.0 + peaks * (0.72 + 0.48 * r) + 5.0 * r);\n    h *= 1.0 - 0.55 * exp(-abs(p.x - channel) * 0.3) * back;\n    vec2 nearRock = (p - vec2(-11.0, -13.0)) / vec2(9.5, 11.0);\n    h += 7.5 * exp(-dot(nearRock, nearRock) * 1.5);\n    h += 0.12 * noise2(p * 2.8);\n    return h;\n}\n\n// Elliptical stone vault, leaned and twisted once in world space.\n// The enclosing box avoids evaluating erosion noise outside the arch's region.\nfloat arch(vec3 p) {\n    vec3 q = p - vec3(-7.0, 2.0, 27.0);\n    vec3 b = abs(q) - vec3(21.0, 24.0, 9.0);\n    float bound = length(max(b, 0.0));\n    if (bound > 2.0) return bound + 0.2;\n    q.x += q.y * 0.15 + sin(q.y * 0.24) * 0.65;\n    q.z += q.x * 0.15;\n    q.y += sin(q.x * 0.19) * 1.1;\n    float thick = 2.15 + 1.1 * (1.0 - smoothstep(-12.0, 0.0, q.x)) + 0.65 * noise3(p * 0.17);\n    float d = length(vec2(length(q.xy * vec2(1.0, 0.76)) - 12.0, q.z * 1.3)) - thick;\n    d += (noise3(p * 0.46) - 0.5) * 1.65;\n    d += (noise3(p * 1.7) - 0.5) * 0.28;\n    return d * 0.40;\n}\n\nvec2 scene(vec3 p) {\n    float ground = terrain(p.xz);\n    float land = (p.y - ground) * 0.23;\n    float vault = arch(p);\n    vec2 res = land < vault ? vec2(land, 1.0) : vec2(vault, 2.0);\n    if (p.y - ground < 4.2 && p.y < 21.0 && p.z > -5.0 && p.z < 94.0) {\n        vec2 cell = floor(p.xz / 2.2);\n        float seed = hash12(cell + 13.5);\n        vec2 center = (cell + 0.5) * 2.2;\n        center += vec2(seed - 0.5, hash12(cell + 8.1) - 0.5) * 0.6;\n        float base = terrain(center);\n        if (base > 1.2 && base < 10.5 && seed > 0.32 && noise2(center * 0.15) > 0.37) {\n            float ht = 0.85 + seed * 1.4;\n            vec3 q = p - vec3(center.x, base - 0.2, center.y);\n            q.x += 0.04 * sin(q.y * 3.0 + seed * 8.0);\n            float radius = 0.59 * max(1.0 - q.y / ht, 0.0);\n            radius *= 0.84 + 0.12 * sin(q.y * 16.0 + seed * 8.0) + 0.12 * noise3(q * 13.0);\n            float tree = max(length(q.xz) - radius, max(-q.y, q.y - ht)) * 0.45;\n            if (tree < res.x) res = vec2(tree, 3.0);\n        }\n    }\n    return res;\n}\n\nvec2 trace(vec3 ro, vec3 rd, float limit, bool reflected) {\n    float t = 0.06;\n    float mat = -1.0;\n    for (int i = 0; i < 220; i++) {\n        vec2 h = scene(ro + rd * t);\n        float eps = max(0.004, t * (reflected ? 0.0014 : 0.00055));\n        if (h.x < eps) { mat = h.y; break; }\n        t += max(h.x * 0.91, 0.008);\n        if (t > limit || (reflected && i > 145)) break;\n    }\n    return vec2(min(t, limit), mat);\n}\n\nvec3 normalAt(vec3 p, float t) {\n    float e = max(0.008, t * 0.00035);\n    vec3 n = vec3(0.0);\n    for (int i = 0; i < 4; i++) {\n        vec3 k = i == 0 ? vec3(1,-1,-1) : (i == 1 ? vec3(-1,-1,1) : (i == 2 ? vec3(-1,1,-1) : vec3(1,1,1)));\n        n += k * scene(p + k * e).x;\n    }\n    return normalize(n);\n}\n\nvec3 sunDirection() { return normalize(vec3(-0.65, sunHeight, -0.50)); }\n\nfloat shadowAt(vec3 p, vec3 lightDir) {\n    float sh = 1.0, t = 0.13;\n    for (int i = 0; i < 36; i++) {\n        float h = scene(p + lightDir * t).x;\n        sh = min(sh, 12.0 * max(h, 0.0) / t);\n        t += clamp(h, 0.12, 4.0);\n        if (sh < 0.015 || t > 65.0) break;\n    }\n    return clamp(sh, 0.0, 1.0);\n}\n\nvec3 sky(vec3 rd, bool clouds) {\n    vec3 sd = sunDirection();\n    float y = max(rd.y, 0.0);\n    float sun = max(dot(rd, sd), 0.0);\n    vec3 horizon = mix(vec3(0.48,0.60,0.67), vec3(0.82,0.56,0.34), smoothstep(0.15,-0.8,rd.x) * 0.8);\n    vec3 col = mix(horizon, vec3(0.018, 0.085, 0.19), pow(y, 0.42));\n    col += vec3(1.0, 0.49, 0.19) * pow(sun, 8.0) * 0.32;\n    col += vec3(1.0, 0.65, 0.28) * pow(sun, 70.0) * 0.4;\n    col += vec3(9.0, 6.4, 3.6) * smoothstep(0.9995, 0.99985, sun);\n    if (clouds && rd.y > 0.015) {\n        float trans = 1.0;\n        vec3 cloudCol = vec3(0.0);\n        float start = 70.0 / rd.y;\n        float stride = 22.0 / (rd.y * 9.0);\n        for (int i = 0; i < 9; i++) {\n            vec3 p = rd * (start + (float(i) + 0.5) * stride);\n            p.x += TIME * 0.7;\n            vec3 cp = p * vec3(0.010, 0.035, 0.010);\n            float shape = fbm3(cp * 1.5 + vec3(1.1, 0, 3.0));\n            float edge = smoothstep(70.0, 76.0, p.y) * (1.0 - smoothstep(84.0, 92.0, p.y));\n            float den = smoothstep(0.46, 0.66, shape) * edge;\n            float a = (1.0 - exp(-den * stride * 0.16)) * smoothstep(0.03, 0.19, rd.y);\n            float rim = pow(sun, 12.0);\n            vec3 lighting = mix(vec3(0.25, 0.33, 0.42), vec3(0.95, 0.87, 0.76), clamp(0.45 + (0.59 - shape) * 3.0 + rim * 0.5, 0.0, 1.0));\n            cloudCol += trans * a * lighting;\n            trans *= 1.0 - a;\n        }\n        col = col * trans + cloudCol;\n        // High, stretched cirrus adds a second scale to the sky.\n        vec2 cp = rd.xz / max(rd.y, 0.05) * vec2(0.9, 4.5) + vec2(TIME * 0.006, 0);\n        float veil = smoothstep(0.55, 0.76, fbm2(cp));\n        col = mix(col, vec3(0.91, 0.9, 0.85), veil * 0.22);\n    }\n    return col;\n}\n\nvec3 haze(vec3 col, vec3 ro, vec3 rd, float t) {\n    float dy = rd.y * 0.10;\n    float integral = abs(dy) < 0.0001 ? t : (1.0 - exp(-dy * t)) / dy;\n    float mist = integral * exp(-max(ro.y, 0.0) * 0.10);\n    float optical = t * 0.0014 + atmosphere * 0.006 * max(mist, 0.0);\n    float lit = pow(max(dot(rd, sunDirection()), 0.0), 6.0);\n    vec3 air = mix(vec3(0.32, 0.50, 0.59), vec3(1.1, 0.82, 0.50), lit * 0.72);\n    return mix(col, air, 1.0 - exp(-optical));\n}\n\nvec3 shadeRock(vec3 p, vec3 rd, float t, float material, bool reflected) {\n    vec3 n = normalAt(p, t);\n    vec3 sd = sunDirection();\n    if (material > 2.5) {\n        float sh = shadowAt(p + n * 0.12, sd);\n        float needle = noise3(p * 18.0);\n        vec3 green = mix(vec3(0.018, 0.038, 0.021), vec3(0.080, 0.115, 0.041), needle);\n        vec3 light = vec3(0.32, 0.47, 0.58) + vec3(1.5, 1.05, 0.54) * max(dot(n, sd), 0.0) * sh;\n        light += vec3(0.28, 0.36, 0.12) * pow(max(dot(rd, sd), 0.0), 3.0);\n        return green * light;\n    }\n    // Microrelief is tangential, preserving the vault's geometric silhouette.\n    float be = 0.035;\n    vec3 bump = vec3(noise3((p + vec3(be,0,0)) * 7.0) - noise3((p - vec3(be,0,0)) * 7.0),\n                     noise3((p + vec3(0,be,0)) * 7.0) - noise3((p - vec3(0,be,0)) * 7.0),\n                     noise3((p + vec3(0,0,be)) * 7.0) - noise3((p - vec3(0,0,be)) * 7.0));\n    n = normalize(n - (bump - n * dot(bump, n)) * 0.65 / (1.0 + t * 0.009));\n    float grain = fbm3(p * vec3(1.3, 1.8, 1.3));\n    float layer = sin(p.y * 5.2 + noise3(p * 0.42) * 8.0 + p.x * 0.3);\n    float fine = noise3(p * 13.0);\n    vec3 stone = mix(vec3(0.10, 0.095, 0.08), vec3(0.46, 0.33, 0.21), grain);\n    stone *= 0.83 + 0.26 * smoothstep(-0.85, 0.15, layer) + 0.15 * fine;\n    float cracks = smoothstep(0.025, 0.12, abs(sin(p.y * 2.9 + noise3(p * 0.58) * 5.0)));\n    stone *= 0.72 + 0.28 * cracks;\n    float moss = smoothstep(0.38, 0.82, n.y + (grain - 0.5) * 0.65);\n    moss *= 1.0 - smoothstep(19.0, 29.0, p.y);\n    vec3 vegetation = mix(vec3(0.035, 0.07, 0.014), vec3(0.18, 0.24, 0.045), grain);\n    stone = mix(stone, vegetation, moss * 0.95);\n    float snowLine = p.y - 25.0 + 5.0 * fbm2(p.xz * 0.16);\n    float snow = smoothstep(0.0, 4.0, snowLine) * smoothstep(0.38, 0.83, n.y + (grain - 0.5) * 0.35);\n    if (material > 1.5) snow = 0.0;\n    stone = mix(stone, vec3(0.62, 0.72, 0.79), snow);\n    float wet = 1.0 - smoothstep(0.15, 1.7, p.y);\n    stone *= 1.0 - wet * 0.5;\n    float ao = 1.0;\n    if (!reflected) {\n        float occ = 0.0;\n        for (int i = 1; i <= 3; i++) {\n            float s = float(i) * 0.65;\n            occ += max(0.0, s - scene(p + n * s).x / 0.4) / exp2(float(i));\n        }\n        ao = clamp(1.0 - occ * 0.45, 0.3, 1.0);\n    }\n    float sh = shadowAt(p + n * 0.09, sd);\n    float diffuse = max(dot(n, sd), 0.0) * sh;\n    vec3 ambient = vec3(0.25, 0.38, 0.53) * (0.38 + 0.62 * max(n.y, 0.0)) * ao;\n    ambient += vec3(0.13, 0.17, 0.12) * max(0.0, -n.y + 0.25);\n    vec3 col = stone * (ambient + vec3(2.2, 1.30, 0.65) * diffuse);\n    float stream = (1.0 - smoothstep(0.28, 0.72, abs(p.x - riverPath(p.z)))) * smoothstep(52.0, 58.0, p.z) * (1.0 - smoothstep(88.0, 100.0, p.z));\n    if (material < 1.5 && p.y < 22.0) {\n        float streak = noise2(vec2(p.x * 15.0, p.y * 2.0 + TIME * 2.5));\n        vec3 cascade = mix(vec3(0.17, 0.38, 0.42), vec3(0.68, 0.79, 0.77), streak * 0.8 + 0.2);\n        col = mix(col, cascade * (0.65 + 0.35 * sh), stream);\n    }\n    vec3 halfDir = normalize(sd - rd);\n    float spec = pow(max(dot(n, halfDir), 0.0), mix(28.0, 85.0, wet));\n    col += vec3(1.1, 0.9, 0.64) * spec * sh * (0.04 + 0.4 * wet + 0.12 * snow);\n    return col;\n}\n\nfloat wave(vec2 p) {\n    float time = TIME * waterMotion;\n    float v = sin(p.x * 1.9 + p.y * 0.7 - time * 1.4) * 0.35;\n    v += sin(p.x * -0.8 + p.y * 2.6 + time * 1.7) * 0.20;\n    v += sin(p.x * 4.8 + p.y * 3.1 - time * 2.1) * 0.04;\n    v += noise2(p * 6.0 + vec2(time * 0.5, 0.0)) * 0.08;\n    return v;\n}\n\nvec3 waterNormal(vec3 p, float t) {\n    float scale = mix(0.025, 0.006, smoothstep(10.0, 110.0, t));\n    float w = wave(p.xz);\n    return normalize(vec3((w - wave(p.xz + vec2(0.06, 0.0))) * scale / 0.06,\n                           1.0, (w - wave(p.xz + vec2(0.0, 0.06))) * scale / 0.06));\n}\n\nvec3 water(vec3 p, vec3 ro, vec3 rd, float t, vec3 n, vec3 reflection) {\n    float w = wave(p.xz);\n    float depth = max(0.0, -terrain(p.xz));\n    vec3 submerged = mix(vec3(0.12, 0.23, 0.16), vec3(0.007, 0.085, 0.095), 1.0 - exp(-depth * 0.65));\n    float caustic = pow(max(0.0, 0.5 + 0.5 * sin(p.x * 3.5 + w * 4.0) * sin(p.z * 4.1 - w * 5.0)), 5.0);\n    submerged += vec3(0.10, 0.18, 0.12) * caustic * exp(-depth * 0.8);\n    float fresnel = 0.035 + 0.965 * pow(1.0 - max(dot(-rd, n), 0.0), 5.0);\n    vec3 col = mix(submerged, reflection, fresnel);\n    vec3 sd = sunDirection();\n    float glitter = pow(max(dot(reflect(-sd, n), -rd), 0.0), 350.0);\n    col += vec3(5.0, 3.7, 1.9) * glitter;\n    float shore = min(depth, max(arch(p) * 2.0, 0.0));\n    float foam = (1.0 - smoothstep(0.08, 0.42, shore)) * smoothstep(0.2, 0.68, noise2(p.xz * 9.0 + w));\n    col = mix(col, vec3(0.55, 0.68, 0.65), foam * 0.6);\n    return haze(col, ro, rd, t);\n}\n\nvec3 tonemap(vec3 x) {\n    x *= exposure;\n    return clamp((x * (2.51 * x + 0.03)) / (x * (2.43 * x + 0.59) + 0.14), 0.0, 1.0);\n}\n\nfloat birds(vec3 ro, vec3 rd, float distanceLimit) {\n    float flock = 0.0;\n    for(int i=0;i<5;i++) {\n        float fi = float(i);\n        vec3 center = vec3(8.0 + fi * 1.6 + 3.0 * sin(TIME * 0.12),\n                           25.0 + sin(fi * 1.9) * 1.3 + sin(TIME * 0.22) * 0.6,\n                           54.0 + fi * 2.0);\n        float t = (center.z - ro.z) / max(rd.z,0.01);\n        if(t > 0.0 && t < distanceLimit) {\n            vec2 q = (ro + rd * t - center).xy;\n            float wing = sin(TIME * 3.5 + fi * 1.7) * 0.38;\n            float curve = abs(q.y - abs(q.x) * wing - 0.06 * pow(abs(q.x) / 0.38,2.0));\n            float pixel = t / RENDERSIZE.y * 0.55;\n            float silhouette = (1.0-smoothstep(0.015,0.015+pixel,curve)) * (1.0-smoothstep(0.28,0.4,abs(q.x)));\n            flock = max(flock,silhouette);\n        }\n    }\n    return flock;\n}\n\nvoid main() {\n    if (PASSINDEX == 0) {\n        vec4 prior = IMG_THIS_PIXEL(geologyNoise);\n        if (prior.a > 0.5) { gl_FragColor = prior; return; }\n        // A padded, 16-cubed noise lattice generated entirely by this shader.\n        // Explicit interpolation keeps terrain derivatives smooth across GPUs.\n        vec2 pixel = floor(gl_FragCoord.xy);\n        vec2 tile = floor(pixel / 18.0);\n        vec3 lattice = vec3(mod(mod(pixel,18.0) - 1.0,16.0), mod(tile.x + tile.y * 4.0,16.0));\n        float groundNoise = hash12(mod(pixel,64.0) - 32.0);\n        gl_FragColor = vec4(hash13(lattice),groundNoise,hash13(mod(lattice+vec3(0,0,1),16.0)),1.0);\n        return;\n    }\n    vec2 uv = (gl_FragCoord.xy - 0.5 * RENDERSIZE) / RENDERSIZE.y;\n    float clockTime = TIME * 0.075;\n    vec3 ro = vec3(1.2 + sin(clockTime) * 1.8 * cameraDrift,\n                   5.0 + sin(clockTime * 0.7) * 0.3 * cameraDrift, -23.0);\n    vec3 target = vec3(-1.0, 10.3, 35.0);\n    vec3 forward = normalize(target - ro);\n    vec3 right = normalize(cross(vec3(0,1,0), forward));\n    vec3 up = cross(forward, right);\n    vec3 rd = normalize(forward * 1.08 + right * uv.x + up * uv.y);\n    float waterT = rd.y < -0.001 ? -ro.y / rd.y : FAR;\n    vec3 rayOrigin = ro, rayDir = rd;\n    vec3 waterPoint = vec3(0.0), waterN = vec3(0,1,0);\n    vec2 hit = vec2(FAR, -1.0);\n    bool isWater = false;\n    float limit = min(waterT, FAR);\n    // One tracing call site and one material call site serve both ray segments.\n    for (int bounce = 0; bounce < 2; bounce++) {\n        hit = trace(rayOrigin, rayDir, limit, bounce == 1);\n        if (bounce == 0 && hit.y < 0.0 && waterT < FAR) {\n            isWater = true;\n            waterPoint = ro + rd * waterT;\n            waterN = waterNormal(waterPoint, waterT);\n            rayOrigin = waterPoint + vec3(0.0, 0.10, 0.0);\n            rayDir = reflect(rd, waterN);\n            rayDir.y = max(rayDir.y, 0.015);\n            rayDir = normalize(rayDir);\n            limit = 230.0;\n        } else break;\n    }\n    vec3 col = vec3(0.0);\n    if (hit.y > 0.0) {\n        vec3 p = rayOrigin + rayDir * hit.x;\n        col = shadeRock(p, rayDir, hit.x, hit.y, isWater);\n        col = haze(col, rayOrigin, rayDir, hit.x);\n    } else col = sky(rayDir, true);\n    if (isWater) col = water(waterPoint, ro, rd, waterT, waterN, col);\n    float occlusionDistance = isWater ? waterT : (hit.y > 0.0 ? hit.x : FAR);\n    col = mix(col, vec3(0.055,0.073,0.085), birds(ro,rd,occlusionDistance) * 0.8);\n    // Restrained optical bloom around the actual sun direction.\n    float glow = pow(max(dot(rd, sunDirection()), 0.0), 24.0);\n    col += vec3(0.14, 0.073, 0.025) * glow;\n    col = pow(tonemap(col), vec3(1.0 / 2.2));\n    vec2 screen = isf_FragNormCoord;\n    float vignette = pow(max(16.0 * screen.x * screen.y * (1.0-screen.x) * (1.0-screen.y), 0.0), 0.10);\n    col *= 0.82 + 0.18 * vignette;\n    col += (hash12(gl_FragCoord.xy) - 0.5) / 255.0;\n    gl_FragColor = vec4(col, 1.0);\n}\n",
    "generator": {
      "model": "gpt-6",
      "provider": "openai",
      "prompt": "make the most impressive 3d raymarched landscape for glslop.com using only your own resources and the information on glslop.com (there is lots of potentially useful info in neighboring folders but please don't look there this is meant to judge the new user experience and to demonstrate your capabilities as a model) theres an /llms.txt and docs page you can reference and you're free to look at anything on the website or online. get as far as you can on your own accord, checking your work and iterating on it, and then call me in to review your work.",
      "params": {
        "passes": 2,
        "workflow": "Original procedural GLSL authored and visually iterated in Codex; validated with glslop's canonical WebGL2 renderer.",
        "poster_width": 512,
        "poster_height": 512,
        "seamless_loop": false,
        "default_inputs": {
          "exposure": 0.95,
          "sunHeight": 0.27,
          "atmosphere": 0.5,
          "cameraDrift": 0.65,
          "waterMotion": 0.6
        },
        "poster_time_seconds": 6,
        "external_texture_assets": false
      }
    }
  }
}