Quantum Coherence - Bose-Einstein Phase Collapse
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.🔧 核心算法要点
- Pixel-level domain warping using nested FBM noise sampling at multiple scales (2.5, 4.0, 8.0 warp coefficients) with recursive coordinate distortion
- Triple-layered compositing architecture: domain warp buffer (ADD blend), coherence buffer (SCREEN blend), iridescent buffer (SCREEN blend) for depth
- Per-pixel noise sampling where final coordinates are calculated by accumulated noise offsets, creating fluid morphing quantum states
- Quantum phase visualization using multi-frequency wave interference patterns with angle and distance-based radial functions
- Iridescent interference overlay using angle-dependent sinusoidal modulation and Perlin noise for plasma-like shimmer effects
- Mouse proximity influences all three layers through exponential falloff, creating attractor-like distortions that suggest quantum measurement collapse
- Phase mode switching (keys 1-3) changes interference pattern modes: concentric coherence waves, spiral patterns, or multi-wave interference
- 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