Quantum Coherence - Bose-Einstein Phase Collapse

📅 April 25, 2026 🏷️ art
bose-einstein condensate quantum phase transition domain warping psychedelic synesthesia pixel-level rendering iridescent gradients quantum coherence generative art pending-review
Generated by GridFlow AI | Tags: bose-einstein condensate, quantum phase transition, domain warping, psychedelic synesthesia, pixel-level rendering, iridescent gradients, quantum coherence, generative art

💡 AI 提示词

Bose-Einstein Condensate Phase Transitions rendered as a psychedelic synesthesia visualization with deep shifting gradients, high-contrast iridescent elements, quantum coherence wave interference patterns, and pixel-level domain warping creating fluid morphing effects that simulate quantum state collapse and coherence.

🔧 核心算法要点

  1. Pixel-level domain warping using nested FBM noise sampling at multiple scales (2.5, 4.0, 8.0 warp coefficients) with recursive coordinate distortion
  2. Triple-layered compositing architecture: domain warp buffer (ADD blend), coherence buffer (SCREEN blend), iridescent buffer (SCREEN blend) for depth
  3. Per-pixel noise sampling where final coordinates are calculated by accumulated noise offsets, creating fluid morphing quantum states
  4. Quantum phase visualization using multi-frequency wave interference patterns with angle and distance-based radial functions
  5. Iridescent interference overlay using angle-dependent sinusoidal modulation and Perlin noise for plasma-like shimmer effects
  6. Mouse proximity influences all three layers through exponential falloff, creating attractor-like distortions that suggest quantum measurement collapse
  7. Phase mode switching (keys 1-3) changes interference pattern modes: concentric coherence waves, spiral patterns, or multi-wave interference
  8. Click-triggered phase collapse animation radiates expanding wave ring with hue shift and intensity burst, simulating condensate collapse

🎨 原始代码

