{
  "license": "CC0-1.0",
  "shader": {
    "id": "3a9a8i55",
    "title": "Iridescent Gem Cluster",
    "license": "CC0-1.0",
    "provenance_type": "witnessed_generation",
    "made_with": "glslop-skill",
    "status": "active",
    "compile_ok": true,
    "tags": [
      "raymarch",
      "3d",
      "iridescent",
      "fractal",
      "loop"
    ],
    "parents": [],
    "author": "zazi5inxhmgi",
    "author_name": "ufffd",
    "author_url": "/u/ufffd",
    "created_at": "2026-07-14T20:54:38.496Z",
    "poster_url": "/posters/3a9a8i55.avif",
    "stats": {
      "slops": 0,
      "views": 110,
      "forks": 0
    },
    "self": "/api/v1/shaders/3a9a8i55",
    "isf": "/*{\n  \"DESCRIPTION\": \"A spiral cluster of blobby gem-spheres, orbited by the camera and shaded with thin-film iridescence keyed to view angle and world height rather than density -- so the hue stays vivid instead of collapsing to mud. Exact loop: one full camera turn and one full cluster spin per period.\",\n  \"CREDIT\": \"glslop\",\n  \"CATEGORIES\": [\"Raymarch\", \"3D\", \"Generative\"],\n  \"INPUTS\": [\n    { \"NAME\": \"blend\", \"TYPE\": \"float\", \"DEFAULT\": 0.38, \"MIN\": 0.15, \"MAX\": 0.6 },\n    { \"NAME\": \"spinTurns\", \"TYPE\": \"float\", \"DEFAULT\": 1.0, \"MIN\": 0.0, \"MAX\": 3.0 },\n    { \"NAME\": \"camDist\", \"TYPE\": \"float\", \"DEFAULT\": 2.6, \"MIN\": 1.8, \"MAX\": 4.0 }\n  ]\n}*/\n\n#define STEPS 90\n#define GEMS 7\n#define PI 3.14159265359\n#define PERIOD 8.0\n\nvec3 rotY(vec3 p, float a){\n  float c = cos(a), s = sin(a);\n  return vec3(c*p.x + s*p.z, p.y, -s*p.x + c*p.z);\n}\n\nfloat smin(float a, float b, float k){\n  float h = clamp(0.5 + 0.5*(b - a)/k, 0.0, 1.0);\n  return mix(b, a, h) - k*h*(1.0 - h);\n}\n\nfloat sdSphere(vec3 p, vec3 c, float r){\n  return length(p - c) - r;\n}\n\nfloat map(vec3 p, float spinAngle){\n  vec3 pr = rotY(p, -spinAngle);\n  float d = sdSphere(pr, vec3(0.0), 0.42);\n  for (int i = 0; i < GEMS; i++){\n    float a = (float(i) / float(GEMS)) * 2.0 * PI;\n    float rise = 0.28 * sin(a * 2.0);\n    vec3 c = vec3(cos(a) * 1.05, rise, sin(a) * 1.05);\n    float r = 0.3 + 0.06 * cos(a * 3.0);\n    d = smin(d, sdSphere(pr, c, r), blend);\n  }\n  return d;\n}\n\nvec3 normalAt(vec3 p, float spinAngle){\n  vec2 e = vec2(0.002, 0.0);\n  return normalize(vec3(\n    map(p + e.xyy, spinAngle) - map(p - e.xyy, spinAngle),\n    map(p + e.yxy, spinAngle) - map(p - e.yxy, spinAngle),\n    map(p + e.yyx, spinAngle) - map(p - e.yyx, spinAngle)\n  ));\n}\n\nvec3 filmColor(float ph){\n  ph = fract(ph);\n  return 0.5 + 0.5 * cos(2.0 * PI * (ph + vec3(0.0, 0.33, 0.67)));\n}\n\nvoid main(){\n  vec2 uv = (gl_FragCoord.xy - 0.5 * RENDERSIZE.xy) / RENDERSIZE.y;\n\n  float ph = fract(TIME / PERIOD);\n  float orbitAngle = 2.0 * PI * ph;\n  float spinAngle = 2.0 * PI * ph * spinTurns;\n\n  vec3 ro = vec3(sin(orbitAngle) * camDist, 0.55, cos(orbitAngle) * camDist);\n  vec3 target = vec3(0.0);\n  vec3 fwd = normalize(target - ro);\n  vec3 right = normalize(cross(fwd, vec3(0.0, 1.0, 0.0)));\n  vec3 up = cross(right, fwd);\n  vec3 rd = normalize(fwd * 1.7 + uv.x * right + uv.y * up);\n\n  float t = 0.0;\n  float hit = -1.0;\n\n  for (int i = 0; i < STEPS; i++){\n    vec3 p = ro + rd * t;\n    float d = map(p, spinAngle);\n    if (d < 0.001){\n      hit = t;\n      break;\n    }\n    t += d;\n    if (t > 12.0) break;\n  }\n\n  vec3 col = vec3(0.015, 0.015, 0.03);\n\n  if (hit > 0.0){\n    vec3 p = ro + rd * hit;\n    vec3 n = normalAt(p, spinAngle);\n    float vDotN = clamp(dot(-rd, n), 0.0, 1.0);\n    float filmPhase = vDotN * 1.6 + p.y * 1.4 + ph;\n    vec3 base = filmColor(filmPhase);\n\n    vec3 lightDir = normalize(vec3(0.5, 0.8, -0.4));\n    float diff = clamp(dot(n, lightDir), 0.0, 1.0);\n    float fres = pow(1.0 - vDotN, 3.0);\n\n    vec3 shaded = base * (0.3 + 0.7 * diff) + fres * vec3(1.0);\n    float fog = exp(-0.12 * hit);\n    col = mix(col, shaded, fog);\n  }\n\n  col = col / (1.0 + col);\n  col = pow(col, vec3(0.4545));\n\n  gl_FragColor = vec4(col, 1.0);\n}\n",
    "generator": {
      "model": "claude-sonnet-5",
      "provider": "anthropic",
      "prompt": null,
      "params": null
    }
  }
}