Ego-Death Fractal Tunnel into the Riemann Zeta Zero
Generated by GridFlow AI | Tags: fractal, julia-set, riemann-zeta, psychedelic, tunnel, synesthesia, ego-death, recursive-void
💡 AI 提示词
Ego-Death Fractal Tunnel into the Riemann Zeta Zero - psychedelic synesthesia with deep shifting gradients and iridescent elements using complex number mapping with Julia set iterations per-pixel🔧 核心算法要点
- Complex plane Julia set iteration mapping each pixel with time-evolving c parameter based on Riemann zeta approximation
- Approximate Riemann zeta function using Dirichlet eta series and reflection formula for critical line evaluation
- Multi-layer compositing with createGraphics offscreen buffers for fractal, tunnel geometry, and void layers
- Additive and screen blend modes for luminous iridescent glow effects impossible with single-canvas rendering
- Recursive void spirals using curveVertex sequences with fractal noise for organic depth
- Ego-death vortex spiral animation converging toward zeta zero with chromatic aberration bloom
- Per-pixel fractal computation with smooth iteration coloring influenced by zeta function magnitude and phase
🎨 原始代码
var sketch = function(p) {
var fractalBuffer, tunnelGraphics, voidGraphics, bloomBuffer;
var palette, currentPalette;
var time = 0;
var mode = 0;
var paletteModes = ['psychedelic', 'alchemical', 'bismuth', 'abyssal'];
var zoomLevel = 1;
var mouseInfluence = { x: 0, y: 0 };
var egoDeathActive = false;
var egoDeathParticles = [];
var RES = 3;
p.setup = function() {
var container = document.getElementById('p5-wrapper');
p.createCanvas(container.offsetWidth, container.offsetHeight).parent(container);
p.colorMode(p.RGB, 255, 255, 255, 255);
p.noStroke();
fractalBuffer = p.createGraphics(p.width, p.height);
tunnelGraphics = p.createGraphics(p.width, p.height);
voidGraphics = p.createGraphics(p.width, p.height);
bloomBuffer = p.createGraphics(p.width, p.height);
initPalette();
fractalBuffer.pixelDensity(1);
p.pixelDensity(1);
};
function initPalette() {
var modeName = paletteModes[mode];
if (modeName === 'psychedelic') {
palette = [
[20, 10, 60],
[60, 20, 120],
[120, 30, 180],
[180, 60, 220],
[220, 120, 200],
[255, 200, 100],
[100, 255, 200],
[200, 255, 255]
];
} else if (modeName === 'alchemical') {
palette = [
[10, 15, 50],
[80, 100, 140],
[180, 160, 80],
[220, 200, 120],
[100, 180, 200],
[60, 80, 120]
];
} else if (modeName === 'bismuth') {
palette = [
[40, 40, 60],
[100, 120, 140],
[160, 180, 200],
[200, 180, 160],
[180, 140, 100],
[140, 100, 160],
[200, 200, 220],
[180, 200, 180]
];
} else {
palette = [
[40, 5, 10],
[80, 15, 20],
[120, 30, 30],
[60, 40, 30],
[100, 50, 40],
[30, 20, 15],
[150, 60, 50],
[80, 30, 25]
];
}
currentPalette = palette;
}
function lerpColor(c1, c2, t) {
return [
c1[0] + (c2[0] - c1[0]) * t,
c1[1] + (c2[1] - c1[1]) * t,
c1[2] + (c2[2] - c1[2]) * t
];
}
function getColorAtPosition(t) {
var idx1 = Math.floor(t) % currentPalette.length;
var idx2 = (idx1 + 1) % currentPalette.length;
var f = (t % 1);
return lerpColor(currentPalette[idx1], currentPalette[idx2], f);
}
function complexMul(a, b) {
return {
re: a.re * b.re - a.im * b.im,
im: a.re * b.im + a.im * b.re
};
}
function complexDiv(a, b) {
var denom = b.re * b.re + b.im * b.im;
if (denom < 1e-10) return { re: 0, im: 0 };
return {
re: (a.re * b.re + a.im * b.im) / denom,
im: (a.im * b.re - a.re * b.im) / denom
};
}
function complexExp(a) {
var expReal = Math.exp(a.re);
return {
re: expReal * Math.cos(a.im),
im: expReal * Math.sin(a.im)
};
}
function complexLog(a) {
return {
re: Math.log(Math.sqrt(a.re * a.re + a.im * a.im)),
im: Math.atan2(a.im, a.re)
};
}
function complexPow(base, exp) {
var logBase = complexLog(base);
return complexExp({
re: logBase.re * exp - logBase.im * 0,
im: logBase.im * exp
});
}
function computeZeta(sigma, t) {
var s = { re: sigma, im: t };
var etaSum = { re: 0, im: 0 };
var one = { re: 1, im: 0 };
var negOne = { re: -1, im: 0 };
for (var k = 1; k <= 60; k++) {
var denom = complexPow({ re: k, im: 0 }, s);
if (denom.re * denom.re + denom.im * denom.im > 1e-10) {
var term = complexDiv(k % 2 === 1 ? one : negOne, denom);
etaSum.re += term.re;
etaSum.im += term.im;
}
}
var oneMinusPow = complexPow({ re: 2, im: 0 }, { re: 1 - sigma, im: -t });
var diff = { re: 1 - oneMinusPow.re, im: -oneMinusPow.im };
if (diff.re * diff.re + diff.im * diff.im > 1e-10) {
return complexDiv(etaSum, diff);
}
return { re: 1, im: 0 };
}
function iterateJulia(cx, cy, maxIter) {
var zx = cx;
var zy = cy;
var zetaC = computeZeta(0.5, cx * 5);
var cReal = 0.3 + 0.3 * Math.sin(time * 0.3) + zetaC.re * 0.1;
var cImag = 0.5 + 0.2 * Math.cos(time * 0.25) + zetaC.im * 0.1;
for (var i = 0; i < maxIter; i++) {
var zxNew = zx * zx - zy * zy + cReal;
zy = 2 * zx * zy + cImag;
zx = zxNew;
if (zx * zx + zy * zy > 256) {
return { iter: i, escape: true, zx: zx, zy: zy };
}
}
return { iter: maxIter, escape: false, zx: zx, zy: zy };
}
function drawFractalLayer() {
fractalBuffer.loadPixels();
var pixels = fractalBuffer.pixels;
for (var y = 0; y < p.height; y += RES) {
for (var x = 0; x < p.width; x += RES) {
var nx = (x - p.width / 2) / (p.height * 0.5 * zoomLevel);
var ny = (y - p.height / 2) / (p.height * 0.5 * zoomLevel);
var mx = (p.mouseX - p.width / 2) / p.width;
var my = (p.mouseY - p.height / 2) / p.height;
var mouseEffect = Math.exp(-(mx * mx + my * my) * 10);
var zetaVal = computeZeta(0.5 + nx * 0.1, ny * 10);
var jResult = iterateJulia(nx + mx * mouseEffect * 0.5, ny + my * mouseEffect * 0.5, 80);
var iterNorm = jResult.iter / 80;
var smoothIter = iterNorm;
if (jResult.escape) {
var log_zn = Math.log(jResult.zx * jResult.zx + jResult.zy * jResult.zy) / 2;
var nu = Math.log(log_zn / Math.log(2)) / Math.log(2);
smoothIter = jResult.iter + 1 - nu;
smoothIter = smoothIter / 80;
}
var zetaMag = Math.sqrt(zetaVal.re * zetaVal.re + zetaVal.im * zetaVal.im);
var zetaPhase = Math.atan2(zetaVal.im, zetaVal.re);
var colorT = smoothIter * 3 + zetaPhase * 0.5 + time * 0.1 + mouseEffect * 2;
var col = getColorAtPosition(colorT % 1);
var bright = smoothIter * 0.6 + Math.min(zetaMag * 0.1, 0.4);
var chroma = 1 + 0.5 * Math.sin(zetaPhase * 3 + time);
for (var dy = 0; dy < RES && y + dy < p.height; dy++) {
for (var dx = 0; dx < RES && x + dx < p.width; dx++) {
var idx = ((y + dy) * p.width + (x + dx)) * 4;
var r = col[0] * bright * chroma;
var g = col[1] * bright;
var b = col[2] * bright / chroma;
pixels[idx] = Math.min(255, r);
pixels[idx + 1] = Math.min(255, g);
pixels[idx + 2] = Math.min(255, b);
pixels[idx + 3] = 255;
}
}
}
}
fractalBuffer.updatePixels();
}
function drawTunnelGeometry() {
tunnelGraphics.clear();
var cx = p.width / 2;
var cy = p.height / 2;
var mx = (p.mouseX - cx) / cx;
var my = (p.mouseY - cy) / cy;
tunnelGraphics.push();
tunnelGraphics.translate(cx, cy);
tunnelGraphics.noFill();
var layers = 12;
for (var layer = 0; layer < layers; layer++) {
var layerRatio = layer / layers;
var baseRadius = p.height * (0.3 - layerRatio * 0.25);
var alpha = (180 - layerRatio * 120) * (0.5 + 0.5 * Math.sin(time + layer));
var sw = 2 - layerRatio * 1.5;
tunnelGraphics.strokeWeight(sw);
tunnelGraphics.stroke(
currentPalette[layer % currentPalette.length][0],
currentPalette[layer % currentPalette.length][1],
currentPalette[layer % currentPalette.length][2],
alpha
);
tunnelGraphics.beginShape();
var segments = 120;
for (var i = 0; i <= segments; i++) {
var angle = (i / segments) * p.TWO_PI * 3;
var tunnelAngle = angle + time * 0.3 * (layer % 2 === 0 ? 1 : -1);
var depthFactor = layerRatio * 0.3;
var noise1 = p.noise(
Math.cos(tunnelAngle) * 2 + depthFactor,
Math.sin(tunnelAngle) * 2 + depthFactor,
time * 0.5
);
var noise2 = p.noise(
Math.cos(tunnelAngle) * 3 - depthFactor,
Math.sin(tunnelAngle) * 3 - depthFactor,
time * 0.3 + 100
);
var radiusMod = baseRadius * (0.7 + 0.4 * (noise1 * 0.7 + noise2 * 0.3));
var spiralFactor = 1 + layerRatio * 0.5;
var spiralAngle = tunnelAngle + layerRatio * Math.PI * 2 + mx * 0.5;
var finalX = radiusMod * Math.cos(spiralAngle) * spiralFactor;
var finalY = radiusMod * Math.sin(spiralAngle) * spiralFactor;
if (i === 0) {
tunnelGraphics.vertex(finalX, finalY);
} else {
tunnelGraphics.vertex(finalX, finalY);
}
}
tunnelGraphics.endShape(p.CLOSE);
}
tunnelGraphics.pop();
}
function drawRecursiveVoid() {
voidGraphics.clear();
var cx = p.width / 2;
var cy = p.height / 2;
voidGraphics.push();
voidGraphics.translate(cx, cy);
var depthLevels = 10;
for (var depth = 0; depth < depthLevels; depth++) {
var depthRatio = depth / depthLevels;
var radius = 80 + depth * 60;
var segments = 8 + depth * 4;
var alpha = 150 - depth * 12;
voidGraphics.noFill();
voidGraphics.strokeWeight(2.5 - depthRatio * 2);
voidGraphics.stroke(
currentPalette[(depth + 2) % currentPalette.length][0],
currentPalette[(depth + 2) % currentPalette.length][1],
currentPalette[(depth + 2) % currentPalette.length][2],
alpha
);
voidGraphics.beginShape();
for (var i = 0; i <= segments; i++) {
var angle = (i / segments) * p.TWO_PI;
var noiseVal = p.noise(
Math.cos(angle) * 2.5 + depth,
Math.sin(angle) * 2.5 + depth,
time * 0.4
);
var rMod = radius * (0.6 + 0.8 * noiseVal);
voidGraphics.curveVertex(
rMod * Math.cos(angle) + mx * 20,
rMod * Math.sin(angle) + my * 20
);
}
voidGraphics.endShape(p.CLOSE);
if (depth < depthLevels - 1) {
for (var k = 0; k < 6; k++) {
var kAngle = (k / 6) * p.TWO_PI + time * 0.2;
var kR = radius * 0.4 * (1 + 0.3 * Math.sin(time + k));
voidGraphics.fill(
currentPalette[(depth + k) % currentPalette.length][0],
currentPalette[(depth + k) % currentPalette.length][1],
currentPalette[(depth + k) % currentPalette.length][2],
100
);
voidGraphics.noStroke();
voidGraphics.ellipse(
kR * Math.cos(kAngle),
kR * Math.sin(kAngle),
10 - depth,
10 - depth
);
}
}
}
voidGraphics.pop();
}
function drawZetaSpiral() {
var cx = p.width / 2;
var cy = p.height / 2;
for (var spiral = 0; spiral < 8; spiral++) {
var spiralOffset = spiral * 0.08;
var baseR = 60 + spiral * 25;
p.strokeWeight(2.5 + 1.5 * Math.sin(time * 2 + spiral));
p.beginShape();
for (var i = 0; i <= 150; i++) {
var t = i * 0.08 + time * 0.6 + spiralOffset;
var r = baseR + t * 35;
var theta = t * 2.5 + spiral * 0.4;
var zetaVal = computeZeta(0.5, t * 0.1);
var colorT = (spiral + t * 0.2) % 1;
var col = getColorAtPosition(colorT);
var bright = 180 + 75 * Math.sin(t * 4 + spiral * 2);
p.stroke(col[0], col[1], col[2], bright);
p.vertex(cx + r * Math.cos(theta), cy + r * Math.sin(theta));
}
p.endShape();
}
}
function drawIridescentPulse() {
var cx = p.width / 2;
var cy = p.height / 2;
var pulseR = 180 + 120 * Math.sin(time * 1.5);
for (var ring = 0; ring < 6; ring++) {
var r = pulseR + ring * 60;
var alpha = 40 - ring * 5;
var col = currentPalette[(ring + 4) % currentPalette.length];
p.noFill();
p.stroke(col[0], col[1], col[2], alpha);
p.strokeWeight(1.5);
p.ellipse(cx, cy, r * 2, r * 2);
}
p.fill(255, 255, 255, 15 + 15 * Math.sin(time * 5));
p.noStroke();
p.ellipse(cx, cy, 60 + 20 * Math.sin(time * 3), 60 + 20 * Math.sin(time * 3));
}
function drawEgoDeath() {
if (!egoDeathActive) return;
for (var i = egoDeathParticles.length - 1; i >= 0; i--) {
var part = egoDeathParticles[i];
part.x += part.vx;
part.y += part.vy;
part.life -= 0.015;
part.size *= 0.98;
if (part.life <= 0) {
egoDeathParticles.splice(i, 1);
continue;
}
var col = getColorAtPosition(part.phase);
p.fill(col[0], col[1], col[2], part.life * 255);
p.noStroke();
p.ellipse(part.x, part.y, part.size, part.size);
}
if (egoDeathParticles.length === 0) {
egoDeathActive = false;
}
}
function triggerEgoDeath() {
egoDeathActive = true;
var mx = p.mouseX;
var my = p.mouseY;
for (var i = 0; i < 80; i++) {
var angle = p.random(p.TWO_PI);
var speed = p.random(3, 12);
var r = p.random(10, 120);
var col = getColorAtPosition(p.random(1));
egoDeathParticles.push({
x: mx + Math.cos(angle) * r,
y: my + Math.sin(angle) * r,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed,
size: p.random(8, 20),
life: 1,
phase: p.random(1)
});
}
for (var j = 0; j < 6; j++) {
var r = 30 + j * 40;
var col = currentPalette[j % currentPalette.length];
p.noFill();
p.stroke(col[0], col[1], col[2], 200);
p.strokeWeight(3);
p.ellipse(mx, my, r * 2, r * 2);
}
}
function handleKeyboard() {
if (p.key === 'z' || p.key === 'Z') {
mode = (mode + 1) % 4;
initPalette();
}
if (p.key === 'r' || p.key === 'R') {
zoomLevel = 1;
egoDeathParticles = [];
egoDeathActive = false;
}
if (p.key === '1') zoomLevel = Math.max(0.5, zoomLevel - 0.2);
if (p.key === '2') zoomLevel = Math.min(4, zoomLevel + 0.2);
}
p.draw = function() {
time += 0.012;
var bgColor = currentPalette[0];
p.background(bgColor[0] * 0.3, bgColor[1] * 0.3, bgColor[2] * 0.3);
zoomLevel = 1 + 0.5 * Math.sin(time * 0.3);
drawFractalLayer();
drawTunnelGeometry();
drawRecursiveVoid();
p.blendMode(p.ADD);
p.image(fractalBuffer, 0, 0);
p.image(tunnelGraphics, 0, 0);
p.image(voidGraphics, 0, 0);
p.blendMode(p.SCREEN);
p.image(fractalBuffer, 0, 0);
p.blendMode(p.BLEND);
drawZetaSpiral();
drawIridescentPulse();
drawEgoDeath();
p.fill(180, 160, 200, 120);
p.textAlign(p.LEFT, p.BOTTOM);
p.textSize(11);
p.text('Mode: ' + paletteModes[mode] + ' [Z]', 12, p.height - 12);
p.text('[1/2] Zoom | [R] Reset | Click for Ego-Death', 12, p.height - 30);
p.text('Ego-Death Fractal Tunnel - Riemann Zeta Zero', 12, p.height - 48);
};
p.mouseMoved = function() {
mouseInfluence.x = (p.mouseX - p.width / 2) / p.width;
mouseInfluence.y = (p.mouseY - p.height / 2) / p.height;
};
p.mousePressed = function() {
triggerEgoDeath();
};
p.keyPressed = function() {
handleKeyboard();
};
p.windowResized = function() {
var container = document.getElementById('p5-wrapper');
p.resizeCanvas(container.offsetWidth, container.offsetHeight);
fractalBuffer = p.createGraphics(p.width, p.height);
tunnelGraphics = p.createGraphics(p.width, p.height);
voidGraphics = p.createGraphics(p.width, p.height);
fractalBuffer.pixelDensity(1);
};
};
✨ AI 艺术解读
This artwork simulates a metaphysical descent into the Riemann zeta zero - the most profound unsolved mystery in mathematics. The fractal tunnel represents consciousness dissolving into pure mathematical truth, while the iridescent spiral evokes ego-death transformation. Each pixel computes Julia set dynamics colored by complex zeta values, creating a synesthetic bridge between number theory and visual experience. The recursive voids spiral inward like ancient temples or cosmic event horizons, inviting the viewer to confront mathematical infinity.
📝 补充说明
- Julia set c parameter evolves with time and incorporates zeta function values for mathematically-inspired morphing
- Resolution step of 3 used for pixel-level computation balance between detail and performance
- Four curated palette modes: psychedelic synesthesia, alchemical transmutation, bismuth crystal, abyssal horror
- Ego-death particle burst triggered on click creates transient ego dissolution visual event
- Additive blending creates natural bloom without expensive Gaussian blur post-processing