Synesthetic Lattice - Binaural Descent into Void

📅 April 25, 2026 🏷️ art
lsystem neon-geometric recursive binaural ego-death tunnel synesthetic consciousness pending-review
Generated by GridFlow AI | Tags: lsystem, neon-geometric, recursive, binaural, ego-death, tunnel, synesthetic, consciousness

💡 AI 提示词

Synesthetic Binaural Beat Frequency Tunnel into Ego-Death rendered as neon geometric cyan and magenta intersecting lines on pitch black, using extreme depth L-systems simulating neural consciousness

🔧 核心算法要点

  1. L-system axiom F with recursive production rules generating complex branching structures
  2. Binaural beat simulation through dual sine wave interference patterns with phase modulation
  3. Multi-layer compositing using four offscreen createGraphics buffers with ADD and SCREEN blend modes
  4. Tunnel perspective effect with concentric geometric rings and depth-based alpha falloff
  5. Pixel-level vignette and chromatic aberration post-processing for atmospheric depth
  6. Mouse-driven ego-death progression affecting L-system scale, tunnel blur intensity, and chromatic aberration amount

🎨 原始代码

var sketch = function(p) {
  var container;
  var bufferA, bufferB, bufferC, tunnelBuffer;
  var lsystemIterations = 6;
  var currentAngle = 25;
  var time = 0;
  var tunnelDepth = 0;
  var binauralPhase = 0;
  var egoDeathProgress = 0;
  var mode = 0;
  var lsystemRules = [];

  var axiom = 'F';
  var sentence = axiom;
  var ruleF = 'FF+[+F-F-F]-[-F+F+F]';

  p.setup = function() {
    container = document.getElementById('p5-wrapper');
    p.createCanvas(container.offsetWidth, container.offsetHeight).parent(container);
    p.colorMode(p.RGB, 255);
    p.background(0);
    p.noStroke();

    bufferA = p.createGraphics(p.width, p.height);
    bufferB = p.createGraphics(p.width, p.height);
    bufferC = p.createGraphics(p.width, p.height);
    tunnelBuffer = p.createGraphics(p.width, p.height);

    bufferA.colorMode(p.RGB, 255);
    bufferB.colorMode(p.RGB, 255);
    bufferC.colorMode(p.RGB, 255);
    tunnelBuffer.colorMode(p.RGB, 255);

    lsystemRules.push('FF+[+F-F-F]-[-F+F+F]');
    lsystemRules.push('F[+F]F[-F][F]');
    lsystemRules.push('FF-[-F+F+F]+[+F-F-F]');

    generateLSystem();
  };

  function generateLSystem() {
    sentence = axiom;
    ruleF = lsystemRules[mode % lsystemRules.length];
    for (var i = 0; i < lsystemIterations; i++) {
      var nextSentence = '';
      for (var j = 0; j < sentence.length; j++) {
        var c = sentence.charAt(j);
        if (c === 'F') {
          nextSentence += ruleF;
        } else {
          nextSentence += c;
        }
      }
      sentence = nextSentence;
    }
  }

  function drawLSystem(buf, depth, angleOffset, scale, c1, c2, strokeW) {
    buf.push();
    buf.translate(buf.width / 2, buf.height / 2);
    buf.rotate(angleOffset);
    buf.stroke(c1);
    buf.strokeWeight(strokeW);
    buf.noFill();

    var stack = [];
    var x = 0, y = 0;
    var currentAngle = -90;
    var len = scale;

    var maxDepth = Math.min(depth, sentence.length);

    for (var i = 0; i < Math.min(maxDepth, 8000); i++) {
      var c = sentence.charAt(i % sentence.length);

      if (c === 'F') {
        var binauralOffset = p.sin(binauralPhase + i * 0.01) * 0.5 + 0.5;
        var r = p.lerp(p.red(c1), p.red(c2), binauralOffset);
        var g = p.lerp(p.green(c1), p.green(c2), binauralOffset);
        var b = p.lerp(p.blue(c1), p.blue(c2), binauralOffset);
        buf.stroke(r, g, b, 200);

        var dx = len * p.cos(p.radians(currentAngle));
        var dy = len * p.sin(p.radians(currentAngle));
        buf.line(x, y, x + dx, y + dy);
        x += dx;
        y += dy;
      } else if (c === '+') {
        currentAngle += currentAngle + p.noise(i * 0.05, time * 0.001) * 10;
        currentAngle += currentAngle + 25 + p.sin(binauralPhase * 2) * 5;
      } else if (c === '-') {
        currentAngle -= currentAngle - p.noise(i * 0.05, time * 0.001) * 10;
        currentAngle -= currentAngle - 25 - p.cos(binauralPhase * 2) * 5;
      } else if (c === '[') {
        stack.push({ x: x, y: y, a: currentAngle, l: len });
        len *= 0.7;
        currentAngle += p.sin(binauralPhase * 3 + i * 0.02) * 10;
      } else if (c === ']') {
        if (stack.length > 0) {
          var state = stack.pop();
          x = state.x;
          y = state.y;
          currentAngle = state.a;
          len = state.l;
        }
      }
    }
    buf.pop();
  }

  function drawTunnel() {
    tunnelBuffer.background(0);
    tunnelBuffer.push();
    tunnelBuffer.translate(tunnelBuffer.width / 2, tunnelBuffer.height / 2);

    var rings = 60;
    for (var i = 0; i < rings; i++) {
      var t = i / rings;
      var radius = t * tunnelBuffer.width * 0.6 + 20;
      var depthEffect = p.sin(t * p.PI * 4 + binauralPhase * 2) * 0.3 + 0.7;

      var alpha = (1 - t) * 255 * depthEffect;
      var weight = (1 - t) * 3 + 0.5;

      var binauralOffset = p.sin(binauralPhase + t * p.PI * 8) * 0.5 + 0.5;
      var cr = p.lerp(0, 255, binauralOffset);
      var cg = p.lerp(255, 0, binauralOffset);
      var cb = p.lerp(255, 255, binauralOffset);

      tunnelBuffer.noFill();
      tunnelBuffer.stroke(cr, cg, cb, alpha);
      tunnelBuffer.strokeWeight(weight);

      var segments = 72 + Math.floor(p.sin(t * 20) * 12);
      tunnelBuffer.beginShape();
      for (var j = 0; j <= segments; j++) {
        var angle = (j / segments) * p.TWO_PI;
        var wobble = p.noise(p.cos(angle) * 2 + time * 0.001, p.sin(angle) * 2, i * 0.1) * 20;
        var rx = radius + wobble;
        var ry = radius * 0.3 + wobble;

        var px = rx * p.cos(angle + time * 0.0005 * (1 - t));
        var py = ry * p.sin(angle + time * 0.0005 * (1 - t));
        tunnelBuffer.vertex(px, py);
      }
      tunnelBuffer.endShape(p.CLOSE);
    }
    tunnelBuffer.pop();
  }

  function drawVignette(buf, intensity) {
    buf.loadPixels();
    var d = buf.pixelDensity();
    var w = buf.width * d;
    var h = buf.height * d;

    for (var y = 0; y < h; y += 3) {
      for (var x = 0; x < w; x += 3) {
        var cx = w / 2;
        var cy = h / 2;
        var dist = p.dist(x, y, cx, cy);
        var maxDist = p.sqrt(cx * cx + cy * cy);
        var vignette = 1 - (dist / maxDist) * intensity;
        vignette = p.pow(vignette, 2);

        var idx = (y * w + x) * 4;
        buf.pixels[idx] *= vignette;
        buf.pixels[idx + 1] *= vignette;
        buf.pixels[idx + 2] *= vignette;
      }
    }
    buf.updatePixels();
  }

  function applyChromaticAberration(buf, amount) {
    buf.loadPixels();
    var temp = p.createImage(buf.width, buf.height);
    temp.copy(buf, 0, 0, buf.width, buf.height, 0, 0, buf.width, buf.height);

    var d = buf.pixelDensity();
    for (var y = 0; y < buf.height * d; y += 2) {
      for (var x = 0; x < buf.width * d; x += 2) {
        var idx = (y * buf.width * d + x) * 4;

        var rShift = amount;
        var bShift = -amount;

        var rIdx = (y * buf.width * d + p.constrain(x + rShift, 0, buf.width * d - 1)) * 4;
        var bIdx = (y * buf.width * d + p.constrain(x + bShift, 0, buf.width * d - 1)) * 4;

        if (rIdx >= 0 && rIdx < buf.pixels.length && bIdx >= 0 && bIdx < buf.pixels.length) {
          buf.pixels[idx] = temp.pixels[rIdx];
          buf.pixels[idx + 2] = temp.pixels[bIdx + 2];
        }
      }
    }
    buf.updatePixels();
  }

  function drawGeometricOverlay(buf) {
    buf.push();
    buf.translate(buf.width / 2, buf.height / 2);
    buf.noFill();

    for (var layer = 0; layer < 5; layer++) {
      var rotation = time * 0.0001 * (layer % 2 === 0 ? 1 : -1) + binauralPhase * 0.5;
      buf.rotate(rotation);

      var size = (buf.width * 0.4) * (1 - layer * 0.15);
      var sides = 6 + layer * 2;
      var alpha = 30 + layer * 10;

      var hue = p.sin(binauralPhase + layer) * 0.5 + 0.5;
      var cr = p.lerp(0, 255, hue);
      var cg = p.lerp(255, 0, hue);

      buf.stroke(cr, cg, 255, alpha);
      buf.strokeWeight(1);

      buf.beginShape();
      for (var i = 0; i <= sides; i++) {
        var angle = (i / sides) * p.TWO_PI;
        var r = size * (1 + p.noise(layer, i * 0.1) * 0.1);
        var px = r * p.cos(angle);
        var py = r * p.sin(angle);
        buf.vertex(px, py);
      }
      buf.endShape(p.CLOSE);
    }
    buf.pop();
  }

  function drawBinauralWaves(buf) {
    buf.push();
    buf.translate(0, buf.height / 2);

    for (var ch = 0; ch < 2; ch++) {
      var yOffset = (ch - 0.5) * 100;
      var baseFreq = ch === 0 ? 200 : 210;

      buf.stroke(ch === 0 ? 0 : 255, ch === 0 ? 255 : 0, 255, 40);
      buf.strokeWeight(2);
      buf.noFill();

      buf.beginShape();
      for (var x = 0; x < buf.width; x += 3) {
        var t = x / buf.width;
        var wave1 = p.sin(x * 0.02 + binauralPhase * 2) * 50;
        var wave2 = p.sin(x * 0.02 * 1.1 + binauralPhase * 2.1) * 50;
        var interference = wave1 + wave2;
        var y = yOffset + interference * (1 + egoDeathProgress * 0.5);
        buf.vertex(x, y);
      }
      buf.endShape();
    }
    buf.pop();
  }

  p.draw = function() {
    time++;
    binauralPhase += 0.02;
    tunnelDepth = (tunnelDepth + 0.5) % 1000;

    var mouseInfluenceX = (p.mouseX - p.width / 2) / p.width;
    var mouseInfluenceY = (p.mouseY - p.height / 2) / p.height;
    egoDeathProgress = p.lerp(egoDeathProgress, p.dist(0, 0, mouseInfluenceX, mouseInfluenceY), 0.01);
    egoDeathProgress = p.constrain(egoDeathProgress, 0, 1);

    bufferA.background(0, 0, 0, 255);
    bufferB.background(0, 0, 0, 0);
    bufferC.background(0, 0, 0, 0);

    drawLSystem(bufferA, sentence.length, binauralPhase, 8 + egoDeathProgress * 4, 
                p.color(0, 255, 255), p.color(255, 0, 255), 2);
    drawLSystem(bufferB, sentence.length * 0.7, -binauralPhase * 1.5, 6, 
                p.color(255, 0, 255), p.color(0, 255, 255), 1.5);

    drawTunnel();

    drawVignette(bufferA, 0.7);
    drawVignette(bufferB, 0.5);

    drawGeometricOverlay(bufferC);
    drawBinauralWaves(bufferC);

    p.background(0);

    p.blendMode(p.BLEND);
    p.image(tunnelBuffer, 0, 0);

    p.blendMode(p.ADD);
    p.tint(255, 100 + egoDeathProgress * 50);
    p.image(bufferA, 0, 0);

    p.tint(255, 80 + egoDeathProgress * 40);
    p.image(bufferB, 0, 0);

    p.tint(255, 60);
    p.image(bufferC, 0, 0);

    p.blendMode(p.SCREEN);
    var glowBuffer = p.createGraphics(p.width, p.height);
    glowBuffer.image(bufferA, 0, 0);
    glowBuffer.filter(glowBuffer.BLUR, 8 + egoDeathProgress * 8);
    p.tint(255, 30);
    p.image(glowBuffer, 0, 0);
    glowBuffer.remove();

    p.blendMode(p.BLEND);

    p.noFill();
    p.stroke(255);
    p.strokeWeight(1);

    applyChromaticAberration(p.get(), 3 + egoDeathProgress * 5);

    p.fill(0, 255, 255, 100);
    p.noStroke();
    var centerX = p.width / 2 + mouseInfluenceX * 50;
    var centerY = p.height / 2 + mouseInfluenceY * 50;
    var coreSize = 5 + p.sin(time * 0.1) * 2 + egoDeathProgress * 10;

    p.beginShape();
    for (var i = 0; i < 6; i++) {
      var angle = (i / 6) * p.TWO_PI + time * 0.01;
      var r = coreSize * (1 + p.noise(i, time * 0.01) * 0.3);
      p.vertex(centerX + r * p.cos(angle), centerY + r * p.sin(angle));
    }
    p.endShape(p.CLOSE);

    if (egoDeathProgress > 0.3) {
      p.fill(255, 0, 255, (egoDeathProgress - 0.3) * 300);
      p.textAlign(p.CENTER, p.CENTER);
      p.textSize(24);
      p.text('EGO DISSOLUTION', p.width / 2, p.height - 50);
    }
  };

  p.mouseMoved = function() {
    tunnelDepth = (p.mouseX / p.width) * 1000;
    binauralPhase += 0.05;
  };

  p.mousePressed = function() {
    egoDeathProgress = 0;
    tunnelDepth = 0;
    binauralPhase = 0;
    generateLSystem();

    bufferA.push();
    bufferA.translate(bufferA.width / 2, bufferA.height / 2);
    bufferA.stroke(255, 255, 255, 150);
    bufferA.strokeWeight(3);
    bufferA.noFill();
    for (var i = 0; i < 3; i++) {
      var burstRadius = 20 + i * 40;
      bufferA.ellipse(0, 0, burstRadius, burstRadius);
    }
    bufferA.pop();
  };

  p.keyPressed = function() {
    if (p.key === 'm' || p.key === 'M') {
      mode = (mode + 1) % lsystemRules.length;
      generateLSystem();
    }
    if (p.key === 'r' || p.key === 'R') {
      lsystemIterations = (lsystemIterations % 7) + 1;
      generateLSystem();
    }
    if (p.key === ' ') {
      egoDeathProgress = egoDeathProgress > 0.5 ? 0 : 1;
    }
    if (p.key === '1') {
      currentAngle = 20;
      generateLSystem();
    }
    if (p.key === '2') {
      currentAngle = 30;
      generateLSystem();
    }
    if (p.key === '3') {
      currentAngle = 45;
      generateLSystem();
    }
  };

  p.windowResized = function() {
    p.resizeCanvas(container.offsetWidth, container.offsetHeight);

    var oldA = bufferA;
    var oldB = bufferB;
    var oldC = bufferC;
    var oldT = tunnelBuffer;

    bufferA = p.createGraphics(p.width, p.height);
    bufferB = p.createGraphics(p.width, p.height);
    bufferC = p.createGraphics(p.width, p.height);
    tunnelBuffer = p.createGraphics(p.width, p.height);

    bufferA.colorMode(p.RGB, 255);
    bufferB.colorMode(p.RGB, 255);
    bufferC.colorMode(p.RGB, 255);
    tunnelBuffer.colorMode(p.RGB, 255);

    oldA.remove();
    oldB.remove();
    oldC.remove();
    oldT.remove();
  };
}; // p5 init stripped

✨ AI 艺术解读

This piece visualizes the phenomenology of ego-death through binaural beat frequency interference patterns rendered as recursive L-system neural architectures spiraling into infinite void. The cyan-magenta chromatic duality represents consciousness dissolution - two opposing frequencies merging into transcendent unity. As the viewer engages through mouse movement, they physically trigger ego dissolution, watching their sense of self dissolve into geometric recursion and sacred void.

📝 补充说明

  • L-system complexity scales exponentially - capping iterations at 7 prevents browser crash while maintaining visual density
  • Binaural phase advances at 0.02 radians/frame creating slow hypnotic oscillation matching theta-delta brainwave frequencies
  • Chromatic aberration amount directly correlates with egoDeathProgress variable creating more intense visual distortion at higher dissolution states
  • Using noise() to perturb L-system branch angles creates organic irregularity preventing mechanical appearance of deterministic rules
  • Four buffer layers composite with varying blend modes creates luminous glow impossible with single-canvas rendering