{
  "name": "Cyan Crystal Cluster",
  "dimension": "3d",
  "slot": "action_bar",
  "width": 256,
  "height": 128,
  "textBaseline": 128,
  "placement": {
    "x": 0,
    "y": 0
  },
  "shapes": [],
  "texts": [],
  "heads": [],
  "images": [],
  "bars": [],
  "triggers": [],
  "world": {
    "glsl": "// Vectorized analytic clipping of a hexagonal, double-terminated crystal.\nvec2 gemSlabs(vec3 p, vec3 d, float h) {\n    vec3 inv = 1.0/(d+vec3(0.0000001));\n    vec3 mid = -p*inv;\n    vec3 span = h*abs(inv);\n    vec3 lo = mid-span;\n    vec3 hi = mid+span;\n    return vec2(max(max(lo.x,lo.y),lo.z),min(min(hi.x,hi.y),hi.z));\n}\nvec3 gemProject(vec3 p) {\n    return vec3(p.x,0.5*p.x+0.8660254*p.z,-0.5*p.x+0.8660254*p.z);\n}\nvec3 gemFrame(vec3 p, vec3 angles) {\n    p.xy = rpw_rot(angles.x)*p.xy;\n    p.yz = rpw_rot(angles.y)*p.yz;\n    p.xz = rpw_rot(angles.z)*p.xz;\n    return p;\n}\nvec4 object(vec3 ro, vec3 rd, float t0, float t1, float time, vec3 light, inout float depth) {\n    float scale = 1.18;\n    ro /= scale;\n    t0 /= scale;\n    t1 /= scale;\n    float best = t1+1.0;\n    vec3 bp = vec3(0.0);\n    vec3 bd = vec3(0.0);\n    vec3 bAngles = vec3(0.0);\n    vec3 bcore = vec3(0.0);\n    vec4 shape = vec4(0.0);\n    float bthick = 0.0;\n    float bid = 0.0;\n    vec3 aura = vec3(0.0);\n    float auraA = 0.0;\n    float auraDepth = t1;\n    for (int j = 0; j < 7; j++) {\n        float id = float(j);\n        vec3 center = vec3(0.0,0.12,0.0);\n        float radius = 0.172;\n        float body = 0.225;\n        float tip = 0.205;\n        float tilt = -0.10;\n        float lean = 0.04;\n        if (j == 1) { center = vec3(-0.41,-0.10,0.11); radius = 0.112; body = 0.145; tip = 0.143; tilt = -0.40; lean = -0.18; }\n        if (j == 2) { center = vec3(0.405,-0.045,0.09); radius = 0.12; body = 0.165; tip = 0.15; tilt = 0.36; lean = 0.20; }\n        if (j == 3) { center = vec3(-0.27,0.27,-0.29); radius = 0.101; body = 0.14; tip = 0.135; tilt = -0.28; lean = 0.20; }\n        if (j == 4) { center = vec3(0.295,0.22,-0.305); radius = 0.10; body = 0.12; tip = 0.14; tilt = 0.22; lean = 0.35; }\n        if (j == 5) { center = vec3(0.11,-0.405,0.255); radius = 0.085; body = 0.091; tip = 0.117; tilt = 0.24; lean = -0.25; }\n        if (j == 6) { center = vec3(-0.275,-0.36,-0.245); radius = 0.071; body = 0.078; tip = 0.096; tilt = -0.55; lean = 0.20; }\n        center.y += 0.034*sin(time*1.15+id*1.7);\n        center.x += 0.012*sin(time*0.7+id*2.1);\n        tilt += 0.055*sin(time*0.64+id);\n        vec3 angles = vec3(tilt,lean,0.21+id*0.49+time*(0.095+id*0.007));\n        vec3 r = gemFrame(ro-center,angles);\n        vec3 d = gemFrame(rd,angles);\n        float slope = radius/tip;\n        vec3 pr = gemProject(r);\n        vec3 pd = gemProject(d);\n        vec2 interval0 = gemSlabs(pr,pd,radius);\n        vec2 interval1 = gemSlabs(pr+vec3(slope*r.y),pd+vec3(slope*d.y),radius+slope*body);\n        vec2 interval2 = gemSlabs(pr-vec3(slope*r.y),pd-vec3(slope*d.y),radius+slope*body);\n        float nearT = max(max(interval0.x,interval1.x),interval2.x);\n        float farT = min(min(interval0.y,interval1.y),interval2.y);\n        vec3 rs = r/vec3(1.0,2.3,1.0);\n        vec3 ds = d/vec3(1.0,2.3,1.0);\n        float closest = clamp(-dot(rs,ds)/dot(ds,ds),t0,t1);\n        vec3 closestP = rs+ds*closest;\n        float haze = exp(-dot(closestP,closestP)/(radius*radius*1.95))*0.155;\n        aura += vec3(0.01,0.68,1.0)*haze;\n        auraA += haze;\n        if (haze > 0.012) auraDepth = min(auraDepth,closest);\n        if (farT > max(nearT,t0) && nearT < t1) {\n            float hit = nearT >= t0 ? nearT : farT;\n            if (hit < best) {\n                best = hit;\n                bp = r+d*hit;\n                bd = d;\n                bAngles = angles;\n                shape = vec4(radius,body,tip,slope);\n                bthick = max(farT-hit,0.0);\n                bid = id;\n                float coreT = clamp(-dot(r.xz,d.xz)/max(dot(d.xz,d.xz),0.0001),hit,farT);\n                bcore = r+d*coreT;\n            }\n        }\n    }\n    for (int i = 0; i < 7; i++) {\n        float id = float(i);\n        float a = id*2.39996+time*(0.15+0.015*sin(id));\n        float y = 0.53*sin(id*4.7+time*0.32);\n        float radius = 0.55+0.05*sin(id*1.3);\n        vec3 c = vec3(cos(a)*radius,y,sin(a)*radius);\n        float t = clamp(dot(c-ro,rd),t0,t1);\n        if (t < best) {\n            vec3 delta = ro+rd*t-c;\n            float dist2 = dot(delta,delta);\n            float spark = exp(-dist2/0.000045);\n            float halo = exp(-dist2/0.0007)*0.07;\n            aura += vec3(0.3,1.0,1.22)*spark+vec3(0.0,0.52,0.75)*halo;\n            auraA += spark*0.8+halo;\n            if (spark > 0.15) auraDepth = min(auraDepth,t);\n        }\n    }\n    if (best <= t1) {\n        float radius = shape.x;\n        float body = shape.y;\n        float tip = shape.z;\n        float slope = shape.w;\n        float norm = inversesqrt(1.0+slope*slope);\n        float e1 = 100.0;\n        float e2 = 100.0;\n        vec3 bn = vec3(0.0,1.0,0.0);\n        for (int k = 0; k < 3; k++) {\n            float a = float(k)*1.0471975512;\n            vec3 axis = vec3(cos(a),0.0,sin(a));\n            float radial = dot(axis,bp);\n            float top = radial+slope*bp.y;\n            float bottom = radial-slope*bp.y;\n            float s0 = abs(radius-abs(radial));\n            float s1 = abs(radius+slope*body-abs(top))*norm;\n            float s2 = abs(radius+slope*body-abs(bottom))*norm;\n            if (s0 < e1) bn = axis*sign(radial);\n            float old = e1; e1 = min(e1,s0); e2 = min(e2,max(old,s0));\n            if (s1 < e1) bn = vec3(axis.x,slope,axis.z)*norm*sign(top);\n            old = e1; e1 = min(e1,s1); e2 = min(e2,max(old,s1));\n            if (s2 < e1) bn = vec3(axis.x,-slope,axis.z)*norm*sign(bottom);\n            old = e1; e1 = min(e1,s2); e2 = min(e2,max(old,s2));\n        }\n        vec3 key = gemFrame(normalize(vec3(0.4,0.8,0.3)),bAngles);\n        float edge = exp(-e2/(0.0015+radius*0.010));\n        float diffuse = max(dot(bn,key),0.0);\n        float fresnel = pow(1.0-max(dot(bn,-bd),0.0),3.0);\n        float core = exp(-dot(bcore.xz,bcore.xz)/(radius*radius*0.19))*(1.0-smoothstep(body*0.5,body+tip,abs(bcore.y)));\n        float flawNoise = rpw_noise(bp*27.0+vec3(bid*4.0));\n        float fractures = pow(0.5+0.5*sin(bp.y*44.0+bp.x*33.0+bp.z*20.0+flawNoise*8.0+bid),28.0);\n        float innerFace = 0.5+0.5*dot(bn,normalize(vec3(-0.6,0.2,0.75)));\n        vec3 base = mix(vec3(0.005,0.035,0.10),vec3(0.012,0.34,0.40),innerFace);\n        base *= (0.42+0.75*diffuse)*light;\n        vec3 color = base+vec3(0.004,0.17,0.27)*(1.0-exp(-bthick*8.0));\n        color += vec3(0.035,0.80,1.05)*core*(0.59+0.09*sin(time*1.7+bid));\n        color += vec3(0.10,0.65,0.82)*fresnel*0.38;\n        color += vec3(0.055,0.46,0.58)*fractures*(0.14+0.35*core);\n        color += vec3(0.28,1.10,1.29)*edge*0.80;\n        color += vec3(0.72,0.98,1.0)*pow(max(dot(bn,normalize(key-bd)),0.0),85.0)*0.75;\n        depth = best*scale;\n        return vec4(color+aura*0.23,1.0);\n    }\n    float alpha = clamp(auraA,0.0,0.85);\n    if (alpha < 0.002) return vec4(0.0);\n    depth = clamp(auraDepth,t0,t1)*scale;\n    return vec4(aura/max(alpha,0.0001),alpha);\n}",
    "prompt": "a cluster of floating magic crystals, glowing cyan",
    "size": 5,
    "summary": "Seven faceted magic crystals float, slowly turn, and bob independently, glowing cyan from within as tiny sparks drift around them."
  }
}