var sketch = function(p) {
  var width, height;
  var domainBuffer, coherenceBuffer, iridescentBuffer;
  var timeOffset = 0;
  var phaseMode = 0;
  var collapseActive = false;
  var collapseTime = 0;
  var mouseInfluence = 0;
  var palette;

  palette = {
    deepVoid: [8, 2, 12],
    quantumPurple: [270, 85, 55],
    iridescentCyan: [180, 100, 80],
    plasmaMagenta: [320, 90, 70],
    coherenceGold: [45, 80, 90],
    phaseBlue: [220, 70, 60]
  };

  p.setup = function() {
    var container = document.getElementById('p5-wrapper');
    width = container.offsetWidth;
    height = container.offsetHeight;
    p.createCanvas(width, height).parent(container);
    p.colorMode(p.HSB, 360, 100, 100, 100);
    p.noStroke();

    domainBuffer = p.createGraphics(width, height);
    coherenceBuffer = p.createGraphics(width, height);
    iridescentBuffer = p.createGraphics(width, height);

    domainBuffer.noStroke();
    coherenceBuffer.noStroke();
    iridescentBuffer.noStroke();
  };

  p.draw = function() {
    timeOffset += 0.003;
    mouseInfluence = p.dist(p.mouseX, p.mouseY, p.width / 2, p.height / 2) / (p.width * 0.5);
    mouseInfluence = 1 - p.constrain(mouseInfluence, 0, 1);

    if (collapseActive) {
      collapseTime += 0.02;
      if (collapseTime > 1) {
        collapseActive = false;
        collapseTime = 0;
      }
    }

    renderDomainWarpLayer();
    renderCoherenceLayer();
    renderIridescentLayer();

    p.background(0, 0, 5);
    p.image(domainBuffer, 0, 0);
    p.blendMode(p.ADD);
    p.image(coherenceBuffer, 0, 0);
    p.blendMode(p.SCREEN);
    p.image(iridescentBuffer, 0, 0);
    p.blendMode(p.BLEND);

    renderPhaseIndicator();
  };

  function renderDomainWarpLayer() {
    domainBuffer.loadPixels();
    var d = domainBuffer.pixels;
    var step = 3;

    for (var y = 0; y < height; y += step) {
      for (var x = 0; x < width; x += step) {
        var cx = x / width;
        var cy = y / height;

        var warpScale1 = 2.5;
        var warpScale2 = 4.0;
        var warpScale3 = 8.0;

        var t = timeOffset * 0.5;

        var wx1 = p.noise(cx * warpScale1 + t, cy * warpScale1 + t, t * 0.7);
        var wy1 = p.noise(cx * warpScale1 + 100, cy * warpScale1 + 100, t * 0.7 + 50);

        var wx2 = p.noise(cx * warpScale2 + wx1 * 3, cy * warpScale2 + wy1 * 3, t + 20);
        var wy2 = p.noise(cx * warpScale2 + 200 + wx1 * 3, cy * warpScale2 + 200 + wy1 * 3, t + 20);

        var wx3 = p.noise(cx * warpScale3 + wx2 * 2, cy * warpScale3 + wy2 * 2, t + 40);
        var wy3 = p.noise(cx * warpScale3 + 300 + wx2 * 2, cy * warpScale3 + 300 + wy2 * 2, t + 40);

        var finalX = cx + (wx1 - 0.5) * 0.15 + (wx2 - 0.5) * 0.2;
        var finalY = cy + (wy1 - 0.5) * 0.15 + (wy2 - 0.5) * 0.2;

        var mx = (p.mouseX / width - 0.5) * mouseInfluence * 0.3;
        var my = (p.mouseY / height - 0.5) * mouseInfluence * 0.3;
        finalX += mx;
        finalY += my;


        var noiseVal = p.noise(finalX * 3 + t, finalY * 3 + t, t * 1.5);
        var noiseVal2 = p.noise(finalX * 6 - t * 0.5, finalY * 6 - t * 0.5, t * 2);
        var noiseVal3 = p.noise(finalX * 12 + t * 0.3, finalY * 12 + t * 0.3, t * 2.5);

        var hue = p.map(noiseVal, 0, 1, palette.quantumPurple[0], palette.phaseBlue[0]);
        hue = (hue + timeOffset * 50) % 360;
        var sat = p.map(noiseVal2, 0, 1, 60, 100);
        var bri = p.map(noiseVal3, 0, 1, 25, 70);

        if (collapseActive) {
          var distToCenter = p.dist(cx, cy, 0.5, 0.5);
          var collapseWave = p.sin((distToCenter - collapseTime * 2) * 20) * 0.5 + 0.5;
          collapseWave *= p.exp(-distToCenter * 3);
          hue = hue + collapseWave * 120;
          bri = bri + collapseWave * 30;
        }

        var r = p.bri / 100;
        var g = p.bri / 100;
        var b = p.bri / 100;
        var hNorm = hue / 360;
        var sNorm = sat / 100;

        if (sNorm > 0) {
          var h6 = hNorm * 6;
          var i = Math.floor(h6);
          var f = h6 - i;
          var v = bri / 100;
          var pv = v * (1 - sNorm);
          var qv = v * (1 - f * sNorm);
          var tv = v * (1 - (1 - f) * sNorm);
          i = i % 6;
          var args = [v * 255, tv * 255, pv * 255, pv * 255, qv * 255, v * 255];
          r = args[(i + 4) % 6] / 255;
          g = args[(i + 2) % 6] / 255;
          b = args[(i + 0) % 6] / 255;
        } else {
          r = bri / 100;
          g = bri / 100;
          b = bri / 100;
        }

        for (var dy = 0; dy < step && y + dy < height; dy++) {
          for (var dx = 0; dx < step && x + dx < width; dx++) {
            var idx = 4 * ((y + dy) * width + (x + dx));
            d[idx] = r * 255;
            d[idx + 1] = g * 255;
            d[idx + 2] = b * 255;
            d[idx + 3] = 255;
          }
        }
      }
    }
    domainBuffer.updatePixels();
  }

  function renderCoherenceLayer() {
    coherenceBuffer.background(0, 0, 0, 0);
    coherenceBuffer.loadPixels();
    var d = coherenceBuffer.pixels;
    var step = 4;

    var centerX = width / 2 + (p.mouseX - width / 2) * mouseInfluence * 0.5;
    var centerY = height / 2 + (p.mouseY - height / 2) * mouseInfluence * 0.5;

    for (var y = 0; y < height; y += step) {
      for (var x = 0; x < width; x += step) {
        var dx = x - centerX;
        var dy = y - centerY;
        var dist = Math.sqrt(dx * dx + dy * dy);
        var angle = Math.atan2(dy, dx);

        var coherence = 0;

        if (phaseMode === 0) {
          for (var n = 1; n <= 5; n++) {
            var wave = p.sin(dist * 0.02 * n - timeOffset * 3 * n + angle * n * 2);
            coherence += wave / n * 0.5 + 0.5;
          }
        } else if (phaseMode === 1) {
          var spiralAngle = angle * 8 + dist * 0.01 + timeOffset * 2;
          coherence = (p.sin(spiralAngle) * 0.5 + 0.5) * (p.sin(dist * 0.015 - timeOffset * 4) * 0.5 + 0.5);
        } else {
          for (var n = 1; n <= 3; n++) {
            var interference = p.sin(dist * 0.025 * n + timeOffset * n * 2) * p.cos(angle * n * 3 - timeOffset);
            coherence += (interference * 0.5 + 0.5) / n;
          }
          coherence *= 0.7 + 0.3 * p.noise(x * 0.01 + timeOffset, y * 0.01 + timeOffset);
        }

        if (collapseActive) {
          var collapseRadius = collapseTime * width * 0.8;
          var ringDist = Math.abs(dist - collapseRadius);
          var ringIntensity = Math.exp(-ringDist * 0.03) * p.sin(dist * 0.1 - collapseTime * 10);
          coherence += ringIntensity * 0.8;
        }

        coherence = p.constrain(coherence, 0, 1);

        var hue = palette.iridescentCyan[0] + coherence * 60;
        var sat = palette.iridescentCyan[1] + coherence * 20;
        var bri = coherence * palette.iridescentCyan[2];

        var alpha = coherence * 60;

        var r = bri / 100;
        var g = bri / 100;
        var b = bri / 100;
        var hNorm = hue / 360;
        var sNorm = sat / 100;

        if (sNorm > 0) {
          var h6 = hNorm * 6;
          var i = Math.floor(h6);
          var f = h6 - i;
          var v = bri / 100;
          var pv = v * (1 - sNorm);
          var qv = v * (1 - f * sNorm);
          var tv = v * (1 - (1 - f) * sNorm);
          i = i % 6;
          var args = [v * 255, tv * 255, pv * 255, pv * 255, qv * 255, v * 255];
          r = args[(i + 4) % 6] / 255;
          g = args[(i + 2) % 6] / 255;
          b = args[(i + 0) % 6] / 255;
        } else {
          r = bri / 100;
          g = bri / 100;
          b = bri / 100;
        }

        for (var dy = 0; dy < step && y + dy < height; dy++) {
          for (var dx = 0; dx < step && x + dx < width; dx++) {
            var idx = 4 * ((y + dy) * width + (x + dx));
            d[idx] = r * 255;
            d[idx + 1] = g * 255;
            d[idx + 2] = b * 255;
            d[idx + 3] = alpha;
          }
        }
      }
    }
    coherenceBuffer.updatePixels();
  }

  function renderIridescentLayer() {
    iridescentBuffer.background(0, 0, 0, 0);
    iridescentBuffer.loadPixels();
    var d = iridescentBuffer.pixels;
    var step = 5;

    for (var y = 0; y < height; y += step) {
      for (var x = 0; x < width; x += step) {
        var cx = x / width;
        var cy = y / height;

        var angle = Math.atan2(cy - 0.5, cx - 0.5);
        var dist = Math.sqrt((cx - 0.5) * (cx - 0.5) + (cy - 0.5) * (cy - 0.5));

        var irid = p.noise(cx * 8 + timeOffset * 0.5, cy * 8 + timeOffset * 0.5, timeOffset * 2);
        irid = p.pow(irid, 2);

        var interference = p.sin(angle * 12 + dist * 30 + timeOffset * 4);
        interference = interference * 0.5 + 0.5;
        interference = p.pow(interference, 3);

        irid *= 0.3 + interference * 0.7;

        var mx = (p.mouseX / width - 0.5);
        var my = (p.mouseY / height - 0.5);
        var mouseDist = Math.sqrt((cx - 0.5 - mx * mouseInfluence) * (cx - 0.5 - mx * mouseInfluence) +
                                  (cy - 0.5 - my * mouseInfluence) * (cy - 0.5 - my * mouseInfluence));
        var mouseGlow = Math.exp(-mouseDist * 4) * mouseInfluence;
        irid = irid * (1 - mouseGlow * 0.5) + mouseGlow * 0.8;

        var hue = palette.plasmaMagenta[0] + irid * 80;
        var sat = 90 + irid * 10;
        var bri = irid * 100;
        var alpha = irid * 70;

        if (collapseActive) {
          var collapseRadius = collapseTime * width * 0.8;
          var ringDist = Math.abs(dist * width - collapseRadius);
          if (ringDist < 20) {
            alpha = 100;
            bri = 100;
          }
        }

        var r = bri / 100;
        var g = bri / 100;
        var b = bri / 100;
        var hNorm = hue / 360;
        var sNorm = sat / 100;

        if (sNorm > 0) {
          var h6 = hNorm * 6;
          var i = Math.floor(h6);
          var f = h6 - i;
          var v = bri / 100;
          var pv = v * (1 - sNorm);
          var qv = v * (1 - f * sNorm);
          var tv = v * (1 - (1 - f) * sNorm);
          i = i % 6;
          var args = [v * 255, tv * 255, pv * 255, pv * 255, qv * 255, v * 255];
          r = args[(i + 4) % 6] / 255;
          g = args[(i + 2) % 6] / 255;
          b = args[(i + 0) % 6] / 255;
        } else {
          r = bri / 100;
          g = bri / 100;
          b = bri / 100;
        }

        for (var dy = 0; dy < step && y + dy < height; dy++) {
          for (var dx = 0; dx < step && x + dx < width; dx++) {
            var idx = 4 * ((y + dy) * width + (x + dx));
            d[idx] = r * 255;
            d[idx + 1] = g * 255;
            d[idx + 2] = b * 255;
            d[idx + 3] = alpha;
          }
        }
      }
    }
    iridescentBuffer.updatePixels();
  }

  function renderPhaseIndicator() {
    var modeNames = ['Coherent State', 'Spiral Wave', 'Interference'];
    var modeName = modeNames[phaseMode];

    p.fill(0, 0, 100, 70);
    p.rect(p.width - 220, p.height - 40, 210, 30, 5);
    p.fill(0, 0, 100);
    p.textSize(12);
    p.textAlign(p.RIGHT, p.CENTER);
    p.text('Phase: ' + modeName + ' | Click: Collapse | Keys: 1-3', p.width - 15, p.height - 25);

    if (collapseActive) {
      var alpha = (1 - collapseTime) * 80;
      p.fill(palette.coherenceGold[0], 80, 90, alpha);
      p.textSize(24);
      p.textAlign(p.CENTER, p.CENTER);
      p.text('PHASE COLLAPSE', p.width / 2, p.height / 2);
    }
  }

  p.mousePressed = function() {
    collapseActive = true;
    collapseTime = 0;
  };

  p.keyPressed = function() {
    if (p.key === '1') {
      phaseMode = 0;
    } else if (p.key === '2') {
      phaseMode = 1;
    } else if (p.key === '3') {
      phaseMode = 2;
    } else if (p.key === 'r' || p.key === 'R') {
      timeOffset = 0;
      phaseMode = 0;
      collapseActive = false;
      collapseTime = 0;
    }
  };

  p.windowResized = function() {
    var container = document.getElementById('p5-wrapper');
    width = container.offsetWidth;
    height = container.offsetHeight;
    p.resizeCanvas(width, height);

    var oldDomain = domainBuffer;
    var oldCoherence = coherenceBuffer;
    var oldIridescent = iridescentBuffer;

    domainBuffer = p.createGraphics(width, height);
    coherenceBuffer = p.createGraphics(width, height);
    iridescentBuffer = p.createGraphics(width, height);

    domainBuffer.noStroke();
    coherenceBuffer.noStroke();
    iridescentBuffer.noStroke();
  };
}; // p5 init stripped

✨ AI 艺术解读

This artwork visualizes the quantum mechanical phenomenon of Bose-Einstein condensation as a psychedelic synesthetic experience. The pixel-level domain warping creates fluid, non-Euclidean distortions that suggest the wavefunction collapse from superposition into a single coherent state. The iridescent interference patterns evoke the quantum coherence property where atoms lose their individual identities and behave as a single quantum entity. The collapse animation triggered by clicks represents the fundamental quantum measurement problem - how observation forces the wavefunction to choose a definite state.

📝 补充说明

  • Domain warping step size of 3 pixels provides good performance while maintaining visual smoothness through pixel fill interpolation
  • Using loadPixels/updatePixels on createGraphics buffers enables GPU-accelerated pixel manipulation per frame
  • Three separate graphics buffers prevent read-write conflicts and allow independent blending of quantum layers
  • Phase mode persistence and collapse animation state are preserved across frames for smooth visual continuity
  • The palette uses HSB color space with manual RGB conversion to maintain precise control over iridescent color transitions and prevent p5.js HSB blending artifacts in pixel buffers