{
  "license": "CC0-1.0",
  "shader": {
    "id": "vdstz3q9",
    "title": "Mesmer",
    "license": "CC0-1.0",
    "provenance_type": "witnessed_generation",
    "made_with": "Claude",
    "status": "active",
    "compile_ok": true,
    "render_hash": "1904d9197f48d94f",
    "tags": [
      "moire",
      "portal",
      "trippy",
      "black and white",
      "tunnel",
      "hypnotic",
      "spiral",
      "uzumaki"
    ],
    "parents": [],
    "author": "u7y1evhf0znj",
    "author_name": "ksin",
    "author_url": "/u/ksin",
    "created_at": "2026-08-03T12:37:13.331Z",
    "poster_url": "/posters/vdstz3q9.avif",
    "stats": {
      "slops": 0,
      "views": 162,
      "forks": 0
    },
    "self": "/api/v1/shaders/vdstz3q9",
    "isf": "/*{\n  \"DESCRIPTION\": \"A black-and-white op-art engine built to be stared at. Everything is computed in log-polar space, where a straight line becomes a logarithmic spiral and simply scrolling the radius is an endless zoom with no seam to repeat. Four harmonics lie over one another - the spiral itself, concentric rings marching outward, radial wedges, and a pair of gratings set a hair out of alignment so they beat against each other into moire - and the sum is squared up into hard black and white. A crossed sine domain warp drags the whole plane around, so the pattern swims rather than merely turning. Every harmonic knows its own screen-space frequency and fades itself toward grey as it approaches one cycle per pixel, which is what keeps the infinite zoom clean instead of boiling into aliasing at the vanishing point. Twenty-four sliders: speed, zoom rate (negative falls inward), spin, radial tightness and arm count, the four layer amounts, warp, breathing, a hardness dial from pure sine to hard square edge, contrast, invert, vignette and grain, plus four more optical effects — Fraser twisted-cord hatching that makes concentric bands read as one continuous spiral, a cafe-wall row offset that sets straight bands leaning, a roving lens that magnifies whatever it wanders over, and a 45-degree halftone dot screen that rebuilds the tone the way it would come off a press. Four more push it further out: a kaleidoscope fold that mirrors the angle into N sectors and turns the spiral into a mandala, self-similar fractal octaves so every band grows bands of its own all the way down, a turbulent fbm warp that makes the plane boil rather than merely sway, and travelling rings of inverted polarity so the whole image keeps turning itself inside out.\",\n  \"CREDIT\": \"CC0\",\n  \"CATEGORIES\": [\"generator\", \"op-art\", \"black-and-white\", \"hypnotic\", \"spiral\", \"moire\", \"2d\"],\n  \"INPUTS\": [\n    { \"NAME\": \"uSpeed\",    \"TYPE\": \"float\", \"DEFAULT\": 1.00,  \"MIN\": 0.0,  \"MAX\": 3.0 },\n    { \"NAME\": \"uZoom\",     \"TYPE\": \"float\", \"DEFAULT\": 0.55,  \"MIN\": -2.0, \"MAX\": 2.0 },\n    { \"NAME\": \"uSpin\",     \"TYPE\": \"float\", \"DEFAULT\": 0.35,  \"MIN\": -2.0, \"MAX\": 2.0 },\n    { \"NAME\": \"uTight\",    \"TYPE\": \"float\", \"DEFAULT\": 6.00,  \"MIN\": 0.5,  \"MAX\": 14.0 },\n    { \"NAME\": \"uArms\",     \"TYPE\": \"float\", \"DEFAULT\": 5.00,  \"MIN\": 0.0,  \"MAX\": 16.0 },\n    { \"NAME\": \"uSpiral\",   \"TYPE\": \"float\", \"DEFAULT\": 1.00,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uRings\",    \"TYPE\": \"float\", \"DEFAULT\": 0.35,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uWedges\",   \"TYPE\": \"float\", \"DEFAULT\": 0.25,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uMoire\",    \"TYPE\": \"float\", \"DEFAULT\": 0.12,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uWarp\",     \"TYPE\": \"float\", \"DEFAULT\": 0.12,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uPulse\",    \"TYPE\": \"float\", \"DEFAULT\": 0.35,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uSharp\",    \"TYPE\": \"float\", \"DEFAULT\": 0.72,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uContrast\", \"TYPE\": \"float\", \"DEFAULT\": 0.55,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uInvert\",   \"TYPE\": \"float\", \"DEFAULT\": 0.00,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uVignette\", \"TYPE\": \"float\", \"DEFAULT\": 0.40,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uGrain\",    \"TYPE\": \"float\", \"DEFAULT\": 0.12,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uFraser\",   \"TYPE\": \"float\", \"DEFAULT\": 0.35,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uCafe\",     \"TYPE\": \"float\", \"DEFAULT\": 0.00,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uLens\",     \"TYPE\": \"float\", \"DEFAULT\": 0.35,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uHalftone\", \"TYPE\": \"float\", \"DEFAULT\": 0.00,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uKaleido\",  \"TYPE\": \"float\", \"DEFAULT\": 0.00,  \"MIN\": 0.0,  \"MAX\": 16.0 },\n    { \"NAME\": \"uFractal\",  \"TYPE\": \"float\", \"DEFAULT\": 0.45,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uTurb\",     \"TYPE\": \"float\", \"DEFAULT\": 0.35,  \"MIN\": 0.0,  \"MAX\": 1.0 },\n    { \"NAME\": \"uFlip\",     \"TYPE\": \"float\", \"DEFAULT\": 0.40,  \"MIN\": 0.0,  \"MAX\": 1.0 }\n  ]\n}*/\n\n// OCULAR - ISF port of the Shadertoy/WebGL2 version\n// (GLSL ES 1.00: gl_FragColor, TIME/RENDERSIZE).\n\n#define PI 3.14159265359\n\nfloat hash12(vec2 p){\n    p = fract(p * vec2(123.34, 456.21));\n    p += dot(p, p + 45.32);\n    return fract(p.x * p.y);\n}\n\nfloat vnoise2(vec2 p){\n    vec2 i = floor(p), f = fract(p);\n    f = f * f * (3.0 - 2.0 * f);\n    float a = hash12(i);\n    float b = hash12(i + vec2(1.0, 0.0));\n    float c = hash12(i + vec2(0.0, 1.0));\n    float d = hash12(i + vec2(1.0, 1.0));\n    return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);\n}\n\nfloat fbm2(vec2 p){\n    float s = 0.0, a = 0.5;\n    for (int i = 0; i < 4; i++){\n        s += a * vnoise2(p);\n        p *= 2.03;\n        a *= 0.5;\n    }\n    return s;\n}\n\n// Cycles per pixel for a harmonic whose phase gradient has the given\n// magnitude (radians per screen unit). px is screen units per pixel.\nfloat cpp(float gradMag, float px){ return gradMag * px * (0.5 / PI); }\n\n// A wave that squares up as `sharp` rises, but softens back toward a\n// sine — and then toward flat grey — as it approaches Nyquist. This is\n// what keeps the infinite zoom from turning into a boiling mess.\nfloat wave(float phase, float fpp, float sharp){\n    float gain = mix(1.0, 16.0, sharp) / (1.0 + fpp * 30.0);\n    float s = clamp(sin(phase) * gain, -1.0, 1.0);\n    return s * smoothstep(0.62, 0.16, fpp);      // fade out past Nyquist\n}\n\nvoid main(){\n    vec2 fragCoord = gl_FragCoord.xy;\n    vec2  R  = RENDERSIZE;\n    vec2  uv = (fragCoord - 0.5 * R) / R.y;\n    float px = 1.0 / R.y;\n    float t  = TIME * uSpeed;\n\n    // breathing — the whole field swells and contracts\n    float breathe = 1.0 + 0.16 * uPulse * sin(t * 0.63);\n    uv *= breathe;\n    px *= breathe;\n\n    // domain warp: two crossed sine fields dragging the plane around.\n    // This is what turns a static pattern into something that swims.\n    if (uWarp > 0.001){\n        float w = 0.14 * uWarp;\n        uv += w * vec2(sin(uv.y * 4.7 - t * 0.87), cos(uv.x * 4.3 + t * 0.79));\n    }\n\n    // turbulence: fbm dragging the plane around on top of the clean sine warp.\n    // The sine warp is orderly and periodic; this one is not, and that is what\n    // makes the pattern boil rather than merely sway.\n    if (uTurb > 0.001){\n        vec2 q1 = vec2(fbm2(uv * 2.1 + vec2(0.0, t * 0.13)),\n                       fbm2(uv * 2.1 + vec2(5.2, -t * 0.11)));\n        vec2 q2 = vec2(fbm2(uv * 4.7 + q1 * 1.4 - t * 0.07),\n                       fbm2(uv * 4.7 + q1 * 1.4 + vec2(3.1, t * 0.09)));\n        uv += uTurb * 0.30 * (q2 - 0.5);\n    }\n\n    // a roving lens — pulls the plane toward its own centre, which reads as\n    // local magnification wandering across the field\n    if (uLens > 0.001){\n        vec2  lc = vec2(0.34 * sin(t * 0.37), 0.30 * cos(t * 0.29));\n        vec2  d  = uv - lc;\n        float dd = dot(d, d);\n        uv -= d * uLens * 0.55 * exp(-dd * 11.0);\n    }\n\n    float r  = max(length(uv), 1e-4);\n    float lr = log(r) + t * uZoom;              // endless zoom, seam-free\n    float an = atan(uv.y, uv.x) + t * uSpin;    // rotation\n\n    // kaleidoscope — mirror the angle into N sectors. The spiral stops being\n    // a spiral and becomes a mandala that folds in on itself.\n    if (uKaleido > 0.5){\n        float sec = 2.0 * PI / floor(uKaleido);\n        an = abs(mod(an, sec) - sec * 0.5);\n    }\n\n    // ---- ONE binary field, whose phase the other layers ripple ----\n    // Summing several hard square waves and then thresholding does not work:\n    // the sum lands on discrete plateaus and the contrast stage turns those\n    // into blocky cells bounded by ring arcs and wedge rays. Feeding the\n    // layers into the phase instead keeps a single clean edge that undulates.\n    float kR = uTight;                 // radial frequency\n    float kA = uArms * uSpiral;        // angular frequency — 0 gives plain rings\n    float phase = kR * lr + kA * an;\n\n    // radial ripple — the arms pump in and out as it zooms\n    if (uRings > 0.001)\n        phase += uRings * 1.15 * sin(uTight * 1.6 * lr - t * 1.1);\n\n    // angular ripple — scallops the edges of every arm\n    if (uWedges > 0.001)\n        phase += uWedges * 0.85 * sin(uArms * 2.0 * an);\n\n    // moire ripple — two fine gratings beating, dragged through the phase\n    if (uMoire > 0.001){\n        float ga = t * 0.19;\n        float f  = 320.0;\n        float fm = cpp(f, px);\n        float g1 = wave(dot(uv, vec2(cos(ga),        sin(ga)))        * f, fm, 0.0);\n        float g2 = wave(dot(uv, vec2(cos(ga + 0.45), sin(ga + 0.45))) * f, fm, 0.0);\n        phase += uMoire * 2.2 * g1 * g2;\n    }\n\n    // cafe wall — shove alternate radial bands a half-cell round. Straight\n    // concentric bands stop looking concentric and start to lean.\n    if (uCafe > 0.001){\n        float row = floor(uTight * 1.6 * lr);\n        phase += uCafe * 1.6 * (mod(row, 2.0) - 0.5);\n    }\n\n    // Fraser — twisted cord. Fine oblique hatching laid along the bands at 45\n    // degrees in log-polar space. It is what makes a ring of concentric\n    // circles read as one continuous spiral even when it is not.\n    float kF = 9.0;\n    float ampF = uFraser * 1.15;\n    if (uFraser > 0.001)\n        phase += ampF * sin(kF * (an + lr) - t * 0.6);\n\n    // fractal octaves — the same spiral again at two and four times the\n    // frequency, so every band grows bands of its own. Self-similar all the\n    // way down, which pairs with the endless zoom: you never reach a bottom.\n    float base = kR * lr + kA * an;\n    if (uFractal > 0.001){\n        phase += uFractal * 0.75 * sin(2.0 * base - t * 0.5);\n        phase += uFractal * 0.34 * sin(4.0 * base + t * 0.8);\n    }\n\n    // the ripples steepen the phase, so inflate the Nyquist estimate to match.\n    // The cord contributes amplitude x frequency, NOT its raw frequency —\n    // using the latter over-estimates badly and fades the cord to grey.\n    float grad = sqrt(kR * kR + kA * kA) / r;\n    grad += ampF * kF * 1.41 / r;                        // twisted cord\n    // The octaves' worst-case gradient (all derivatives aligned) is ~2.9x the\n    // base, but summing worst cases makes the AA far too eager and washes the\n    // whole mid-field to grey. An RMS-ish half of that tracks reality.\n    grad += uFractal * 1.30 * sqrt(kR * kR + kA * kA) / r;\n    float fpp  = cpp(grad, px) * (1.0 + 1.5 * uRings + 1.2 * uWedges + 1.5 * uCafe);\n    float v = wave(phase, fpp, uSharp);\n\n    // polarity waves — rings of inversion travelling outward, so the image\n    // keeps turning itself inside out. The slider sets how much of each cycle\n    // inverts, NOT how strongly: blending toward -1 would just dim the field\n    // to grey. Inside a band it is always a full flip.\n    if (uFlip > 0.001){\n        float fw  = sin(lr * 2.1 - t * 1.7);\n        float thr = 1.0 - 2.0 * uFlip;\n        v *= 1.0 - 2.0 * smoothstep(thr + 0.05, thr - 0.05, fw);\n    }\n\n    // ---- square it up into black and white ----\n    v = clamp(v * mix(1.0, 5.0, uContrast), -1.0, 1.0);\n    float lum = 0.5 + 0.5 * v;\n\n    // halftone — rebuild the tone out of dots on a 45-degree screen, the way\n    // it would come off a press. This has to read the RAW sine, not the\n    // squared-up field: that one is already saturated to black and white, so\n    // there is no continuous tone left for the dot size to track and you get\n    // ragged edges instead of dots.\n    if (uHalftone > 0.001){\n        float tone = sin(phase) * smoothstep(0.62, 0.16, fpp);\n        float ha = 0.7854;                                  // 45 degrees\n        vec2  hp = vec2(fragCoord.x * cos(ha) - fragCoord.y * sin(ha),\n                        fragCoord.x * sin(ha) + fragCoord.y * cos(ha)) * 0.34;\n        float dot2 = sin(hp.x) * sin(hp.y);                 // the dot lattice\n        float dotted = smoothstep(-0.08, 0.08, tone * 1.15 - dot2 * 0.92);\n        lum = mix(lum, dotted, uHalftone);\n    }\n\n    lum = mix(lum, 1.0 - lum, uInvert);\n\n    // a dark pupil at the vanishing point, so the eye has somewhere to fall\n    lum *= smoothstep(0.0, 0.055, r);\n\n    vec3 col = vec3(lum);\n\n    // vignette\n    vec2 q = fragCoord / R;\n    float vig = pow(16.0 * q.x * q.y * (1.0 - q.x) * (1.0 - q.y), 0.28);\n    col *= mix(1.0, vig, uVignette);\n\n    // grain\n    col += (hash12(fragCoord + fract(TIME) * 311.0) - 0.5) * uGrain * 0.10;\n\n    gl_FragColor = vec4(clamp(col, 0.0, 1.0), 1.0);\n}\n",
    "generator": {
      "model": "Claude-Opus-5",
      "provider": null,
      "prompt": null,
      "params": null
    }
  }
}