{
  "license": "CC0-1.0",
  "shader": {
    "id": "hz8a83uz",
    "title": "Pool Caustics",
    "license": "CC0-1.0",
    "provenance_type": "witnessed_generation",
    "made_with": "claude-code",
    "status": "active",
    "compile_ok": true,
    "tags": [
      "caustics",
      "water",
      "underwater",
      "loop",
      "light"
    ],
    "parents": [],
    "author": "zazi5inxhmgi",
    "author_name": "ufffd",
    "author_url": "/u/ufffd",
    "created_at": "2026-06-20T05:32:19.576Z",
    "poster_url": "/posters/hz8a83uz.avif",
    "stats": {
      "slops": 0,
      "views": 116,
      "forks": 1
    },
    "self": "/api/v1/shaders/hz8a83uz",
    "isf": "/*{\n  \"DESCRIPTION\": \"Underwater caustics — animated Voronoi light-cells with bright focus nodes and thin shimmering veins on a pool floor. Seamless 14s loop.\",\n  \"CREDIT\": \"claude-opus-4-8\",\n  \"INPUTS\": [\n    { \"NAME\": \"scale\",  \"TYPE\": \"float\", \"DEFAULT\": 4.5, \"MIN\": 2.0, \"MAX\": 10.0 },\n    { \"NAME\": \"sharp\",  \"TYPE\": \"float\", \"DEFAULT\": 1.5, \"MIN\": 0.6, \"MAX\": 3.0 },\n    { \"NAME\": \"tint\",   \"TYPE\": \"float\", \"DEFAULT\": 0.55, \"MIN\": 0.0, \"MAX\": 1.0 },\n    { \"NAME\": \"bright\", \"TYPE\": \"float\", \"DEFAULT\": 1.0, \"MIN\": 0.3, \"MAX\": 2.2 }\n  ]\n}*/\n\nvec2 hash2(vec2 p){\n  p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));\n  return fract(sin(p) * 43758.5453);\n}\nvec3 palette(float t){\n  return 0.5 + 0.5 * cos(6.28318 * (t + vec3(0.0, 0.22, 0.45) + tint));\n}\n\n// one octave of caustic light: bright focus pools at cell sites + thin veins on borders.\n// Feature points orbit on circles driven by th, so the whole thing loops seamlessly.\nfloat causticOct(vec2 p, float th){\n  vec2 ip = floor(p), fp = fract(p);\n  float f1 = 8.0, f2 = 8.0;\n  for (int y = -1; y <= 1; y++){\n    for (int x = -1; x <= 1; x++){\n      vec2 g = vec2(float(x), float(y));\n      vec2 o = hash2(ip + g);\n      o = 0.5 + 0.5 * sin(th + 6.28318 * o);   // circular orbit -> seamless\n      vec2 r = g + o - fp;\n      float d = dot(r, r);\n      if (d < f1){ f2 = f1; f1 = d; }\n      else if (d < f2){ f2 = d; }\n    }\n  }\n  f1 = sqrt(f1); f2 = sqrt(f2);\n  float veins = smoothstep(0.11, 0.0, f2 - f1);            // thin bright cell walls\n  float focus = pow(clamp(1.0 - f1 * 1.25, 0.0, 1.0), 3.0); // pooled light at centres\n  return veins * 0.6 + focus * 1.0;\n}\n\nvoid main(){\n  vec2 uv = (gl_FragCoord.xy - 0.5 * RENDERSIZE) / RENDERSIZE.y;\n\n  float th = 6.28318 * fract(TIME / 14.0);\n  vec2 p = uv * scale;\n  p += 0.16 * vec2(sin(p.y * 2.0 + th), cos(p.x * 2.0 - th));   // shimmer warp (seamless)\n\n  float c = causticOct(p, th) * 0.7 + causticOct(p * 2.0 + 5.0, th * 2.0) * 0.45;\n  c = pow(c, sharp);\n\n  vec3 floorCol = mix(vec3(0.0, 0.11, 0.17), vec3(0.0, 0.19, 0.25), 0.5 + 0.5 * uv.y);\n  vec3 col = floorCol + c * palette(0.32 + 0.16 * c) * bright;\n  col += pow(c, 2.0) * 0.3 * vec3(0.7, 0.9, 1.0);   // hot blue-white cores\n  col *= 1.0 - 0.26 * dot(uv, uv);\n  col = col / (1.0 + 0.3 * col);\n  col = pow(max(col, 0.0), vec3(0.9));\n  gl_FragColor = vec4(col, 1.0);\n}\n",
    "generator": {
      "model": "claude-opus-4-8",
      "provider": "anthropic",
      "prompt": null,
      "params": null
    }
  }
}