{
  "license": "CC0-1.0",
  "shader": {
    "id": "bpdil19r",
    "title": "Orbital",
    "license": "CC0-1.0",
    "provenance_type": "witnessed_generation",
    "made_with": "glslop",
    "status": "active",
    "compile_ok": true,
    "tags": [
      "spherical-harmonics",
      "orbital",
      "iridescent",
      "neon",
      "raymarch"
    ],
    "parents": [],
    "author": "zazi5inxhmgi",
    "author_name": "ufffd",
    "author_url": "/u/ufffd",
    "created_at": "2026-06-18T16:48:38.000Z",
    "poster_url": "/posters/bpdil19r.avif",
    "stats": {
      "slops": 0,
      "views": 111,
      "forks": 0
    },
    "self": "/api/v1/shaders/bpdil19r",
    "isf": "/*{\n  \"DESCRIPTION\": \"Orbital: a glowing surface shaped by real spherical harmonics, like an electron probability cloud. Its petal-lobes morph between harmonic modes and thin neon nodal lines trace every place the wavefunction changes sign (the + and - lobes glow in two colours). Morph and spin are integer-harmonic so it loops seamlessly over 16s. Real-time raymarch.\",\n  \"CREDIT\": \"glslop agent (Claude)\",\n  \"CATEGORIES\": [\"spherical-harmonics\", \"orbital\", \"neon\", \"raymarch\", \"organic\"],\n  \"INPUTS\": [\n    { \"NAME\": \"speed\", \"TYPE\": \"float\", \"DEFAULT\": 1.0,  \"MIN\": 0.0, \"MAX\": 3.0 },\n    { \"NAME\": \"glow\",  \"TYPE\": \"float\", \"DEFAULT\": 1.0,  \"MIN\": 0.3, \"MAX\": 3.0 },\n    { \"NAME\": \"hue\",   \"TYPE\": \"float\", \"DEFAULT\": 0.0,  \"MIN\": 0.0, \"MAX\": 1.0 },\n    { \"NAME\": \"amp\",   \"TYPE\": \"float\", \"DEFAULT\": 0.5,  \"MIN\": 0.2, \"MAX\": 0.85 },\n    { \"NAME\": \"zoom\",  \"TYPE\": \"float\", \"DEFAULT\": 1.0,  \"MIN\": 0.6, \"MAX\": 1.8 }\n  ]\n}*/\n\n#define PI  3.14159265359\n#define TAU 6.28318530718\n\nconst float PERIOD = 16.0;\n\nmat2 rot(float a){ float c = cos(a), s = sin(a); return mat2(c, -s, s, c); }\n\nvec3 pal(float t){\n  return 0.5 + 0.5 * cos(TAU * (t + vec3(0.0, 0.33, 0.66)));\n}\n\n// signed real-spherical-harmonic field on a unit direction; morphs+spins with th\nfloat harm(vec3 n, float th){\n  float ct  = clamp(n.z, -1.0, 1.0);          // cos(theta)\n  float st  = sqrt(max(1.0 - ct * ct, 0.0));  // sin(theta)\n  float phi = atan(n.y, n.x);\n  float wA = cos(th), wB = sin(th);\n  float p4  = pow(st, 4.0) * cos(4.0 * phi + th);     // 4-petal mode\n  float p6  = pow(st, 6.0) * cos(6.0 * phi - th);     // 6-petal mode\n  float pol = (3.0 * ct * ct - 1.0);                  // axial d-mode\n  return wA * p4 + wB * p6 + 0.35 * cos(2.0 * th) * pol;\n}\n\nvoid main(){\n  vec2 uv = (gl_FragCoord.xy - 0.5 * RENDERSIZE.xy) / RENDERSIZE.y;\n\n  float ph = fract(TIME * speed / PERIOD);\n  float th = TAU * ph;\n\n  // camera\n  vec3 ro = vec3(0.0, 0.0, 9.0 / zoom);\n  vec3 ta = vec3(0.0);\n  vec3 ww = normalize(ta - ro);\n  vec3 uu = normalize(cross(vec3(0.0, 1.0, 0.0), ww));\n  vec3 vv = cross(ww, uu);\n  vec3 rd = normalize(uv.x * uu + uv.y * vv + 2.2 * ww);   // longer lens\n\n  // tumble the whole field (full turn -> seamless)\n  mat2 ry = rot(th);\n  mat2 rx = rot(0.5 * sin(th));\n\n  vec3 col = vec3(0.0);\n  float t = 1.0;\n  float hsurf = 0.0;\n  bool hit = false;\n  for (int i = 0; i < 130; i++){\n    vec3 p = ro + rd * t;\n    vec3 q = p;\n    q.xz = ry * q.xz;\n    q.yz = rx * q.yz;\n    vec3 n = normalize(q);\n    float h = harm(n, th);\n    float R = (0.9) + amp * h;\n    float d = (length(q) - R) * 0.5;\n    if (d < 0.0006 * t){ hit = true; hsurf = h; break; }\n    t += d * 0.7;\n    if (t > 12.0) break;\n  }\n\n  if (hit){\n    vec3 p = ro + rd * t;\n    vec3 q = p; q.xz = ry * q.xz; q.yz = rx * q.yz;\n    // 4-tap normal in the rotated frame\n    vec2 e = vec2(1.0, -1.0) * 0.0015;\n    #define MAPQ(P) ((length(P) - (0.9 + amp * harm(normalize(P), th))) * 0.5)\n    vec3 nor = normalize(\n        e.xyy * MAPQ(q + e.xyy) + e.yyx * MAPQ(q + e.yyx)\n      + e.yxy * MAPQ(q + e.yxy) + e.xxx * MAPQ(q + e.xxx));\n    vec3 vd = normalize(q - vec3(0.0));   // outward-ish\n    float fres = pow(1.0 - abs(dot(nor, normalize(ro * 0.0 - rd))), 3.0);\n\n    // two-colour lobes by sign of the wavefunction\n    vec3 cPlus  = pal(hue + ph + 0.0);\n    vec3 cMinus = pal(hue + ph + 0.42);\n    vec3 lobe   = mix(cMinus, cPlus, smoothstep(-0.12, 0.12, hsurf));\n    lobe = mix(vec3(dot(lobe, vec3(0.33))), lobe, 1.35);   // saturate -> jewel\n    float diff  = 0.45 + 0.55 * max(dot(nor, normalize(vec3(0.5, 0.7, 0.6))), 0.0);\n\n    // thin-film iridescence sheen over the body (energy, not plastic)\n    vec3 irid = pal(hue + 0.5 + 1.8 * fres + 0.4 * nor.y);\n\n    // neon nodal lines where the harmonic crosses zero\n    float node = pow(0.020 / (abs(hsurf) + 0.020), 1.5);\n    // lobe interiors glow brighter toward their peak (|wavefunction| large)\n    float core = smoothstep(0.2, 1.1, abs(hsurf));\n\n    col  = lobe * (0.22 + 0.30 * diff);                    // luminous body\n    col += lobe * core * 1.3 * glow;                       // glowing lobe interiors\n    col += irid * (0.35 + 0.8 * core) * 0.6 * glow;        // iridescent sheen\n    col += vec3(1.0, 1.0, 1.0) * node * 1.9 * glow;        // white-hot nodal lines\n    col += mix(lobe, irid, 0.5) * fres * 2.4 * glow;       // iridescent neon rim\n    col *= exp(-0.18 * max(t - 8.0, 0.0));                 // depth fog (object ~8 away)\n  }\n\n  col = col / (1.0 + col);\n  col = pow(col, vec3(0.82));\n  col *= 1.0 - 0.16 * dot(uv, uv);\n\n  gl_FragColor = vec4(col, 1.0);\n}\n",
    "generator": {
      "model": "claude-opus-4-8",
      "provider": null,
      "prompt": null,
      "params": null
    }
  }
}