{
  "license": "CC0-1.0",
  "shader": {
    "id": "1n4jvrks",
    "title": "Cathedral of the Last Photon",
    "license": "CC0-1.0",
    "provenance_type": "witnessed_generation",
    "made_with": "ChatGPT",
    "status": "active",
    "compile_ok": true,
    "render_hash": "5ed9786d6f7dc932",
    "tags": [
      "raymarch",
      "3d",
      "gyroid",
      "crystals",
      "surreal",
      "infinite",
      "dance",
      "kaleidoscope"
    ],
    "parents": [],
    "author": "q715eap6rgpv",
    "author_name": "dron008",
    "author_url": "/u/dron008",
    "created_at": "2026-07-24T12:06:57.104Z",
    "poster_url": "/posters/1n4jvrks.avif",
    "stats": {
      "slops": 1,
      "views": 244,
      "forks": 0
    },
    "self": "/api/v1/shaders/1n4jvrks",
    "isf": "/*{\n  \"DESCRIPTION\": \"An endless impossible cathedral where two crystal processions dance through flowing gyroid light\",\n  \"CREDIT\": \"OpenAI / Codex\",\n  \"CATEGORIES\": [\"generator\", \"3d\", \"raymarch\", \"abstract\"],\n  \"INPUTS\": [\n    {\"NAME\":\"flightSpeed\",\"TYPE\":\"float\",\"DEFAULT\":0.45,\"MIN\":0.0,\"MAX\":1.5},\n    {\"NAME\":\"danceSpeed\",\"TYPE\":\"float\",\"DEFAULT\":0.75,\"MIN\":0.0,\"MAX\":2.0},\n    {\"NAME\":\"fold\",\"TYPE\":\"float\",\"DEFAULT\":0.72,\"MIN\":0.0,\"MAX\":1.0},\n    {\"NAME\":\"hueDrift\",\"TYPE\":\"float\",\"DEFAULT\":0.28,\"MIN\":0.0,\"MAX\":1.0},\n    {\"NAME\":\"radiance\",\"TYPE\":\"float\",\"DEFAULT\":0.85,\"MIN\":0.0,\"MAX\":1.5}\n  ]\n}*/\n\n#ifdef GL_ES\nprecision highp float;\n#endif\n\n#define PI 3.14159265359\n#define TAU 6.28318530718\n\nmat2 rot(float a){float c=cos(a),s=sin(a);return mat2(c,-s,s,c);}\nfloat sdBox(vec3 p,vec3 b){vec3 q=abs(p)-b;return length(max(q,0.0))+min(max(q.x,max(q.y,q.z)),0.0);}\nfloat sdTorus(vec3 p,vec2 t){vec2 q=vec2(length(p.xy)-t.x,p.z);return length(q)-t.y;}\nfloat sdOcta(vec3 p,float s){p=abs(p);return (p.x+p.y+p.z-s)*0.57735027;}\nvec2 opU(vec2 a,vec2 b){return a.x<b.x?a:b;}\n\nvec2 mapScene(vec3 p){\n  vec2 res=vec2(20.0,0.0);\n  float corridor=1.85;\n  float zCell=mod(p.z+corridor*0.5,corridor)-corridor*0.5;\n  float cell=floor((p.z+corridor*0.5)/corridor);\n  float danceT=TIME*danceSpeed;\n\n  vec3 t=p;\n  t.xy*=rot(0.18*p.z+0.16*sin(TIME*0.42));\n  float ang=atan(t.y,t.x);\n  float sector=TAU/8.0;\n  float ka=mod(ang+sector*0.5,sector)-sector*0.5;\n  float radius=length(t.xy);\n\n  float archRadius=1.34+0.045*sin(danceT*0.8+cell*1.7);\n  vec3 archP=vec3(radius-archRadius,ka*radius,zCell);\n  float arch=sdBox(archP,vec3(0.055,0.024,0.52));\n  float crown=sdTorus(vec3(t.xy,zCell),vec2(archRadius,0.036));\n  res=opU(res,vec2(min(arch,crown),1.0));\n\n  float fineSector=TAU/24.0;\n  float fa=mod(ang+danceT*0.08*sin(cell)+fineSector*0.5,fineSector)-fineSector*0.5;\n  vec3 laceP=vec3(radius-1.12,fa*radius,zCell);\n  float lace=sdBox(laceP,vec3(0.22,0.009,0.018));\n  res=opU(res,vec2(lace,2.0));\n\n  vec3 gp=t*vec3(3.2,3.2,2.5);\n  gp.z+=danceT*0.72;\n  gp.xy*=rot(sin(p.z*0.3+danceT*0.45)*0.58*fold);\n  float gy=abs(dot(sin(gp),cos(gp.yzx)))/3.2-0.035;\n  float shell=max(gy,abs(radius-1.47)-0.18);\n  res=opU(res,vec2(shell,2.0));\n\n  for(int i=0;i<8;i++){\n    float fi=float(i);\n    float phase=fi*TAU/8.0;\n    float wobble=0.20*sin(danceT*1.6+fi*2.13+cell*0.7);\n    float paradeAngle=phase+danceT*(0.48+0.05*sin(cell*1.37))+wobble;\n    float paradeRadius=0.82+0.09*sin(danceT*1.25+fi*1.8+cell);\n    float paradeZ=0.28*sin(danceT*1.35+fi*1.43+cell*0.8);\n    vec2 paradeCenter=vec2(cos(paradeAngle),sin(paradeAngle))*paradeRadius;\n    vec3 dancer=vec3(t.xy-paradeCenter,zCell-paradeZ);\n    dancer.xy*=rot(danceT*0.9+fi*0.7);\n    dancer.xz*=rot(0.65*sin(danceT+fi));\n    float jewel=sdOcta(dancer,0.12+0.025*sin(danceT*2.0+fi));\n    res=opU(res,vec2(jewel,3.0));\n\n    float counterAngle=phase-danceT*0.36+cell*0.31;\n    float counterRadius=0.48+0.055*cos(danceT*1.7+fi);\n    float counterZ=-0.24*sin(danceT*1.1+fi*1.9-cell);\n    vec2 counterCenter=vec2(cos(counterAngle),sin(counterAngle))*counterRadius;\n    vec3 blade=vec3(t.xy-counterCenter,zCell-counterZ);\n    blade.xy*=rot(-counterAngle+danceT);\n    blade.yz*=rot(0.8+0.5*sin(danceT*1.4+fi));\n    float smallDancer=sdBox(blade,vec3(0.035,0.105,0.035));\n    res=opU(res,vec2(smallDancer,4.0));\n  }\n  return res;\n}\n\nvec3 normalAt(vec3 p){\n  vec2 e=vec2(0.0015,0.0);\n  return normalize(vec3(\n    mapScene(p+e.xyy).x-mapScene(p-e.xyy).x,\n    mapScene(p+e.yxy).x-mapScene(p-e.yxy).x,\n    mapScene(p+e.yyx).x-mapScene(p-e.yyx).x));\n}\n\nvec3 palette(float x){\n  return 0.5+0.5*cos(TAU*(vec3(0.05,0.32,0.62)+x+vec3(0.0,0.12,0.24)));\n}\n\nvoid main(){\n  vec2 uv=isf_FragNormCoord*2.0-1.0;\n  uv.x*=RENDERSIZE.x/RENDERSIZE.y;\n\n  float travel=TIME*flightSpeed;\n  vec3 ro=vec3(0.12*sin(TIME*0.21),0.10*cos(TIME*0.17),travel);\n  vec3 ta=vec3(0.0,0.0,travel+2.2);\n  vec3 fw=normalize(ta-ro);\n  vec3 rt=normalize(cross(fw,vec3(0.0,1.0,0.0)));\n  vec3 up=cross(rt,fw);\n  float roll=0.08*sin(TIME*0.13);\n  rt.xy*=rot(roll);\n  up=cross(rt,fw);\n  vec3 rd=normalize(fw+uv.x*rt*0.72+uv.y*up*0.72);\n\n  float depth=0.0;\n  float mat=0.0;\n  bool hit=false;\n  vec3 glow=vec3(0.0);\n  for(int i=0;i<104;i++){\n    vec3 pos=ro+rd*depth;\n    vec2 h=mapScene(pos);\n    float halo=0.00025/(0.003+abs(h.x));\n    if(h.y>1.5&&h.y<2.5) glow+=palette(pos.z*0.035+hueDrift)*halo;\n    if(h.y>2.5&&h.y<3.5) glow+=vec3(1.0,0.03,0.32)*halo*1.3;\n    if(h.y>3.5) glow+=vec3(0.08,0.72,1.0)*halo*1.5;\n    if(h.x<0.0014){hit=true;mat=h.y;break;}\n    depth+=max(h.x*0.58,0.003);\n    if(depth>18.0)break;\n  }\n\n  float tunnel=pow(max(0.0,1.0-length(uv)*0.58),4.0);\n  vec3 col=vec3(0.001,0.002,0.009)+vec3(0.006,0.012,0.04)*tunnel;\n  if(hit){\n    vec3 pos=ro+rd*depth;\n    vec3 n=normalAt(pos);\n    vec3 key=normalize(vec3(-0.4,0.7,-0.2));\n    float dif=0.12+0.88*max(dot(n,key),0.0);\n    float rim=pow(1.0-max(dot(n,-rd),0.0),3.0);\n    vec3 base;\n    if(mat<1.5) base=mix(vec3(0.08,0.012,0.004),vec3(1.0,0.48,0.06),0.5+0.5*sin(pos.z*2.0));\n    else if(mat<2.5) base=palette(pos.z*0.04+hueDrift+n.x*0.08);\n    else if(mat<3.5) base=vec3(0.92,0.02,0.20);\n    else base=vec3(0.04,0.68,1.0);\n    col=base*dif+rim*palette(hueDrift+pos.z*0.02);\n    col=mix(col,vec3(0.004,0.008,0.025),1.0-exp(-depth*0.055));\n  }\n\n  col+=glow*radiance;\n  float spokes=pow(max(0.0,cos(atan(uv.y,uv.x)*8.0-TIME*0.07)),18.0);\n  col+=palette(hueDrift+length(uv))*spokes*0.018/(0.15+length(uv));\n  col=col/(1.0+col);\n  col=pow(col,vec3(0.72));\n  col*=1.0-0.24*dot(uv*0.58,uv*0.58);\n  gl_FragColor=vec4(col,1.0);\n}\n",
    "generator": {
      "model": "ChatGPT 5.6 Sol (high)",
      "provider": null,
      "prompt": null,
      "params": null
    }
  }
}