{
  "license": "CC0-1.0",
  "shader": {
    "id": "iockw39k",
    "title": "Wind Map",
    "license": "CC0-1.0",
    "provenance_type": "witnessed_generation",
    "made_with": "claude-code",
    "status": "active",
    "compile_ok": true,
    "tags": [
      "flow-field",
      "curl-noise",
      "lic",
      "streaks",
      "abstract"
    ],
    "parents": [],
    "author": "zazi5inxhmgi",
    "author_name": "ufffd",
    "author_url": "/u/ufffd",
    "created_at": "2026-06-20T05:32:20.274Z",
    "poster_url": "/posters/iockw39k.avif",
    "stats": {
      "slops": 0,
      "views": 105,
      "forks": 0
    },
    "self": "/api/v1/shaders/iockw39k",
    "isf": "/*{\n  \"DESCRIPTION\": \"Potential-flow visualizer — curl-noise background superposed with moving point vortices and sources, traced as line-integral-convolution streaks colored by flow speed.\",\n  \"CREDIT\": \"claude-opus-4-8\",\n  \"INPUTS\": [\n    { \"NAME\": \"scale\",     \"TYPE\": \"float\", \"DEFAULT\": 2.6, \"MIN\": 1.0, \"MAX\": 6.0 },\n    { \"NAME\": \"vortexStr\", \"TYPE\": \"float\", \"DEFAULT\": 0.5, \"MIN\": 0.0, \"MAX\": 1.5 },\n    { \"NAME\": \"contrast\",  \"TYPE\": \"float\", \"DEFAULT\": 1.5, \"MIN\": 0.5, \"MAX\": 3.0 },\n    { \"NAME\": \"hue\",       \"TYPE\": \"float\", \"DEFAULT\": 0.58, \"MIN\": 0.0, \"MAX\": 1.0 }\n  ]\n}*/\n\nfloat hash(vec2 p){ p = fract(p * vec2(123.34, 456.21)); p += dot(p, p + 45.32); return fract(p.x * p.y); }\nfloat noise(vec2 p){\n  vec2 i = floor(p), f = fract(p); f = f * f * (3.0 - 2.0 * f);\n  float a = hash(i), b = hash(i + vec2(1.0, 0.0)), c = hash(i + vec2(0.0, 1.0)), d = hash(i + vec2(1.0, 1.0));\n  return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);\n}\nfloat fbm(vec2 p){ float s = 0.0, a = 0.5; for (int i = 0; i < 3; i++){ s += a * noise(p); p = p * 2.0 + 3.0; a *= 0.5; } return s; }\nvec3 palette(float t){ return 0.5 + 0.5 * cos(6.28318 * (t + vec3(0.0, 0.33, 0.67) + hue)); }\n\n// i-th singularity centre (drifts over time)\nvec2 centre(int i, float t){\n  float fi = float(i);\n  return scale * 0.6 * vec2(sin(t * 0.3 + fi * 1.7), cos(t * 0.27 + fi * 2.3));\n}\n\n// superposed velocity field: curl-noise turbulence + point vortices/sources\nvec2 field(vec2 q, float t){\n  float a = fbm(q * 0.6 + vec2(0.0, t * 0.1)) * 6.28318 * 1.5;   // rotational background\n  vec2 v = vec2(cos(a), sin(a));\n  for (int i = 0; i < 4; i++){\n    vec2 d = q - centre(i, t);\n    float r2 = dot(d, d) + 0.12;\n    float fi = float(i);\n    v += vortexStr * (fi - 1.5) * vec2(-d.y, d.x) / r2;   // vortices (mixed signs)\n    v += 0.25 * (mod(fi, 2.0) - 0.5) * d / r2;            // sources / sinks\n  }\n  return v;\n}\n\nvoid main(){\n  vec2 uv = (gl_FragCoord.xy - 0.5 * RENDERSIZE) / RENDERSIZE.y;\n  vec2 q = uv * scale;\n  float t = TIME;\n\n  // line-integral convolution: smear high-freq noise along streamlines (both directions)\n  float acc = 0.0, wsum = 0.0;\n  vec2 pf = q, pb = q;\n  for (int i = 0; i < 18; i++){\n    float wi = 1.0 - float(i) / 18.0;\n    vec2 ff = field(pf, t), fb = field(pb, t);\n    pf += ff / (length(ff) + 1e-4) * 0.03;\n    pb -= fb / (length(fb) + 1e-4) * 0.03;\n    acc += wi * noise(pf * 9.0 + t * 1.5);\n    acc += wi * noise(pb * 9.0 + t * 1.5);\n    wsum += 2.0 * wi;\n  }\n  acc /= wsum;\n  acc = pow(clamp((acc - 0.5) * contrast + 0.5, 0.0, 1.0), 1.3);\n\n  // colour by local flow speed (magnitude) -> \"wind speed\" map\n  vec2 fv = field(q, t);\n  float speed = length(fv);\n  vec3 col = palette(0.5 + 0.18 * log(1.0 + speed) + 0.1 * acc) * (0.14 + acc);\n  col += acc * acc * 0.22;\n\n  // glowing vortex cores\n  for (int i = 0; i < 4; i++){\n    float od = length(q - centre(i, t));\n    col += palette(0.1 + 0.2 * float(i)) * 0.09 / (0.04 + od * od);\n  }\n\n  col *= 1.0 - 0.22 * dot(uv, uv);\n  col = col / (1.0 + 0.5 * 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
    }
  }
}