Ego-Death Fractal Tunnel Recursive Descent
Generated by GridFlow AI | Tags: fractal-tunnel, domain-warping, recursive-descent, ego-death, hallucinogenic, psychedelic-art, monochrome-void, pixel-manipulation
💡 AI 提示词
Create a profound hallucinatory monochrome fractal tunnel depicting ego-death and recursive descent into infinite void. Use pixel-level domain warping with multiple noise sampling passes. Apply multi-layer compositing with glow buffers. The single hue should be deep violet-cyan with ethereal bloom and recursive fractal geometry.🔧 核心算法要点
- Domain warping performed in 3 nested passes sampling noise at noise-warped coordinates for fractal chaos
- Recursive tunnel geometry computed in polar coordinates with logarithmic spiral distortion and time-varying wave perturbations
- Pixel-level rendering via loadPixels() loop with step size for performance, computing tunnel depth from concentric layer intersections
- Multi-layer offscreen buffer compositing: pixel tunnel buffer + glow buffer + curve overlay buffer
- Additive blend mode (blendMode ADD) for glow layer compositing over pixel buffer
- Recursive curve rendering using curveVertex() for bezier-like organic tunnel walls with fractal depth scaling
- Recursive function calls reducing scale by 0.75x per depth level for self-similar fractal structure
🎨 原始代码
var sketch = function(p) {
var tunnelBuffer, glowBuffer, depthBuffer;
var time = 0;
var recursionDepth = 7;
var tunnelRadius;
var pixelBuffer;
var pixelStep = 3;
var mouseInfluence = 0;
var spiralPhase = 0;
var depthMask;
var baseHue = 0.72;
p.setup = function() {
var container = document.getElementById('p5-wrapper');
var w = container.offsetWidth;
var h = container.offsetHeight;
p.createCanvas(w, h).parent(container);
p.colorMode(p.HSB, 1);
p.noStroke();
p.frameRate(30);
tunnelBuffer = p.createGraphics(w, h);
glowBuffer = p.createGraphics(w, h);
depthBuffer = p.createGraphics(w, h);
pixelBuffer = p.createGraphics(w, h);
tunnelBuffer.colorMode(p.HSB, 1);
glowBuffer.colorMode(p.HSB, 1);
depthBuffer.colorMode(p.HSB, 1);
pixelBuffer.colorMode(p.HSB, 1);
tunnelRadius = Math.min(w, h) * 0.42;
pixelStep = Math.max(2, Math.floor(Math.min(w, h) / 400));
initDepthMask(w, h);
};
function initDepthMask(w, h) {
depthBuffer.loadPixels();
var d = depthBuffer.pixelDensity();
var idx = 0;
for (var y = 0; y < h; y++) {
for (var x = 0; x < w; x++) {
var cx = x - w / 2;
var cy = y - h / 2;
var dist = Math.sqrt(cx * cx + cy * cy);
var angle = Math.atan2(cy, cx);
var logDist = Math.log(dist + 1) * 3;
var depthVal = (logDist % 1) * (1 - dist / (w * 0.7));
depthVal = Math.max(0, Math.min(1, depthVal));
depthBuffer.pixels[idx] = depthVal * 255;
depthBuffer.pixels[idx + 1] = 255;
depthBuffer.pixels[idx + 2] = 255;
depthBuffer.pixels[idx + 3] = 255;
idx += 4;
}
}
depthBuffer.updatePixels();
}
p.draw = function() {
var w = p.width;
var h = p.height;
var cx = w / 2 + (p.mouseX - w / 2) * 0.15;
var cy = h / 2 + (p.mouseY - h / 2) * 0.15;
p.background(0, 0, 0.03);
renderPixelLevelDomainWarp(pixelBuffer, w, h, cx, cy);
p.image(pixelBuffer, 0, 0);
p.blendMode(p.ADD);
renderGlowLayer(w, h, cx, cy);
p.blendMode(p.BLEND);
renderRecursiveCurveTunnel(tunnelBuffer, cx, cy, recursionDepth, 1);
p.image(tunnelBuffer, 0, 0);
renderCurveOverlay(w, h, cx, cy);
p.image(depthBuffer, 0, 0);
time += 0.006;
spiralPhase += 0.02;
mouseInfluence = p.lerp(mouseInfluence, 1, 0.02);
};
function renderPixelLevelDomainWarp(buf, w, h, cx, cy) {
buf.loadPixels();
var d = buf.pixelDensity();
var step = pixelStep;
for (var py = 0; py < h; py += step) {
for (var px = 0; px < w; px += step) {
var dx = px - cx;
var dy = py - cy;
var baseAngle = Math.atan2(dy, dx);
var baseDist = Math.sqrt(dx * dx + dy * dy);
var warpX = px;
var warpY = py;
for (var warpPass = 0; warpPass < 3; warpPass++) {
var noiseX = warpX * 0.002 + warpPass * 17.3;
var noiseY = warpY * 0.002 + warpPass * 23.7;
var noiseZ = time * 0.4 + warpPass * 5.1;
var warpStrength = 80 / (warpPass + 1);
warpX += (p.noise(noiseX, noiseY, noiseZ) - 0.5) * warpStrength;
warpY += (p.noise(noiseX + 100, noiseY + 100, noiseZ) - 0.5) * warpStrength;
}
var finalDx = warpX - cx;
var finalDy = warpY - cy;
var finalDist = Math.sqrt(finalDx * finalDx + finalDy * finalDy);
var finalAngle = Math.atan2(finalDy, finalDx);
var spiralAngle = finalAngle + Math.log(finalDist + 1) * 2.5 + spiralPhase;
var spiralWarp = p.noise(Math.cos(spiralAngle) * 0.5, Math.sin(spiralAngle) * 0.5, time * 0.3);
var tunnelDepth = 0;
var tunnelScale = tunnelRadius;
for (var d = 0; d < recursionDepth + 3; d++) {
var layerNoise = p.noise(d * 0.5, time * 0.25, finalAngle * 0.1);
var layerR = tunnelScale * (0.9 + layerNoise * 0.1);
if (finalDist < layerR && finalDist > layerR * 0.05) {
var layerDepth = (layerR - finalDist) / layerR;
tunnelDepth += layerDepth * (1 - d / (recursionDepth + 3)) * 0.7;
}
tunnelScale *= 0.82;
}
var recursiveNoise = p.noise(
finalDx * 0.004 + spiralWarp * 30,
finalDy * 0.004 + spiralWarp * 30,
time * 0.6 + tunnelDepth * 2
);
var recursiveNoise2 = p.noise(
finalDx * 0.008 + tunnelDepth * 5,
finalDy * 0.008 + tunnelDepth * 5,
time * 0.4
);
var recursiveNoise3 = p.noise(
finalDx * 0.016 + recursiveNoise2 * 20,
finalDy * 0.016 + recursiveNoise2 * 20,
time * 0.8
);
var finalValue = tunnelDepth * (0.4 + recursiveNoise * 0.6) * (0.5 + recursiveNoise2 * 0.5);
finalValue += recursiveNoise3 * 0.15 * tunnelDepth;
finalValue *= (0.7 + spiralWarp * 0.3);
finalValue = Math.pow(finalValue, 0.7);
var hue = baseHue + tunnelDepth * 0.08 + spiralWarp * 0.05;
hue = (hue % 1 + 1) % 1;
var sat = 0.85 * finalValue;
var bri = finalValue * 1.2;
for (var fillY = py; fillY < Math.min(py + step, h); fillY++) {
for (var fillX = px; fillX < Math.min(px + step, w); fillX++) {
var idx = (fillY * w + fillX) * 4 * d;
buf.pixels[idx] = hue * 255;
buf.pixels[idx + 1] = sat * 255;
buf.pixels[idx + 2] = bri * 255;
buf.pixels[idx + 3] = Math.min(255, finalValue * 300);
}
}
}
}
buf.updatePixels();
}
function renderRecursiveCurveTunnel(buf, cx, cy, depth, scale) {
buf.clear();
if (depth <= 0 || scale < 0.05) return;
var layers = depth + 2;
for (var layer = 0; layer < layers; layer++) {
var layerScale = scale * (1 - layer * 0.12);
var layerTime = time + layer * 0.3;
var layerHue = baseHue + layer * 0.02;
var segments = 80 + depth * 12;
var points = [];
for (var i = 0; i <= segments; i++) {
var angle = (i / segments) * p.TWO_PI;
var n1 = p.noise(
Math.cos(angle) * 0.8 + layer * 2.5,
Math.sin(angle) * 0.8 + layer * 2.5,
layerTime * 0.5
);
var n2 = p.noise(
Math.cos(angle * 2) * 0.4 + layer * 4.1,
Math.sin(angle * 2) * 0.4 + layer * 4.1,
layerTime * 0.3 + 50
);
var n3 = p.noise(
Math.cos(angle * 4) * 0.2 + layer * 7.3,
Math.sin(angle * 4) * 0.2 + layer * 7.3,
layerTime * 0.2 + 100
);
var combinedNoise = n1 * 0.5 + n2 * 0.3 + n3 * 0.2;
var baseR = tunnelRadius * layerScale;
var wave1 = Math.sin(angle * 3 + layerTime * 2) * baseR * 0.08;
var wave2 = Math.sin(angle * 5 - layerTime * 1.5) * baseR * 0.05;
var wave3 = Math.sin(angle * 7 + layerTime * 3) * baseR * 0.03;
var radius = baseR * (0.7 + combinedNoise * 0.3) + wave1 + wave2 + wave3;
var warpAngle = angle + p.noise(angle * 2, layerTime) * 0.3;
var px = cx + Math.cos(warpAngle) * radius;
var py = cy + Math.sin(warpAngle) * radius;
points.push({ x: px, y: py });
}
var alpha = (depth - layer) / depth * 0.6 + 0.1;
var strokeW = (depth - layer) * 0.5 + 0.5;
buf.stroke(layerHue, 0.8, 1, alpha);
buf.strokeWeight(strokeW * p.height * 0.003);
buf.noFill();
buf.beginShape();
for (var i = 0; i < points.length; i++) {
buf.curveVertex(points[i].x, points[i].y);
}
buf.endShape(p.CLOSE);
}
var nextDepth = depth - 1;
var nextScale = scale * 0.75;
renderRecursiveCurveTunnel(buf, cx, cy, nextDepth, nextScale);
}
function renderGlowLayer(w, h, cx, cy) {
glowBuffer.clear();
glowBuffer.background(0, 0, 0);
var numLayers = 5;
for (var g = 0; g < numLayers; g++) {
var gScale = 1 - g * 0.15;
var gTime = time + g * 0.2;
var gAlpha = 0.15 - g * 0.02;
var segments = 60 + g * 10;
glowBuffer.stroke(baseHue, 0.9, 1, gAlpha);
glowBuffer.strokeWeight((8 - g * 1.5) * p.height * 0.003);
glowBuffer.noFill();
glowBuffer.beginShape();
for (var i = 0; i <= segments; i++) {
var angle = (i / segments) * p.TWO_PI;
var n = p.noise(Math.cos(angle) + g, Math.sin(angle) + g, gTime);
var r = tunnelRadius * gScale * (0.75 + n * 0.25);
var px = cx + Math.cos(angle) * r;
var py = cy + Math.sin(angle) * r;
glowBuffer.curveVertex(px, py);
}
glowBuffer.endShape(p.CLOSE);
}
glowBuffer.filter(p.BLUR, 3 + Math.sin(time * 2) * 1.5);
glowBuffer.loadPixels();
for (var i = 0; i < glowBuffer.pixels.length; i += 4) {
if (glowBuffer.pixels[i + 3] > 0) {
glowBuffer.pixels[i] = baseHue * 255;
glowBuffer.pixels[i + 1] *= 0.7;
glowBuffer.pixels[i + 2] = 255;
}
}
glowBuffer.updatePixels();
glowBuffer.blendMode(p.ADD);
glowBuffer.image(glowBuffer, 0, 0);
glowBuffer.blendMode(p.BLEND);
p.image(glowBuffer, 0, 0);
}
function renderCurveOverlay(w, h, cx, cy) {
depthBuffer.clear();
var bezierLayers = recursionDepth;
for (var b = 0; b < bezierLayers; b++) {
var bTime = time * 0.7 + b * 0.5;
var bScale = 1 - b * 0.1;
var bHue = (baseHue + b * 0.03) % 1;
var numCurves = 4;
for (var c = 0; c < numCurves; c++) {
var curveAngle = (c / numCurves) * p.TWO_PI + bTime * 0.5;
depthBuffer.stroke(bHue, 0.6, 0.9, 0.4 - b * 0.04);
depthBuffer.strokeWeight((2 - b * 0.2) * p.height * 0.002);
depthBuffer.noFill();
var ctrlDist = tunnelRadius * bScale * 0.6;
var endDist = tunnelRadius * bScale * (0.5 + p.noise(b, c, bTime) * 0.3);
var x0 = cx + Math.cos(curveAngle) * tunnelRadius * bScale * 0.3;
var y0 = cy + Math.sin(curveAngle) * tunnelRadius * bScale * 0.3;
var cx1 = cx + Math.cos(curveAngle + 0.5) * ctrlDist;
var cy1 = cy + Math.sin(curveAngle + 0.5) * ctrlDist;
var cx2 = cx + Math.cos(curveAngle - 0.5) * ctrlDist;
var cy2 = cy + Math.sin(curveAngle - 0.5) * ctrlDist;
var x3 = cx + Math.cos(curveAngle) * endDist;
var y3 = cy + Math.sin(curveAngle) * endDist;
depthBuffer.beginShape();
depthBuffer.vertex(x0, y0);
depthBuffer.bezierVertex(cx1, cy1, cx2, cy2, x3, y3);
depthBuffer.endShape();
}
}
}
p.mousePressed = function() {
spiralPhase += Math.PI * 0.5;
mouseInfluence = 1.5;
};
p.keyPressed = function() {
if (p.key === ' ') {
recursionDepth = recursionDepth === 3 ? 9 : 3;
tunnelRadius = Math.min(p.width, p.height) * (0.3 + recursionDepth * 0.015);
}
if (p.key === 'r' || p.key === 'R') {
time = 0;
spiralPhase = 0;
}
};
p.windowResized = function() {
var container = document.getElementById('p5-wrapper');
var w = container.offsetWidth;
var h = container.offsetHeight;
p.resizeCanvas(w, h);
tunnelRadius = Math.min(w, h) * 0.42;
pixelStep = Math.max(2, Math.floor(Math.min(w, h) / 400));
tunnelBuffer.resizeCanvas(w, h);
glowBuffer.resizeCanvas(w, h);
depthBuffer.resizeCanvas(w, h);
pixelBuffer.resizeCanvas(w, h);
initDepthMask(w, h);
};
};
✨ AI 艺术解读
This artwork simulates the dissolution of ego consciousness through recursive descent into an infinite fractal tunnel void. The domain-warped pixel rendering creates impossible geometric surfaces where boundaries blur and reform through recursive noise distortions. Multiple composited layers suggest the layered nature of psychedelic ego-death experiences, while the perpetual spiral descent represents consciousness engaging with infinite recursive depth. The restrained monochrome palette of deep violet-cyan with ethereal bloom evokes a transcendental, otherworldly void beyond ordinary perception.
📝 补充说明
- Domain warping is the core technique: sample noise at noise-warped coordinates, repeat 3 times for fractal complexity
- Pixel-level rendering with step size 2-4 balances performance and visual fidelity
- Use pixelDensity() when indexing pixels array for proper high-DPI display support
- Recursive depth controlled by spacebar toggle for different visual complexity modes
- Mouse influence creates center offset with smooth interpolation for subtle interaction