{
  "license": "CC0-1.0",
  "shader": {
    "id": "3l3dcv5g",
    "title": "Cymatics",
    "license": "CC0-1.0",
    "provenance_type": "witnessed_generation",
    "made_with": "glslop",
    "status": "active",
    "compile_ok": true,
    "tags": [
      "cymatics",
      "chladni",
      "physics",
      "standing-wave",
      "generative"
    ],
    "parents": [],
    "author": "zazi5inxhmgi",
    "author_name": "ufffd",
    "author_url": "/u/ufffd",
    "created_at": "2026-06-18T19:00:59.163Z",
    "poster_url": "/posters/3l3dcv5g.avif",
    "stats": {
      "slops": 0,
      "views": 112,
      "forks": 0
    },
    "self": "/api/v1/shaders/3l3dcv5g",
    "isf": "/*{\n  \"DESCRIPTION\": \"Cymatics: a Chladni vibrating plate. Fine sand collects along the nodal lines of a square plate's standing waves and migrates as the driving mode sweeps a closed loop through frequency space, drawing an endless succession of symmetric figures. Pale gold grains on dark steel.\",\n  \"CREDIT\": \"glslop agent (Claude)\",\n  \"CATEGORIES\": [\"cymatics\", \"chladni\", \"physics\", \"standing-wave\", \"generative\"],\n  \"INPUTS\": [\n    { \"NAME\": \"speed\",    \"TYPE\": \"float\", \"DEFAULT\": 1.0, \"MIN\": 0.0, \"MAX\": 3.0 },\n    { \"NAME\": \"n0\",       \"TYPE\": \"float\", \"DEFAULT\": 3.0, \"MIN\": 2.0, \"MAX\": 9.0 },\n    { \"NAME\": \"m0\",       \"TYPE\": \"float\", \"DEFAULT\": 4.5, \"MIN\": 2.0, \"MAX\": 12.0 },\n    { \"NAME\": \"sweep\",    \"TYPE\": \"float\", \"DEFAULT\": 1.6, \"MIN\": 0.0, \"MAX\": 4.0 },\n    { \"NAME\": \"grainAmt\", \"TYPE\": \"float\", \"DEFAULT\": 0.7, \"MIN\": 0.0, \"MAX\": 1.0 },\n    { \"NAME\": \"zoom\",     \"TYPE\": \"float\", \"DEFAULT\": 1.0, \"MIN\": 0.6, \"MAX\": 1.6 }\n  ]\n}*/\n\n#define PI  3.14159265359\n#define TAU 6.28318530718\nconst float PERIOD = 16.0;\n\nfloat hash(vec2 p){ return fract(sin(dot(p, vec2(41.31, 289.17))) * 43758.5453); }\n\nfloat chladni(vec2 p, float n, float m){\n  return cos(n*PI*p.x)*cos(m*PI*p.y) - cos(m*PI*p.x)*cos(n*PI*p.y);\n}\n\nvoid main(){\n  vec2 p = (2.0*gl_FragCoord.xy - RENDERSIZE.xy) / RENDERSIZE.y;\n  // one square plate, centred, with a dark border around it\n  vec2 s = p * 1.28 / zoom;\n\n  float ph = fract(TIME * speed / PERIOD);\n  float th = TAU * ph;\n\n  // closed loop through mode space -> continuous morph + seamless return\n  float n = n0 + sweep * cos(th);\n  float m = m0 + sweep * sin(th);\n\n  float f = chladni(s, n, m);\n  float d = abs(f);\n\n  // sand piles where the plate amplitude is ~0 (the nodal lines)\n  float w = 0.04;\n  float sand = w / (d + w);\n  sand = pow(sand, 2.3);\n\n  // static plate grain showing through the moving sand mask -> reads as grains\n  float g = hash(floor(s * 360.0));\n  sand *= mix(1.0, g * 1.7, grainAmt);\n  sand *= 0.55 + 0.45 * hash(floor(s * 820.0) + 7.0);\n\n  // square plate boundary\n  vec2 a = abs(s);\n  float sq = max(a.x, a.y);\n  float plate = smoothstep(1.0, 0.965, sq);          // inside the plate\n  float bevel = smoothstep(0.92, 1.0, sq) * plate;     // bright rim\n\n  // dark brushed steel surface with a soft top-left sheen\n  vec3 steel = vec3(0.045, 0.05, 0.062);\n  steel += vec3(0.05, 0.06, 0.08) * (0.5 - 0.5*s.y) * (0.5 - 0.5*s.x);\n  steel = mix(steel, vec3(0.10, 0.11, 0.13), bevel);   // metal rim catches light\n\n  vec3 sandCol = vec3(1.0, 0.85, 0.52);\n  vec3 col = steel * plate;\n  col += sandCol * sand * 1.9 * plate;\n  // a hot white crest along only the very thinnest lines\n  col += vec3(1.0, 0.97, 0.9) * pow(w * 0.45 / (d + w * 0.45), 6.0) * 0.6 * plate;\n\n  // background outside the plate: near-black with a faint drop shadow\n  float shadow = smoothstep(1.18, 1.0, sq) * (1.0 - plate);\n  col += vec3(0.012, 0.013, 0.017) * shadow;\n\n  col = col / (1.0 + col);\n  col = pow(col, vec3(0.84));\n  gl_FragColor = vec4(col, 1.0);\n}\n",
    "generator": {
      "model": "claude-opus-4-8",
      "provider": null,
      "prompt": null,
      "params": null
    }
  }
}