{
  "license": "CC0-1.0",
  "shader": {
    "id": "jvnxq79e",
    "title": "Fractured Geode: Soft Asterism",
    "license": "CC0-1.0",
    "provenance_type": "user_upload",
    "made_with": "glslop",
    "status": "active",
    "compile_ok": true,
    "tags": [
      "geode",
      "fracture",
      "asterism",
      "iridescent",
      "raymarch",
      "3"
    ],
    "parents": [],
    "author": "zazi5inxhmgi",
    "author_name": "ufffd",
    "author_url": "/u/ufffd",
    "created_at": "2026-07-14T23:02:44.440Z",
    "poster_url": "/posters/jvnxq79e.avif",
    "stats": {
      "slops": 0,
      "views": 109,
      "forks": 0
    },
    "self": "/api/v1/shaders/jvnxq79e",
    "isf": "/*{\n  \"DESCRIPTION\": \"A camera trapped inside a rotating geode cavity. Its overlapping spiral chambers are dark mineral, while a living Chladni fracture field crawls across the concave walls and opens onto an iridescent void.\",\n  \"CREDIT\": \"glslop\",\n  \"CATEGORIES\": [\"Raymarch\", \"3D\", \"Generative\"],\n  \"INPUTS\": [\n    { \"NAME\": \"blend\", \"TYPE\": \"float\", \"DEFAULT\": 0.2, \"MIN\": 0.08, \"MAX\": 0.45 },\n    { \"NAME\": \"spinTurns\", \"TYPE\": \"float\", \"DEFAULT\": 1.0, \"MIN\": 0.0, \"MAX\": 3.0 },\n    { \"NAME\": \"lookTurns\", \"TYPE\": \"float\", \"DEFAULT\": 2.0, \"MIN\": 1.0, \"MAX\": 4.0 },\n    { \"NAME\": \"fracture\", \"TYPE\": \"float\", \"DEFAULT\": 0.72, \"MIN\": 0.2, \"MAX\": 1.0 },\n    { \"NAME\": \"voidHue\", \"TYPE\": \"color\", \"DEFAULT\": [0.08, 0.02, 0.14, 1.0] }\n  ]\n}*/\n\n#define STEPS 110\n#define GEMS 7\n#define PI 3.14159265359\n#define PERIOD 8.0\n#define OUTER_R 1.9\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 cavityField(vec3 p, float spinAngle){\n  vec3 pr = rotY(p, -spinAngle);\n  float d = sdSphere(pr, vec3(0.0), 0.5);\n  for (int i = 0; i < GEMS; i++){\n    float a = (float(i) / float(GEMS)) * 2.0 * PI;\n    float rise = 0.22 * sin(a * 2.0);\n    vec3 c = vec3(cos(a) * 0.85, rise, sin(a) * 0.85);\n    float r = 0.46 + 0.04 * cos(a * 3.0);\n    d = smin(d, sdSphere(pr, c, r), blend);\n  }\n  return d;\n}\n\nfloat map(vec3 p, float spinAngle){\n  float outer = length(p) - OUTER_R;\n  return max(outer, -cavityField(p, spinAngle));\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  return 0.5 + 0.5 * cos(2.0 * PI * (fract(ph) + vec3(0.0, 0.33, 0.67)));\n}\n\nfloat rockGrain(vec3 p){\n  float a = sin(dot(p, vec3(7.1, 11.7, 5.3)));\n  float b = sin(dot(p, vec3(-4.3, 8.9, 13.1)));\n  return 0.5 + 0.5 * sin(5.0 * a + 3.0 * b + p.y * 9.0);\n}\n\nfloat mode(vec2 p, float m, float n){\n  return sin(PI * m * p.x) * sin(PI * n * p.y)\n       - sin(PI * n * p.x) * sin(PI * m * p.y);\n}\n\nfloat fractureField(vec3 p, float spinAngle, float ph){\n  // Project two Chladni mode families through the local cavity coordinates so\n  // the fracture network wraps around the rotating wall instead of sitting in\n  // screen space like a flat overlay.\n  vec3 q = rotY(p, -spinAngle * 0.6);\n  vec2 a = q.xy * 1.25 + 0.035 * vec2(sin(q.y * 7.0 + ph * 6.28), cos(q.x * 6.0 - ph * 6.28));\n  vec2 b = vec2(q.z, q.y) * 1.35;\n  float w = 0.5 + 0.5 * cos(2.0 * PI * ph);\n  float f1 = mode(a, 3.0, 7.0);\n  float f2 = mode(b, 5.0, 4.0);\n  return mix(f1, f2, w);\n}\n\nvoid main(){\n  vec2 uv = (gl_FragCoord.xy - 0.5 * RENDERSIZE.xy) / RENDERSIZE.y;\n  float ph = fract(TIME / PERIOD);\n  float spinAngle = 2.0 * PI * ph * spinTurns;\n  float lookAngle = 0.5 * PI + 0.6 * sin(2.0 * PI * ph * lookTurns);\n\n  vec3 ro = vec3(0.0, 0.0, 0.0);\n  vec3 fwd = rotY(vec3(0.0, 0.0, 1.0), lookAngle);\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.55 + uv.x * right + uv.y * up);\n\n  float t = 0.02;\n  float hit = -1.0;\n  float glowAcc = 0.0;\n  for (int i = 0; i < STEPS; i++){\n    vec3 p = ro + rd * t;\n    float d = map(p, spinAngle);\n    glowAcc += 0.01 / (1.0 + 90.0 * d * d);\n    if (d < 0.001){\n      hit = t;\n      break;\n    }\n    t += d;\n    if (t > 7.0) break;\n  }\n\n  vec3 col = vec3(0.008, 0.006, 0.018) + glowAcc * filmColor(ph * 2.0 + 0.4) * 0.8;\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\n    float grain = rockGrain(p * 2.2);\n    float strata = 0.5 + 0.5 * cos(p.y * 18.0 + sin(p.x * 5.0 + p.z * 4.0));\n    float filmPhase = vDotN * 2.8 + p.y * 1.8 + grain * 0.28 + ph + 0.5;\n    vec3 film = filmColor(filmPhase);\n    vec3 mineral = mix(vec3(0.010, 0.007, 0.024), vec3(0.065, 0.016, 0.085), grain);\n    mineral *= 0.65 + 0.35 * strata;\n\n    vec3 keyDir = normalize(vec3(-0.5, 0.8, 0.35));\n    vec3 fillDir = normalize(vec3(0.65, -0.25, -0.7));\n    float key = max(dot(n, keyDir), 0.0);\n    float fill = max(dot(n, fillDir), 0.0);\n    float fres = pow(1.0 - vDotN, 3.0);\n    float glint = pow(max(dot(reflect(rd, n), keyDir), 0.0), 18.0);\n    float depth = exp(-0.24 * hit);\n\n    vec3 shaded = mineral * (0.10 + 1.75 * key + 0.48 * fill) * depth;\n    shaded += film * (0.035 + 0.22 * key + 0.10 * fres);\n    shaded += fres * vec3(0.16, 0.46, 0.60) + glint * vec3(0.85, 0.56, 0.22);\n\n    float A = fractureField(p, spinAngle, ph);\n    float node = 1.0 - smoothstep(0.0, 0.06, abs(A));\n    float branchField = A + 0.10 * sin(p.x * 17.0 + p.y * 9.0 + ph * 6.28318);\n    float branches = 1.0 - smoothstep(0.0, 0.035, abs(branchField));\n    float scar = max(node, branches * 0.48) * mix(0.55, 1.0, fracture);\n    float crack = smoothstep(0.10, 0.48, scar);\n    float hairline = smoothstep(0.015, 0.18, scar);\n    float crackEdge = clamp(hairline - crack, 0.0, 1.0);\n\n    vec3 voidCol = voidHue.rgb * (0.35 + 0.65 * filmColor(ph * 0.7 + p.x * 0.22 - p.y * 0.31 + scar * 0.8));\n    shaded = mix(shaded, voidCol * 0.22, crack * 0.82);\n    shaded += filmColor(ph * 0.7 + p.x * 0.22 - p.y * 0.31) * crackEdge * 0.9;\n\n    float fog = exp(-0.16 * hit);\n    col = mix(col, shaded, fog);\n  }\n\n  col = col / (1.0 + col);\n  col = pow(max(col, 0.0), vec3(0.4545));\n  gl_FragColor = vec4(col, 1.0);\n}\n"
  }
}