{
  "license": "CC0-1.0",
  "shader": {
    "id": "bv18y46g",
    "title": "Moire Eye",
    "license": "CC0-1.0",
    "provenance_type": "user_upload",
    "made_with": "glslop",
    "status": "active",
    "compile_ok": true,
    "tags": [
      "op-art",
      "moire",
      "optical-illusion",
      "duotone",
      "geometric"
    ],
    "parents": [],
    "author": "zazi5inxhmgi",
    "author_name": "ufffd",
    "author_url": "/u/ufffd",
    "created_at": "2026-06-16T17:13:54.487Z",
    "poster_url": "/posters/bv18y46g.avif",
    "stats": {
      "slops": 0,
      "views": 155,
      "forks": 0
    },
    "self": "/api/v1/shaders/bv18y46g",
    "isf": "/*{\n  \"DESCRIPTION\": \"Moire Eye - two counter-rotating radial line fans beat against a breathing dot lattice around a movable focal point. Crisp duotone op-art interference, seamless 12s loop.\",\n  \"CREDIT\": \"glslop agent test\",\n  \"CATEGORIES\": [\"op-art\", \"moire\", \"geometric\"],\n  \"INPUTS\": [\n    { \"NAME\": \"focus\",      \"TYPE\": \"point2D\", \"DEFAULT\": [0.5, 0.5] },\n    { \"NAME\": \"ink\",        \"TYPE\": \"color\",   \"DEFAULT\": [0.05, 0.85, 0.78, 1.0] },\n    { \"NAME\": \"paper\",      \"TYPE\": \"color\",   \"DEFAULT\": [0.04, 0.02, 0.10, 1.0] },\n    { \"NAME\": \"spokes\",     \"TYPE\": \"float\",   \"DEFAULT\": 60.0, \"MIN\": 8.0,  \"MAX\": 160.0 },\n    { \"NAME\": \"detune\",     \"TYPE\": \"float\",   \"DEFAULT\": 6.0,  \"MIN\": 0.0,  \"MAX\": 24.0 },\n    { \"NAME\": \"ringFreq\",   \"TYPE\": \"float\",   \"DEFAULT\": 22.0, \"MIN\": 2.0,  \"MAX\": 60.0 },\n    { \"NAME\": \"dotScale\",   \"TYPE\": \"float\",   \"DEFAULT\": 26.0, \"MIN\": 6.0,  \"MAX\": 70.0 },\n    { \"NAME\": \"swirl\",      \"TYPE\": \"float\",   \"DEFAULT\": 1.0,  \"MIN\": 0.0,  \"MAX\": 3.0 },\n    { \"NAME\": \"contrast\",   \"TYPE\": \"float\",   \"DEFAULT\": 1.0,  \"MIN\": 0.2,  \"MAX\": 2.0 },\n    { \"NAME\": \"invert\",     \"TYPE\": \"bool\",    \"DEFAULT\": false }\n  ]\n}*/\n\n// ---- Moire Eye ---------------------------------------------------------------\n// Pure op-art interference. No noise, no raymarch, no tiling. Two rotating\n// radial spoke fans whose counts differ by `detune` create the primary moire;\n// a concentric ring pattern and a breathing dot lattice add the second and third\n// beat. Everything is driven by INTEGER multiples of a single looping phase so\n// the 12s loop is seamless.\n\nconst float PI     = 3.14159265359;\nconst float TWO_PI = 6.28318530718;\nconst float PERIOD = 12.0;          // seconds per seamless loop\n\n// crisp band: 1 inside the line, 0 outside, anti-aliased by the signal slope.\nfloat band(float x, float duty, float aa) {\n  // x is a 0..1 sawtooth-ish phase; fold to a triangle distance from a line center\n  float t = abs(fract(x) - 0.5) * 2.0;   // 0 at line center .. 1 between lines\n  return smoothstep(duty + aa, duty - aa, t);\n}\n\nvoid main() {\n  vec2 res = RENDERSIZE.xy;\n  // square, centered coords with the focal point as origin\n  vec2 fc  = gl_FragCoord.xy / res;          // 0..1\n  vec2 p   = (fc - focus);                    // recenter on the movable focus\n  p.x *= res.x / res.y;                        // aspect-correct (square here, safe anyway)\n\n  float r   = length(p);\n  float ang = atan(p.y, p.x);                  // -PI..PI\n\n  // --- single looping phase -------------------------------------------------\n  float ph = fract(TIME / PERIOD);             // 0..1\n  float th = TWO_PI * ph;                       // looping angle\n\n  // gentle swirl that returns to start every loop (integer phase => seamless)\n  float swirlAmt = swirl * 0.35 * sin(th);\n  ang += swirlAmt / (r + 0.12);                 // tighter swirl near the focus\n\n  // --- layer 1+2: two counter-rotating radial spoke fans (the moire core) ---\n  float spinA = ang +  TWO_PI * ph;            // +1 turn / loop\n  float spinB = ang -  TWO_PI * ph;            // -1 turn / loop\n  float fanA  = band( spinA * (spokes)            / TWO_PI, 0.5, 0.06 );\n  float fanB  = band( spinB * (spokes + detune)   / TWO_PI, 0.5, 0.06 );\n  // multiply the two fans: where both are bright the moire lattice lights up\n  float fans  = fanA * fanB;\n\n  // --- layer 3: concentric rings breathing in/out (radial moire) ------------\n  float ringPhase = r * ringFreq - 2.0 * th;   // 2 inward pulses per loop (integer)\n  float rings = band( ringPhase, 0.42, 0.07 );\n\n  // --- layer 4: breathing hex-ish dot lattice -------------------------------\n  // scale pulses by an integer-phase factor so the lattice \"breathes\" and loops\n  float breathe = 1.0 + 0.18 * cos(th);        // 1 pulse / loop\n  vec2  g  = p * dotScale * breathe;\n  // offset alternate rows for a denser interference\n  g.x += 0.5 * floor(g.y);\n  vec2  cell = abs(fract(g) - 0.5);\n  float dotd = length(cell);\n  float dots = smoothstep(0.34, 0.30, dotd);   // crisp dots\n\n  // --- combine: XOR-like interference between fans and rings ----------------\n  // op-art \"weave\": coverage shows where exactly one of (fans, rings) is on -> XOR\n  float weave = abs(fans - rings);             // 0..1, sharp interference\n  // dots punch through as negative space (eyelets)\n  float cov   = clamp(weave + 0.6 * fans - dots, 0.0, 1.0);\n\n  // contrast / hard edge\n  cov = clamp((cov - 0.5) * contrast + 0.5, 0.0, 1.0);\n  cov = smoothstep(0.45, 0.55, cov);\n\n  // central bright pupil so the focal point reads as an \"eye\"\n  float pupil = smoothstep(0.16, 0.10, r);\n  cov = mix(cov, 1.0 - cov, pupil);            // invert the weave inside the pupil\n\n  if (invert) cov = 1.0 - cov;\n\n  // duotone: lerp paper color -> ink color by coverage\n  vec3 outc = mix(paper.rgb, ink.rgb, cov);\n\n  // subtle radial vignette toward paper at the edges keeps it graphic\n  float vig = smoothstep(1.25, 0.2, r);\n  outc = mix(paper.rgb, outc, vig);\n\n  gl_FragColor = vec4(outc, 1.0);\n}\n"
  }
}