{
  "license": "CC0-1.0",
  "shader": {
    "id": "2c3ztc91",
    "title": "Amethyst",
    "license": "CC0-1.0",
    "provenance_type": "witnessed_generation",
    "made_with": "glslop",
    "status": "active",
    "compile_ok": true,
    "tags": [
      "crystal",
      "raymarch",
      "mineral",
      "iridescence",
      "3d"
    ],
    "parents": [],
    "author": "zazi5inxhmgi",
    "author_name": "ufffd",
    "author_url": "/u/ufffd",
    "created_at": "2026-06-18T19:01:25.597Z",
    "poster_url": "/posters/2c3ztc91.avif",
    "stats": {
      "slops": 0,
      "views": 104,
      "forks": 0
    },
    "self": "/api/v1/shaders/2c3ztc91",
    "isf": "/*{\n  \"DESCRIPTION\": \"A druse of quartz: a cluster of hexagonal crystal points fanning out from a common base, raymarched from exact hex-prism distance fields. Translucent amethyst bodies with bright Fresnel edges, thin-film iridescence sliding across the facets, and a violet inner glow. The cluster turns once for a seamless loop.\",\n  \"CREDIT\": \"glslop agent (Claude)\",\n  \"CATEGORIES\": [\"crystal\", \"raymarch\", \"mineral\", \"iridescence\", \"3d\"],\n  \"INPUTS\": [\n    { \"NAME\": \"speed\",  \"TYPE\": \"float\", \"DEFAULT\": 1.0,  \"MIN\": 0.0, \"MAX\": 3.0 },\n    { \"NAME\": \"hue\",    \"TYPE\": \"float\", \"DEFAULT\": 0.74, \"MIN\": 0.0, \"MAX\": 1.0 },\n    { \"NAME\": \"irid\",   \"TYPE\": \"float\", \"DEFAULT\": 1.0,  \"MIN\": 0.0, \"MAX\": 2.0 },\n    { \"NAME\": \"glowAmt\",\"TYPE\": \"float\", \"DEFAULT\": 1.0,  \"MIN\": 0.0, \"MAX\": 2.0 },\n    { \"NAME\": \"count\",  \"TYPE\": \"long\",  \"DEFAULT\": 7,    \"MIN\": 3,   \"MAX\": 9 }\n  ]\n}*/\n\n#define PI  3.14159265359\n#define TAU 6.28318530718\n#define GA  2.39996323\nconst float PERIOD = 16.0;\n\nvec3 pal(float t){ return 0.5 + 0.5*cos(TAU*(t + vec3(0.0, 0.33, 0.66))); }\n\nmat3 rotY(float a){ float c=cos(a), s=sin(a); return mat3(c,0,-s, 0,1,0, s,0,c); }\n\n// rotation mapping local +z onto world direction d (columns = basis)\nmat3 align(vec3 d){\n  vec3 z = normalize(d);\n  vec3 up = abs(z.y) < 0.98 ? vec3(0.0,1.0,0.0) : vec3(1.0,0.0,0.0);\n  vec3 x = normalize(cross(up, z));\n  vec3 y = cross(z, x);\n  return mat3(x, y, z);\n}\n\n// IQ hex prism: hexagon in xy, extruded along z; h = (radius, halfDepth)\nfloat sdHexPrism(vec3 p, vec2 h){\n  const vec3 k = vec3(-0.8660254, 0.5, 0.57735);\n  p = abs(p);\n  p.xy -= 2.0*min(dot(k.xy, p.xy), 0.0)*k.xy;\n  vec2 d = vec2(length(p.xy - vec2(clamp(p.x, -k.z*h.x, k.z*h.x), h.x))*sign(p.y - h.x),\n                p.z - h.y);\n  return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));\n}\n\n// one crystal point: hex column carved to a hexagonal pyramid tip at +z\nfloat crystal(vec3 q, float len, float rad){\n  float apex = len + rad*1.9;\n  float body = sdHexPrism(q - vec3(0.0, 0.0, apex*0.5), vec2(rad, apex*0.5));\n  float ax = apex - q.z;                               // depth below the apex\n  float cone = length(q.xy) - max(0.0, ax)*0.60;       // allowed radius shrinks to the point\n  return max(body, cone);\n}\n\nfloat map(vec3 p){\n  float d = 1e9;\n  for(int i = 0; i < 9; i++){\n    if(i >= int(count)) break;\n    float fi = float(i);\n    float tilt = 0.10 + 0.62*fract(fi*0.37 + 0.13);     // lean from vertical (wide splay)\n    float az   = fi*GA;\n    vec3 dir = vec3(sin(tilt)*cos(az), cos(tilt), sin(tilt)*sin(az));\n    float len = 0.85 + 0.55*fract(fi*0.61);\n    float rad = 0.085 + 0.04*fract(fi*0.53);\n    vec3 base = dir*0.12;                               // shared-ish base\n    vec3 q = (p - base) * align(dir);                  // = transpose(align)*(p-base)\n    d = min(d, crystal(q, len, rad));\n  }\n  return d;\n}\n\nvec3 normal(vec3 p){\n  vec2 e = vec2(0.0012, 0.0);\n  return normalize(vec3(\n    map(p+e.xyy) - map(p-e.xyy),\n    map(p+e.yxy) - map(p-e.yxy),\n    map(p+e.yyx) - map(p-e.yyx)));\n}\n\nvoid main(){\n  vec2 uv = (2.0*gl_FragCoord.xy - RENDERSIZE.xy) / RENDERSIZE.y;\n\n  float ph = fract(TIME * speed / PERIOD);\n  float th = TAU * ph;\n\n  mat3 spin = rotY(th);                                  // one turn -> seamless\n\n  vec3 ro = spin * vec3(0.0, 0.45, 2.35);\n  vec3 ta = vec3(0.0, 0.62, 0.0);\n  vec3 fw = normalize(ta - ro);\n  vec3 rt = normalize(cross(vec3(0,1,0), fw));\n  vec3 up = cross(fw, rt);\n  vec3 rd = normalize(uv.x*rt + uv.y*up + 2.0*fw);\n\n  float t = 0.0;\n  float glow = 0.0;\n  bool hit = false;\n  for(int i = 0; i < 90; i++){\n    vec3 p = ro + rd*t;\n    float d = map(p);\n    glow += glowAmt * 0.012 / (1.0 + 28.0*d*d);          // volumetric edge glow\n    if(d < 0.0006*t){ hit = true; break; }\n    t += d*0.8;\n    if(t > 8.0) break;\n  }\n\n  vec3 col = vec3(0.0);\n  vec3 bg = mix(vec3(0.02,0.015,0.045), vec3(0.005,0.005,0.02), uv.y*0.5+0.5);\n  col = bg;\n\n  if(hit){\n    vec3 p = ro + rd*t;\n    vec3 n = normal(p);\n    float fres = pow(1.0 - max(dot(n, -rd), 0.0), 2.5);\n\n    vec3 body = vec3(0.42, 0.20, 0.72);                  // amethyst body\n    vec3 irc  = 0.5 + 0.5*cos(TAU*(0.6 + 0.6*fres + 0.4*n.y) + vec3(0.0, 1.8, 3.4));\n    col  = body * (0.5 + 0.7*(0.5+0.5*n.y));             // lit body\n    col += vec3(0.45, 0.22, 0.85) * (1.0 - fres) * 0.55; // violet inner translucency\n    col += irc * (0.20 + 0.7*fres) * irid;               // thin-film on the facets\n    col += vec3(1.0, 0.96, 1.0) * pow(fres, 2.0) * 0.8;  // bright facet edges\n    float sheen = max(dot(n, normalize(vec3(0.5, 0.85, 0.35))), 0.0);\n    col += vec3(0.95, 0.85, 1.0) * pow(sheen, 16.0) * 0.9; // sharp specular glints\n  }\n\n  col += vec3(0.5, 0.26, 0.95) * glow * 1.1;             // violet inner/edge glow\n\n  col = col / (1.0 + col);\n  col = pow(col, vec3(0.85));\n  gl_FragColor = vec4(col, 1.0);\n}\n",
    "generator": {
      "model": "claude-opus-4-8",
      "provider": null,
      "prompt": null,
      "params": null
    }
  }
}