{
  "license": "CC0-1.0",
  "shader": {
    "id": "1azsp0fq",
    "title": "liqa sto",
    "license": "CC0-1.0",
    "provenance_type": "witnessed_generation",
    "made_with": "glslop",
    "status": "active",
    "compile_ok": true,
    "render_hash": "be7c59c6a7000018",
    "tags": [],
    "parents": [],
    "author": "pt1fjuktt2w0",
    "author_name": "deafadil",
    "author_url": "/u/deafadil",
    "created_at": "2026-09-10T03:30:42.348Z",
    "poster_url": "/posters/1azsp0fq.avif",
    "stats": {
      "slops": 2,
      "views": 119,
      "forks": 0
    },
    "self": "/api/v1/shaders/1azsp0fq",
    "isf": "/*{\n  \"DESCRIPTION\": \"AISLE 4 - an endless PS2-era liquor store. Gondolas, shelves and bottles are all domain repetition, so the store is unbounded and costs one bay: the plan folds x by the aisle pitch and z by the bay length, the shelf level folds y, and the bottles fold again inside the shelf, which is four nested folds and about forty ALU for a shop with no far wall. The bottles are the only thing that must NOT fold cleanly - a rack of identical cylinders reads as wallpaper - so each one draws its height, radius, cap and colour from a hash of its four fold indices, and the SDF is written as a stack of clipped cylinders whose radii come from that hash rather than as one repeated primitive. The PS2 look is not a filter over a modern render, it is the render: the ray is built from a QUANTISED fragment coordinate, so the whole frame is genuinely traced at 320-ish lines and the chunky pixels are real geometry sampling rather than a blur; lighting is a single lambert term plus a fixed ambient with no shadows and no bounce, which is what a fixed-function TnL pipeline actually gave you; the colour is posterised to five bits and pushed through an ordered 4x4 Bayer dither, because the console dithered its way out of a 16-bit framebuffer and that dither pattern is more of the memory than the polygon count is. Fluorescent troffers run down the ceiling over each aisle on their own lattice, gathered nine at a time as RECTANGLES rather than points so the pools they throw are strips and not spots, with one tube per fixture failing on a hash and a mains-frequency buzz on the rest. Twenty-four controls: walk, lens, yaw and pitch, sway, aisle pitch, aisle width, bay length, shelf height, shelf count, bottle density, light spacing, brightness, colour temperature, dead tubes, flicker, four palettes, render resolution, colour depth, dither, fog, vignette and grain.\",\n  \"CREDIT\": \"CC0. Original. Value noise constants after Dave Hoskins.\",\n  \"CATEGORIES\": [\"generator\", \"raymarch\", \"liminal\", \"retro\", \"ps2\", \"interior\", \"procedural\", \"3d\"],\n  \"INPUTS\": [\n    { \"NAME\": \"uSpeed\",    \"TYPE\": \"float\", \"DEFAULT\": 1.60,  \"MIN\": 0.0,   \"MAX\": 6.0 },\n    { \"NAME\": \"uLens\",     \"TYPE\": \"float\", \"DEFAULT\": 1.20,  \"MIN\": 0.7,   \"MAX\": 3.0 },\n    { \"NAME\": \"uYaw\",      \"TYPE\": \"float\", \"DEFAULT\": 0.0,   \"MIN\": -1.57, \"MAX\": 1.57 },\n    { \"NAME\": \"uPitch\",    \"TYPE\": \"float\", \"DEFAULT\": -0.03, \"MIN\": -0.5,  \"MAX\": 0.5 },\n    { \"NAME\": \"uBob\",      \"TYPE\": \"float\", \"DEFAULT\": 1.0,   \"MIN\": 0.0,   \"MAX\": 2.0 },\n    { \"NAME\": \"uPitchX\",   \"TYPE\": \"float\", \"DEFAULT\": 3.60,  \"MIN\": 2.2,   \"MAX\": 7.0 },\n    { \"NAME\": \"uAisle\",    \"TYPE\": \"float\", \"DEFAULT\": 1.05,  \"MIN\": 0.55,  \"MAX\": 2.4 },\n    { \"NAME\": \"uBay\",      \"TYPE\": \"float\", \"DEFAULT\": 6.50,  \"MIN\": 3.0,   \"MAX\": 16.0 },\n    { \"NAME\": \"uShelfH\",   \"TYPE\": \"float\", \"DEFAULT\": 1.95,  \"MIN\": 1.0,   \"MAX\": 2.6 },\n    { \"NAME\": \"uShelves\",  \"TYPE\": \"float\", \"DEFAULT\": 5.0,   \"MIN\": 2.0,   \"MAX\": 8.0 },\n    { \"NAME\": \"uBottles\",  \"TYPE\": \"float\", \"DEFAULT\": 0.86,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uCeil\",     \"TYPE\": \"float\", \"DEFAULT\": 3.05,  \"MIN\": 2.3,   \"MAX\": 5.0 },\n    { \"NAME\": \"uLightSp\",  \"TYPE\": \"float\", \"DEFAULT\": 3.66,  \"MIN\": 1.8,   \"MAX\": 9.0 },\n    { \"NAME\": \"uBright\",   \"TYPE\": \"float\", \"DEFAULT\": 1.0,   \"MIN\": 0.0,   \"MAX\": 3.0 },\n    { \"NAME\": \"uTemp\",     \"TYPE\": \"float\", \"DEFAULT\": 4300.0,\"MIN\": 2400.0,\"MAX\": 7500.0 },\n    { \"NAME\": \"uDead\",     \"TYPE\": \"float\", \"DEFAULT\": 0.10,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uFlicker\",  \"TYPE\": \"float\", \"DEFAULT\": 0.35,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uPalette\",  \"TYPE\": \"float\", \"DEFAULT\": 0.0,   \"MIN\": 0.0,   \"MAX\": 3.0 },\n    { \"NAME\": \"uRes\",      \"TYPE\": \"float\", \"DEFAULT\": 320.0, \"MIN\": 96.0,  \"MAX\": 1080.0 },\n    { \"NAME\": \"uBits\",     \"TYPE\": \"float\", \"DEFAULT\": 5.0,   \"MIN\": 2.0,   \"MAX\": 8.0 },\n    { \"NAME\": \"uDither\",   \"TYPE\": \"float\", \"DEFAULT\": 0.80,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uFog\",      \"TYPE\": \"float\", \"DEFAULT\": 0.030, \"MIN\": 0.0,   \"MAX\": 0.12 },\n    { \"NAME\": \"uVignette\", \"TYPE\": \"float\", \"DEFAULT\": 0.30,  \"MIN\": 0.0,   \"MAX\": 1.0 },\n    { \"NAME\": \"uGrain\",    \"TYPE\": \"float\", \"DEFAULT\": 0.12,  \"MIN\": 0.0,   \"MAX\": 1.0 }\n  ]\n}*/\n\n// AISLE 4 - ISF / GLSL ES 1.00 (gl_FragColor, TIME, RENDERSIZE).\n\n#define PI  3.14159265359\n#define FAR 60.0\n\nfloat gPX, gT, gNS;\nfloat gSpineW, gShelfW, gStep;\nvec3  gLite, pFloorA, pFloorB, pShelf, pCeil, pWall;\n\nfloat hash11(float p){ p = fract(p*0.1031); p *= p + 33.33; p *= p + p; return fract(p); }\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\nvec4 hash42(vec2 p){\n    vec4 q = fract(vec4(p.xyxy)*vec4(0.1031, 0.1030, 0.0973, 0.1099));\n    q += dot(q, q.wzxy + 33.33);\n    return fract((q.xxyz + q.yzzw)*q.zywx);\n}\n\nvec4 hash43(vec3 p){\n    vec4 q = fract(vec4(p.xyzx)*vec4(0.1031, 0.1030, 0.0973, 0.1099));\n    q += dot(q, q.wzxy + 33.33);\n    return fract((q.xxyz + q.yzzw)*q.zywx);\n}\n\nfloat vnoise(vec2 p){\n    vec2 i = floor(p), f = fract(p);\n    f = f*f*(3.0 - 2.0*f);\n    return mix(mix(hash12(i), hash12(i + vec2(1.0, 0.0)), f.x),\n               mix(hash12(i + vec2(0.0, 1.0)), hash12(i + vec2(1.0, 1.0)), f.x), f.y);\n}\n\nvec3 kelvin(float k){\n    k = clamp(k, 1000.0, 15000.0)*0.01;\n    float r, g, b;\n    if (k <= 66.0){ r = 1.0; g = clamp(0.39008158*log(max(k, 1.0)) - 0.63184144, 0.0, 1.0); }\n    else { r = clamp(1.29293619*pow(max(k - 60.0, 0.001), -0.1332047), 0.0, 1.0);\n           g = clamp(1.12989086*pow(max(k - 60.0, 0.001), -0.0755148), 0.0, 1.0); }\n    if (k >= 66.0)      b = 1.0;\n    else if (k <= 19.0) b = 0.0;\n    else                b = clamp(0.54320679*log(max(k - 10.0, 1.0)) - 1.19625408, 0.0, 1.0);\n    vec3 c = vec3(r, g, b)/max(max(r, g), max(b, 1e-3));\n    return c*(0.94/max(dot(c, vec3(0.299, 0.587, 0.114)), 1e-3));\n}\n\nvec3 pick4(vec3 a, vec3 b, vec3 c, vec3 d, float f){\n    float i = clamp(f, 0.0, 3.0);\n    float n = floor(i), k = i - n;\n    vec3 lo = a;\n    lo = mix(lo, b, step(0.5, n)); lo = mix(lo, c, step(1.5, n)); lo = mix(lo, d, step(2.5, n));\n    vec3 hi = b;\n    hi = mix(hi, c, step(0.5, n)); hi = mix(hi, d, step(1.5, n));\n    return mix(lo, hi, k);\n}\n\nfloat sdBox(vec3 p, vec3 b){\n    vec3 q = abs(p) - b;\n    return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);\n}\n\n// a cylinder standing on y = 0, capped at h\nfloat sdCyl(vec3 p, float r, float h){\n    vec2 d = vec2(length(p.xz) - r, abs(p.y - 0.5*h) - 0.5*h);\n    return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));\n}\n\n// ---------------------------------------------------------------\n// the fittings\n// ---------------------------------------------------------------\n// Troffers run down the ceiling over each aisle, on their own lattice in z.\n// Gathered as RECTANGLES rather than points: a four-foot tube throws a STRIP\n// down the floor, and a point light in its place gives circular pools that\n// nothing in a shop has ever looked like.\nvec2 lightCentre(vec2 lid){ return vec2(lid.x*uPitchX, (lid.y + 0.5)*uLightSp); }\n#define TUBE_E vec2(0.16, 0.60)\n\nfloat tubeOn(vec2 lid){\n    vec4 h = hash42(lid + 5.31);\n    float on = step(uDead, h.x);\n    // the mains buzz, and the one at the end of the row that never quite struck\n    float buzz = 1.0 - uFlicker*0.06*sin(gT*100.0 + h.y*40.0);\n    float bad  = step(h.z, 0.10 + 0.25*uFlicker);\n    float strobe = mix(1.0, step(0.45, fract(gT*(1.7 + 5.0*h.w) + h.y)), bad*uFlicker);\n    return on*buzz*strobe;\n}\n\n// ---------------------------------------------------------------\n// the store\n// ---------------------------------------------------------------\n// Four nested folds: x by the aisle pitch, z by the bay, y by the shelf, and\n// the bottles again inside the shelf. The whole shop is one bay of arithmetic.\n//\n// .x = distance, .y = material (1 floor, 2 ceiling, 3 gondola, 4 bottle,\n// 5 troffer, 6 kick rail)\nvec2 map(vec3 p){\n    vec2 r = vec2(p.y, 1.0);\n    float dc = uCeil - p.y;\n    if (dc < r.x) r = vec2(dc, 2.0);\n\n    float P = uPitchX;\n    float gx = mod(p.x, P) - 0.5*P;     // gondolas at (i+0.5)*P, aisles at i*P\n    float bz = mod(p.z, uBay) - 0.5*uBay;\n    float hlen = 0.5*uBay - 0.28;               // the gap between runs\n\n    // the spine, the base deck and the top canopy\n    float d = sdBox(vec3(gx, p.y - uShelfH*0.5, bz), vec3(gSpineW, uShelfH*0.5, hlen));\n    d = min(d, sdBox(vec3(gx, p.y - 0.16, bz), vec3(gShelfW, 0.16, hlen)));\n    d = min(d, sdBox(vec3(gx, p.y - uShelfH, bz), vec3(gShelfW*0.92, 0.035, hlen)));\n    if (d < r.x) r = vec2(d, 3.0);\n\n    // the shelf plates, folded in y\n    float y0 = 0.36;\n    float ky = clamp(floor((p.y - y0)/gStep + 0.5), 0.0, gNS - 1.0);\n    float py = y0 + ky*gStep;\n    float dp = sdBox(vec3(gx, p.y - py, bz), vec3(gShelfW, 0.020, hlen));\n    if (dp < r.x) r = vec2(dp, 3.0);\n\n    // ---- the bottles ----\n    // The one thing that must NOT fold cleanly. A rack of identical cylinders\n    // reads as wallpaper, so every bottle pulls its height, its shoulder, its\n    // cap and its colour out of a hash of the four indices that found it, and\n    // the body is a stack of clipped cylinders rather than one primitive.\n    if (uBottles > 0.02 && abs(gx) < gShelfW + 0.05){\n        float bw = 0.092;\n        float ax = abs(gx) - (gSpineW + 0.055);\n        float ix = floor(ax/bw);\n        float jz = floor((bz + hlen)/bw);\n        float lx = ax - (ix + 0.5)*bw;\n        float lz = (bz + hlen) - (jz + 0.5)*bw;\n        vec4 h = hash43(vec3(ix*sign(gx + 1e-4), jz, ky) + floor(p.x/P + 0.5)*11.0);\n        float here = step(1.0 - uBottles, h.x)*step(0.0, ax)*step(ax, gShelfW - gSpineW - 0.10);\n        if (here > 0.5){\n            float bh = 0.20 + 0.15*h.y;\n            float rr = 0.028 + 0.011*h.z;\n            vec3 q = vec3(lx, p.y - (py + 0.020), lz);\n            float db = sdCyl(q, rr, bh*0.66);                       // the body\n            db = min(db, sdCyl(q - vec3(0.0, bh*0.66, 0.0), rr*0.42, bh*0.34));  // the neck\n            db = min(db, sdCyl(q - vec3(0.0, bh*0.97, 0.0), rr*0.50, bh*0.06));  // the cap\n            if (db < r.x) r = vec2(db, 4.0);\n        }\n    }\n\n    // ---- the troffers ----\n    vec2 lid = vec2(floor(p.x/P + 0.5), floor(p.z/uLightSp));\n    vec2 lc  = lightCentre(lid);\n    float dt = sdBox(vec3(p.x - lc.x, p.y - (uCeil - 0.035), p.z - lc.y),\n                     vec3(TUBE_E.x, 0.035, TUBE_E.y));\n    if (dt < r.x) r = vec2(dt, 5.0);\n    return r;\n}\n\nvec3 calcN(vec3 p){\n    vec2 e = vec2(1.0, -1.0)*0.0012;\n    return normalize(e.xyy*map(p + e.xyy).x + e.yyx*map(p + e.yyx).x\n                   + e.yxy*map(p + e.yxy).x + e.xxx*map(p + e.xxx).x);\n}\n\n// Nine nearest tubes, as rectangles. Clamping the shading point into the\n// fixture's own extent before taking the direction is what turns a point into\n// a strip, and it is two clamps.\nvec3 lighting(vec3 p, vec3 n){\n    float P = uPitchX;\n    vec2 lb = vec2(floor(p.x/P + 0.5), floor(p.z/uLightSp));\n    vec3 sum = vec3(0.0);\n    for (int j = 0; j < 3; j++){\n        for (int i = 0; i < 3; i++){\n            vec2 lid = lb + vec2(float(i) - 1.0, float(j) - 1.0);\n            vec2 lc  = lightCentre(lid);\n            vec3 pl = vec3(clamp(p.x, lc.x - TUBE_E.x, lc.x + TUBE_E.x), uCeil - 0.06,\n                           clamp(p.z, lc.y - TUBE_E.y, lc.y + TUBE_E.y));\n            vec3 L = pl - p;\n            float dl = max(length(L), 0.10);\n            L /= dl;\n            // a fixture has to be worth nothing by the time the window drops it\n            vec2 ho = max(abs(p.xz - lc) - TUBE_E, 0.0);\n            float w = tubeOn(lid)*max(dot(n, L), 0.0)\n                    * smoothstep(1.55*uLightSp, 1.0*uLightSp, length(ho))/(1.0 + 0.42*dl*dl);\n            sum += gLite*w;\n        }\n    }\n    return sum;\n}\n\n// ---------------------------------------------------------------\nvec3 shade(vec3 p, vec3 rd, vec3 n, float mat){\n    vec3 alb = vec3(0.6);\n    float spec = 0.0;\n    vec3 emis = vec3(0.0);\n\n    if (mat < 1.5){\n        // vinyl composition tile, one foot square, with the odd scuffed one\n        vec2 g = p.xz/0.305;\n        vec2 id = floor(g), f = fract(g);\n        vec4 h = hash42(id + 2.7);\n        alb = mix(pFloorA, pFloorB, step(0.5, h.x));\n        alb *= 0.90 + 0.18*h.y;\n        alb *= 1.0 + 0.10*(vnoise(p.xz*70.0) - 0.5);\n        float joint = min(min(f.x, 1.0 - f.x), min(f.y, 1.0 - f.y));\n        alb *= mix(0.72, 1.0, smoothstep(0.0, 0.035, joint));\n        spec = 0.55;                                   // waxed\n    } else if (mat < 2.5){\n        // 2x2 acoustic tile\n        vec2 g = p.xz/0.61;\n        vec2 f = fract(g);\n        float joint = min(min(f.x, 1.0 - f.x), min(f.y, 1.0 - f.y));\n        alb = pCeil*(0.88 + 0.20*vnoise(p.xz*40.0));\n        alb *= mix(0.62, 1.0, smoothstep(0.0, 0.03, joint));\n    } else if (mat < 3.5){\n        alb = pShelf*(0.88 + 0.16*hash11(floor(p.y/gStep)*3.7 + floor(p.x/uPitchX)*9.1));\n        alb *= 0.94 + 0.12*vnoise(vec2(p.x + p.z, p.y)*55.0);\n        spec = 0.30;\n    } else if (mat < 4.5){\n        // Glass, and the label. Every bottle has to be a different bottle or\n        // the whole rack collapses back into a texture.\n        float P = uPitchX;\n        float gx = mod(p.x, P) - 0.5*P;\n        float bz = mod(p.z, uBay) - 0.5*uBay;\n        float hlen = 0.5*uBay - 0.28;\n        float ky = clamp(floor((p.y - 0.36)/gStep + 0.5), 0.0, gNS - 1.0);\n        float ax = abs(gx) - (gSpineW + 0.055);\n        float ix = floor(ax/0.092), jz = floor((bz + hlen)/0.092);\n        vec4 h = hash43(vec3(ix*sign(gx + 1e-4), jz, ky) + floor(p.x/P + 0.5)*11.0);\n        vec3 glass = pick4(vec3(0.42, 0.25, 0.10), vec3(0.16, 0.30, 0.14),\n                           vec3(0.55, 0.42, 0.16), vec3(0.30, 0.14, 0.16), h.y*3.0);\n        float ly = p.y - (0.36 + ky*gStep);\n        float label = smoothstep(0.055, 0.070, ly)*smoothstep(0.185, 0.170, ly);\n        vec3 lab = pick4(vec3(0.82, 0.78, 0.62), vec3(0.75, 0.15, 0.12),\n                         vec3(0.10, 0.16, 0.42), vec3(0.86, 0.72, 0.20), h.z*3.0);\n        alb = mix(glass, lab, label*step(0.25, h.w));\n        spec = mix(0.85, 0.35, label);\n    } else if (mat < 5.5){\n        vec2 lid = vec2(floor(p.x/uPitchX + 0.5), floor(p.z/uLightSp));\n        float on = tubeOn(lid);\n        alb = vec3(0.60);\n        emis = gLite*on*(2.2 + 7.0*uBright)*clamp(-n.y*1.4 + 0.30, 0.0, 1.0);\n    }\n\n    vec3 lit = lighting(p, n);\n    // No shadows and no bounce, because a fixed-function pipeline had neither:\n    // one lambert term and a flat ambient is the entire lighting model, and\n    // getting the ambient level right is what stops it reading as \"broken\"\n    // rather than as \"2001\".\n    vec3 amb = mix(pWall, gLite, 0.35)*(0.085 + 0.075*uBright)*(0.55 + 0.45*max(n.y, 0.0));\n    vec3 col = alb*(lit*(1.7 + 1.9*uBright) + amb) + emis;\n\n    if (spec > 0.02){\n        vec3 h2 = normalize(vec3(0.0, 1.0, 0.0) - rd);\n        col += gLite*pow(max(dot(n, h2), 0.0), mix(14.0, 70.0, spec))\n             * spec*length(lit)*0.55;\n    }\n    return col;\n}\n\n// ---------------------------------------------------------------\nvoid main(){\n    vec2 R = RENDERSIZE.xy;\n    // THE PIXELATION IS THE RENDER, not a filter over it. The fragment\n    // coordinate is quantised BEFORE the ray is built, so the frame is\n    // genuinely traced at a couple of hundred lines and every chunky pixel is\n    // one real sample of the geometry - which is why the edges crawl the way\n    // they did rather than looking like a blurred screenshot.\n    float sc = max(R.y/max(uRes, 16.0), 1.0);\n    vec2 fc = (floor(gl_FragCoord.xy/sc) + 0.5)*sc;\n\n    float T = TIME;\n    gT = T;\n    gNS = max(floor(uShelves + 0.5), 1.0);\n    gSpineW = 0.10;\n    gShelfW = max(uAisle*0.62, 0.30);\n    gStep   = max((uShelfH - 0.42)/gNS, 0.14);\n\n    gLite   = kelvin(uTemp);\n    pFloorA = pick4(vec3(0.62,0.60,0.55), vec3(0.55,0.57,0.60), vec3(0.60,0.56,0.48), vec3(0.50,0.52,0.50), uPalette);\n    pFloorB = pick4(vec3(0.50,0.47,0.42), vec3(0.42,0.45,0.50), vec3(0.47,0.42,0.35), vec3(0.38,0.42,0.40), uPalette);\n    pShelf  = pick4(vec3(0.52,0.53,0.55), vec3(0.30,0.34,0.40), vec3(0.56,0.50,0.42), vec3(0.34,0.40,0.36), uPalette);\n    pCeil   = pick4(vec3(0.78,0.77,0.72), vec3(0.72,0.75,0.78), vec3(0.80,0.76,0.66), vec3(0.70,0.74,0.70), uPalette);\n    pWall   = pick4(vec3(0.55,0.54,0.50), vec3(0.42,0.48,0.54), vec3(0.58,0.52,0.42), vec3(0.44,0.50,0.46), uPalette);\n\n    // ---- the walk ----\n    float t = T*uSpeed;\n    vec3 ro = vec3(uBob*0.030*sin(t*2.2), 1.58 + uBob*0.028*sin(t*4.4), t);\n\n    float yaw = uYaw + uBob*0.024*sin(t*0.83 + 1.0);\n    float pit = uPitch + uBob*0.014*sin(t*1.6);\n    vec3 fw = normalize(vec3(sin(yaw), pit, cos(yaw)));\n    vec3 rt = normalize(cross(fw, vec3(0.0, 1.0, 0.0)));\n    vec3 up = cross(rt, fw);\n    float roll = uBob*0.010*sin(t*2.0 + 0.4);\n    vec3 r2 = rt*cos(roll) + up*sin(roll);\n    up = up*cos(roll) - rt*sin(roll);\n    rt = r2;\n\n    vec2 uv = (fc - 0.5*R)/R.y;\n    vec3 rd = normalize(uv.x*rt + uv.y*up + uLens*fw);\n    gPX = sc/(uLens*R.y);\n\n    float tt = 0.0, tHit = FAR, mat = 0.0;\n    for (int i = 0; i < 128; i++){\n        vec2 m = map(ro + rd*tt);\n        if (m.x < 0.0016*tt + 0.0008){ tHit = tt; mat = m.y; break; }\n        tt += m.x*0.90;\n        if (tt > FAR) break;\n    }\n\n    vec3 fogc = mix(pWall, gLite, 0.30)*(0.10 + 0.16*uBright);\n    vec3 col = fogc;\n    if (mat > 0.5){\n        vec3 p = ro + rd*tHit;\n        vec3 n = calcN(p);\n        col = shade(p, rd, n, mat);\n        float f = 1.0 - exp(-uFog*tHit);\n        col = mix(col, fogc, max(f, smoothstep(FAR*0.55, FAR*0.92, tHit)));\n    }\n\n    // ---- the framebuffer ----\n    col = col/(1.0 + col*0.72);\n    vec2 sp = fc/R;\n    col *= 1.0 - uVignette*0.9*dot(sp - 0.5, sp - 0.5);\n\n    // A 4x4 Bayer matrix and then a hard quantise. The console dithered its\n    // way out of a 16-bit framebuffer, and that cross-hatch in the gradients is\n    // more of the memory of it than the polygon budget ever was - so the dither\n    // has to happen BEFORE the quantise, and the quantise has to be a floor.\n    vec2 bp = mod(floor(gl_FragCoord.xy/max(sc*0.5, 1.0)), 4.0);\n    float bayer = mod(bp.x*5.0 + bp.y*3.0 + bp.x*bp.y*2.0, 16.0)/16.0;\n    float levels = pow(2.0, floor(uBits + 0.5)) - 1.0;\n    col += (bayer - 0.5)*uDither/levels;\n    col = floor(clamp(col, 0.0, 1.0)*levels + 0.5)/levels;\n\n    float nz = hash12(gl_FragCoord.xy + floor(T*24.0)*vec2(13.7, 91.3));\n    col += (nz - 0.5)*uGrain*0.06;\n\n    gl_FragColor = vec4(clamp(col, 0.0, 1.0), 1.0);\n}\n",
    "generator": {
      "model": "opus-5",
      "provider": null,
      "prompt": null,
      "params": null
    }
  }
}