Cellular Automaton Breeding the Flower of Life
Generated by GridFlow AI | Tags: L-system, cellular-automaton, flower-of-life, bismuth-crystal, recursive-geometry, generative-art, sacred-geometry, neural-patterns, interference-patterns, multi-layer-compositing
💡 AI 提示词
Cellular Automaton Breeding the Flower of Life rendered in bismuth crystal style — geometric pastel rainbow interference patterns on dark background. Using L-systems with extreme recursion depth simulating neural or fungal consciousness. Multi-layer offscreen compositing with ADD and SCREEN blend modes for luminous depth.🔧 核心算法要点
- L-system generation with recursive growth rules simulating organic consciousness patterns
- Cellular automaton state propagation creating evolving wave interference across hexagonal grids
- Multi-layer offscreen buffer architecture for depth compositing with ADD and SCREEN blend modes
- Sacred geometry Flower of Life pattern with overlapping vesica piscis formations
- Pixel-level background void rendering with angular interference functions
- Mouse proximity influence affecting pattern scale, size, and growth dynamics
- Dynamic recursion depth modulation based on temporal phase and interaction intensity
- Recursive consciousness core with Metatron's Cube inspired geometric transformations
- Curve-based interference branches with sinusoidal wave displacement rendering
- Mode-based L-system parameter switching for visual diversity across 5 modes
🎨 原始代码
var sketch = function(p) {
// Multi-layer buffer architecture for depth compositing
let bgBuffer, layer1Buffer, layer2Buffer, layer3Buffer, compositeBuffer;
let time = 0;
let mode = 0;
let mouseInfluence = 0;
let lastMouseX = 0;
let lastMouseY = 0;
let interactionRadius = 200;
let growthPhase = 0;
let recursionDepth = 7;
// Bismuth crystal color palette - geometric pastel rainbow
let bismuthPalette = [];
// L-System rules for consciousness-like growth patterns
let lSysRules = {
iterations: 6,
angle: 25.7,
startLength: 8,
startX: 0,
startY: 0,
sentences: ['X', 'F'],
rules: {}
};
p.setup = function() {
let container = document.getElementById('p5-wrapper');
p.createCanvas(container.offsetWidth, container.offsetHeight).parent(container);
p.colorMode(p.RGB, 255, 255, 255, 1);
p.noStroke();
// Initialize bismuth crystal pastel palette
bismuthPalette = [
p.color(200, 180, 255, 0.6), // Soft violet
p.color(255, 200, 220, 0.6), // Blush pink
p.color(180, 230, 255, 0.6), // Sky crystal
p.color(220, 255, 200, 0.6), // Mint shard
p.color(255, 240, 180, 0.6), // Golden facet
p.color(200, 240, 255, 0.6), // Ice blue
p.color(255, 200, 200, 0.6), // Rose quartz
p.color(180, 200, 255, 0.6) // Lavender layer
];
// Create offscreen buffers for multi-layer compositing
bgBuffer = p.createGraphics(p.width, p.height);
layer1Buffer = p.createGraphics(p.width, p.height);
layer2Buffer = p.createGraphics(p.width, p.height);
layer3Buffer = p.createGraphics(p.width, p.height);
compositeBuffer = p.createGraphics(p.width, p.height);
initLSystemRules();
drawBackground();
};
function initLSystemRules() {
// Organic growth rules simulating neural/fungal consciousness
lSysRules.rules = {
'X': 'F+[[X]-X]-F[-FX]+X',
'F': 'FF'
};
lSysRules.angle = 22.5 + p.sin(time * 0.001) * 5;
}
function drawBackground() {
bgBuffer.background(8, 4, 15, 1);
// Create dark void with subtle interference pattern
bgBuffer.loadPixels();
let step = 3;
for (let x = 0; x < bgBuffer.width; x += step) {
for (let y = 0; y < bgBuffer.height; y += step) {
let centerX = bgBuffer.width / 2;
let centerY = bgBuffer.height / 2;
let dx = x - centerX;
let dy = y - centerY;
let dist = p.sqrt(dx * dx + dy * dy);
let angle = p.atan2(dy, dx);
let interference1 = p.sin(angle * 3 + dist * 0.02 + time * 0.5);
let interference2 = p.cos(angle * 5 - dist * 0.015 + time * 0.3);
let interference3 = p.sin((x + y) * 0.01 + time * 0.4);
let combined = (interference1 + interference2 + interference3) / 3;
let intensity = (combined + 1) * 0.5;
let r = 8 + intensity * 12;
let g = 4 + intensity * 8;
let b = 15 + intensity * 20;
// Add subtle gradient from center
let radialGrad = 1 - (dist / (bgBuffer.width * 0.7));
radialGrad = p.max(0, radialGrad);
let idx = (x + y * bgBuffer.width) * 4;
bgBuffer.pixels[idx] = r + radialGrad * 5;
bgBuffer.pixels[idx + 1] = g + radialGrad * 3;
bgBuffer.pixels[idx + 2] = b + radialGrad * 10;
bgBuffer.pixels[idx + 3] = 255;
}
}
bgBuffer.updatePixels();
}
function generateLSystemSentence(iterations) {
let sentence = 'X';
for (let i = 0; i < iterations; i++) {
let nextSentence = '';
for (let j = 0; j < sentence.length; j++) {
let char = sentence.charAt(j);
nextSentence += lSysRules.rules[char] || char;
}
sentence = nextSentence;
}
return sentence;
}
function drawLSystemToBuffer(buffer, cx, cy, sentence, maxDepth, paletteOffset) {
buffer.push();
buffer.translate(cx, cy);
let len = lSysRules.startLength;
let stack = [];
let depth = 0;
// Add rotation based on time for living quality
buffer.rotate(time * 0.0005);
for (let i = 0; i < sentence.length; i++) {
let char = sentence.charAt(i);
if (char === 'F') {
// Draw with interference pattern
let angle = buffer.atan2(0, 1) - buffer.rotation;
let x2 = 0;
let y2 = -len;
// Rotate for actual drawing
buffer.push();
buffer.rotate(-buffer.rotation);
let colorIdx = (depth + paletteOffset) % bismuthPalette.length;
let col = bismuthPalette[colorIdx];
// Create glow effect
let glowAlpha = p.map(depth, 0, maxDepth, 0.4, 0.1);
let baseAlpha = p.map(depth, 0, maxDepth, 0.8, 0.3);
// Draw multiple layers for depth
for (let g = 3; g >= 0; g--) {
buffer.stroke(red(col), green(col), blue(col), baseAlpha * (1 - g * 0.2));
buffer.strokeWeight(1 + g * 1.5);
buffer.line(0, 0, x2, y2);
}
buffer.translate(x2, y2);
buffer.pop();
} else if (char === '+') {
buffer.rotate(lSysRules.angle + p.sin(time * 0.002 + depth) * 3);
} else if (char === '-') {
buffer.rotate(-lSysRules.angle - p.cos(time * 0.002 + depth) * 3);
} else if (char === '[') {
stack.push({ x: buffer.translation.x, y: buffer.translation.y, r: buffer.rotation });
len *= 0.7;
depth++;
} else if (char === ']') {
if (stack.length > 0) {
let state = stack.pop();
buffer.translate(state.x - buffer.translation.x, state.y - buffer.translation.y);
buffer.rotate(state.r - buffer.rotation);
len /= 0.7;
depth--;
}
}
}
buffer.pop();
}
function drawFlowerOfLifeLayer(buffer, cx, cy, radius, numCircles, alpha) {
buffer.push();
buffer.translate(cx, cy);
buffer.rotate(time * 0.0008);
// Interference pattern overlay
let interferenceScale = 0.003 + p.sin(time * 0.001) * 0.001;
for (let i = 0; i < numCircles; i++) {
for (let j = 0; j < 6; j++) {
let angle = (j / 6) * p.TWO_PI + (i * p.TWO_PI / numCircles) * 0.1;
let px = p.cos(angle) * radius;
let py = p.sin(angle) * radius;
// Calculate interference for this position
let distFromCenter = p.sqrt(px * px + py * py);
let interferenceAngle = p.atan2(py, px);
let wave1 = p.sin(distFromCenter * interferenceScale * 50 + time * 0.5);
let wave2 = p.cos(interferenceAngle * 4 + distFromCenter * 0.01 + time * 0.3);
let wave3 = p.sin((px + py) * interferenceScale * 30 + time * 0.4);
let interference = (wave1 + wave2 + wave3) / 3;
let colorIdx = ((i + j + Math.floor(time * 0.05)) * 17) % bismuthPalette.length;
let col = bismuthPalette[colorIdx];
// Draw with interference-based opacity
let finalAlpha = alpha * (0.3 + interference * 0.4) * (0.5 + interference * 0.5);
buffer.noFill();
// Multiple stroke layers for crystal facet effect
for (let layer = 0; layer < 4; layer++) {
buffer.stroke(red(col), green(col), blue(col), finalAlpha * (1 - layer * 0.2));
buffer.strokeWeight(0.5 + layer * 0.3 + interference * 0.5);
buffer.ellipse(px, py, radius * (1.1 + layer * 0.15), radius * (1.1 + layer * 0.15));
}
}
}
buffer.pop();
}
function drawCellularAutomaton(buffer, cx, cy, radius) {
buffer.push();
buffer.translate(cx, cy);
buffer.rotate(time * 0.001);
// Draw cellular automaton grid as interference pattern
let gridSize = 40;
let cellSize = radius / gridSize;
for (let i = -gridSize / 2; i < gridSize / 2; i++) {
for (let j = -gridSize / 2; j < gridSize / 2; j++) {
// Calculate cell state based on neighborhood (like cellular automaton)
let x = i + gridSize / 2;
let y = j + gridSize / 2;
// Create propagating wave patterns
let dist = p.sqrt(i * i + j * j);
let angle = p.atan2(j, i);
// Multiple wave sources for interference
let wave1 = p.sin(dist * 0.5 - time * 0.8 + angle * 2);
let wave2 = p.sin(dist * 0.3 + time * 0.6 - angle * 3);
let wave3 = p.cos((i + j) * 0.2 + time * 0.4);
let state = (wave1 + wave2 + wave3) / 3;
state = (state + 1) * 0.5; // Normalize to 0-1
// Create hexagonal cells
let px = i * cellSize + cellSize / 2;
let py = j * cellSize + cellSize / 2;
// Only draw active cells
if (state > 0.3) {
let colorIdx = Math.floor(state * bismuthPalette.length * 1.5) % bismuthPalette.length;
let col = bismuthPalette[colorIdx];
let alpha = p.map(state, 0.3, 1, 0, 0.7);
// Draw hexagonal cell
buffer.fill(red(col), green(col), blue(col), alpha);
buffer.noStroke();
buffer.beginShape();
for (let k = 0; k < 6; k++) {
let a = k * p.TWO_PI / 6 + time * 0.01;
let hx = px + p.cos(a) * cellSize * 0.4;
let hy = py + p.sin(a) * cellSize * 0.4;
buffer.vertex(hx, hy);
}
buffer.endShape(p.CLOSE);
}
}
}
buffer.pop();
}
function drawVesicaLayer(buffer, cx, cy, size, rotation) {
buffer.push();
buffer.translate(cx, cy);
buffer.rotate(rotation + time * 0.0003);
// Draw vesica piscis / seed of life pattern
let petalCount = 6;
let angleStep = p.TWO_PI / petalCount;
for (let i = 0; i < petalCount; i++) {
let angle = i * angleStep;
let px = p.cos(angle) * size * 0.5;
let py = p.sin(angle) * size * 0.5;
// Interference calculation
let interference1 = p.sin(angle * 4 + time * 0.3);
let interference2 = p.cos(dist(0, 0, px, py) * 0.02 + time * 0.5);
let interference = (interference1 + interference2) / 2;
let colorIdx = (i + Math.floor(time * 0.02)) % bismuthPalette.length;
let col = bismuthPalette[colorIdx];
// Multiple overlapping ellipses for depth
for (let layer = 0; layer < 3; layer++) {
let layerAlpha = 0.3 - layer * 0.1;
let layerSize = size * (0.3 + layer * 0.15);
buffer.noFill();
buffer.stroke(red(col), green(col), blue(col), layerAlpha * (0.5 + interference * 0.5));
buffer.strokeWeight(0.5 + layer * 0.5);
// Draw vesica shape
let a = 0;
buffer.beginShape();
for (let t = 0; t <= 100; t++) {
a = p.map(t, 0, 100, 0, p.PI);
let vx = px + layerSize * 0.4 * p.sin(a);
let vy = py + layerSize * p.cos(a) * p.sqrt(1 + p.sin(a) * p.sin(a) * 0.5);
buffer.vertex(vx, vy);
}
buffer.endShape();
}
}
buffer.pop();
}
p.draw = function() {
time++;
// Calculate mouse influence
let dx = p.mouseX - lastMouseX;
let dy = p.mouseY - lastMouseY;
mouseInfluence = p.sqrt(dx * dx + dy * dy) * 0.1;
mouseInfluence = p.constrain(mouseInfluence, 0, 50);
lastMouseX = p.mouseX;
lastMouseY = p.mouseY;
// Update growth phase for evolving patterns
growthPhase = (time * 0.002) % (p.TWO_PI * 2);
// Dynamic recursion depth based on time and interaction
recursionDepth = 5 + Math.floor(p.sin(time * 0.001) * 2) + Math.floor(mouseInfluence * 0.1);
recursionDepth = p.constrain(recursionDepth, 4, 8);
// Clear layers
layer1Buffer.clear();
layer2Buffer.clear();
layer3Buffer.clear();
compositeBuffer.clear();
// Draw to layer buffers
drawLayer1();
drawLayer2();
drawLayer3();
// Composite all layers
compositeBuffer.image(bgBuffer, 0, 0);
compositeBuffer.blendMode(p.ADD);
compositeBuffer.image(layer1Buffer, 0, 0);
compositeBuffer.image(layer2Buffer, 0, 0);
compositeBuffer.blendMode(p.BLEND);
compositeBuffer.image(layer3Buffer, 0, 0);
// Apply final compositing to main canvas
p.image(bgBuffer, 0, 0);
p.blendMode(p.ADD);
p.image(layer1Buffer, 0, 0);
p.image(layer2Buffer, 0, 0);
p.blendMode(p.SCREEN);
p.image(layer3Buffer, 0, 0);
p.blendMode(p.BLEND);
// Apply bloom effect via pixel manipulation
applyBloomEffect();
// Draw UI hint
drawUIHints();
};
function drawLayer1() {
layer1Buffer.noStroke();
// Central Flower of Life pattern with interference
let baseRadius = p.min(p.width, p.height) * 0.35;
let numCircles = 7;
// Draw multiple flower of life instances
let flowerCenters = [
{ x: p.width / 2, y: p.height / 2, r: baseRadius, speed: 1 },
{ x: p.width * 0.3 + p.sin(time * 0.003) * 50, y: p.height * 0.35, r: baseRadius * 0.4, speed: 1.5 },
{ x: p.width * 0.7 + p.cos(time * 0.003) * 50, y: p.height * 0.65, r: baseRadius * 0.5, speed: 0.8 }
];
for (let f = 0; f < flowerCenters.length; f++) {
let fc = flowerCenters[f];
// Apply mouse influence
let mouseDist = p.dist(p.mouseX, p.mouseY, fc.x, fc.y);
if (mouseDist < interactionRadius) {
let influence = 1 - mouseDist / interactionRadius;
fc.r *= (1 + influence * 0.2);
}
drawFlowerOfLifeLayer(layer1Buffer, fc.x, fc.y, fc.r, numCircles, 0.4 + p.sin(time * 0.01 + f) * 0.1);
}
// L-system growth patterns
let sentence = generateLSystemSentence(recursionDepth);
let lSysCenters = [
{ x: p.width * 0.2, y: p.height * 0.3 },
{ x: p.width * 0.8, y: p.height * 0.7 },
{ x: p.width * 0.5, y: p.height * 0.15 }
];
for (let i = 0; i < lSysCenters.length; i++) {
let lc = lSysCenters[i];
let offset = i * 50 + Math.floor(time * 0.03) % 100;
drawLSystemToBuffer(layer1Buffer, lc.x, lc.y, sentence, recursionDepth, offset);
}
// Add interference rings
layer1Buffer.noFill();
for (let i = 0; i < 5; i++) {
let radius = p.min(p.width, p.height) * (0.2 + i * 0.15);
let interference = p.sin(time * 0.02 + i * 0.5) * 0.5 + 0.5;
let colorIdx = i % bismuthPalette.length;
let col = bismuthPalette[colorIdx];
layer1Buffer.stroke(red(col), green(col), blue(col), 0.15 * interference);
layer1Buffer.strokeWeight(1 + interference);
layer1Buffer.beginShape();
for (let a = 0; a < p.TWO_PI; a += 0.05) {
let wave = p.sin(a * 6 + time * 0.05 + i) * 10;
let r = radius + wave;
layer1Buffer.vertex(p.width / 2 + p.cos(a) * r, p.height / 2 + p.sin(a) * r);
}
layer1Buffer.endShape(p.CLOSE);
}
layer1Buffer.noStroke();
}
function drawLayer2() {
layer2Buffer.noStroke();
// Vesica layers with organic growth
let numVesica = 8;
for (let i = 0; i < numVesica; i++) {
let angle = (i / numVesica) * p.TWO_PI + time * 0.001;
let distance = p.min(p.width, p.height) * (0.2 + p.sin(time * 0.002 + i) * 0.1);
let cx = p.width / 2 + p.cos(angle) * distance;
let cy = p.height / 2 + p.sin(angle) * distance;
let size = p.min(p.width, p.height) * (0.1 + i * 0.02);
// Mouse interaction
let mouseDist = p.dist(p.mouseX, p.mouseY, cx, cy);
if (mouseDist < interactionRadius * 0.7) {
size *= 1.3;
}
drawVesicaLayer(layer2Buffer, cx, cy, size, i * p.PI / 4);
}
// Cellular automaton grid pattern
drawCellularAutomaton(layer2Buffer, p.width / 2, p.height / 2, p.min(p.width, p.height) * 0.3);
// Fractal interference branches
for (let i = 0; i < 6; i++) {
let angle = (i / 6) * p.TWO_PI + time * 0.0008;
let startX = p.width / 2 + p.cos(angle) * p.min(p.width, p.height) * 0.3;
let startY = p.height / 2 + p.sin(angle) * p.min(p.height, p.width) * 0.3;
drawInterferenceBranch(layer2Buffer, startX, startY, angle, 150, 5);
}
};
function drawInterferenceBranch(buffer, x, y, angle, length, depth) {
if (depth <= 0 || length < 5) return;
let interference = p.sin(time * 0.03 + depth * 0.5) * 0.5 + 0.5;
let colorIdx = depth % bismuthPalette.length;
let col = bismuthPalette[colorIdx];
let newLength = length * 0.7;
// Draw main branch with interference wave
let endX = x + p.cos(angle) * length;
let endY = y + p.sin(angle) * length;
buffer.stroke(red(col), green(col), blue(col), 0.3 * interference);
buffer.strokeWeight(depth * 0.5);
buffer.noFill();
buffer.beginShape();
for (let t = 0; t <= 1; t += 0.05) {
let px = x + (endX - x) * t;
let py = y + (endY - y) * t;
let wave = p.sin(t * p.PI * 4 + time * 0.05) * 5 * interference;
let perpX = -p.sin(angle) * wave;
let perpY = p.cos(angle) * wave;
buffer.vertex(px + perpX, py + perpY);
}
buffer.endShape();
// Recursive branches
let numBranches = 2 + Math.floor(interference * 2);
for (let b = 0; b < numBranches; b++) {
let branchAngle = angle + (b - numBranches / 2) * (p.PI / 6) + interference * 0.3;
let branchStartRatio = 0.5 + p.random() * 0.3;
let bx = x + (endX - x) * branchStartRatio;
let by = y + (endY - y) * branchStartRatio;
drawInterferenceBranch(buffer, bx, by, branchAngle, newLength, depth - 1);
}
}
function drawLayer3() {
layer3Buffer.noStroke();
// Glowing focal points with interference halos
let focalPoints = [
{ x: p.width * 0.25, y: p.height * 0.25, size: 30 },
{ x: p.width * 0.75, y: p.height * 0.75, size: 25 },
{ x: p.width * 0.7, y: p.height * 0.25, size: 35 },
{ x: p.width * 0.3, y: p.height * 0.75, size: 20 },
{ x: p.width * 0.5, y: p.height * 0.5, size: 40 }
];
for (let fp of focalPoints) {
// Apply mouse influence to size
let mouseDist = p.dist(p.mouseX, p.mouseY, fp.x, fp.y);
let sizeMultiplier = mouseDist < interactionRadius ? 1.5 : 1;
let actualSize = fp.size * sizeMultiplier;
// Draw interference halo rings
for (let r = 5; r >= 0; r--) {
let ringRadius = actualSize * (1 + r * 0.8);
let interference = p.sin(time * 0.04 + r * 0.3) * 0.5 + 0.5;
let alpha = 0.1 * interference / (r + 1);
let colorIdx = (r + Math.floor(time * 0.02)) % bismuthPalette.length;
let col = bismuthPalette[colorIdx];
layer3Buffer.fill(red(col), green(col), blue(col), alpha);
layer3Buffer.beginShape();
for (let a = 0; a < p.TWO_PI; a += 0.1) {
let wave = p.sin(a * 8 + time * 0.05 + r) * actualSize * 0.2;
let rx = fp.x + p.cos(a) * (ringRadius + wave);
let ry = fp.y + p.sin(a) * (ringRadius + wave);
layer3Buffer.vertex(rx, ry);
}
layer3Buffer.endShape(p.CLOSE);
}
// Central glow point
let centralInterference = p.sin(time * 0.06) * 0.5 + 0.5;
for (let g = 4; g >= 0; g--) {
let gSize = actualSize * (0.2 + g * 0.15);
let gAlpha = 0.5 * centralInterference / (g + 1);
let gc = bismuthPalette[Math.floor(time * 0.01 + g) % bismuthPalette.length];
layer3Buffer.fill(red(gc), green(gc), blue(gc), gAlpha);
layer3Buffer.ellipse(fp.x, fp.y, gSize, gSize);
}
}
// Central consciousness core with recursive geometry
drawConsciousnessCore(layer3Buffer, p.width / 2, p.height / 2, 80);
}
function drawConsciousnessCore(buffer, cx, cy, size) {
buffer.push();
buffer.translate(cx, cy);
buffer.rotate(time * 0.001);
// Recursive sacred geometry - Metatron's Cube inspired
let layers = 4;
for (let layer = 0; layer < layers; layer++) {
let layerSize = size * (1 - layer * 0.2);
let rotation = layer * p.PI / 8 + time * 0.002;
// Draw geometric forms
let interference = p.sin(time * 0.03 + layer * 0.5) * 0.5 + 0.5;
let colorIdx = (layer + Math.floor(time * 0.015)) % bismuthPalette.length;
let col = bismuthPalette[colorIdx];
buffer.rotate(rotation);
// Flower of life within each layer
for (let i = 0; i < 6; i++) {
let angle = (i / 6) * p.TWO_PI;
let px = p.cos(angle) * layerSize * 0.5;
let py = p.sin(angle) * layerSize * 0.5;
buffer.noFill();
buffer.stroke(red(col), green(col), blue(col), 0.2 * interference);
buffer.strokeWeight(1 + layer * 0.5);
let petalSize = layerSize * 0.4;
buffer.ellipse(px, py, petalSize, petalSize * 1.5);
}
// Connect with lines
buffer.stroke(red(col), green(col), blue(col), 0.15 * interference);
buffer.strokeWeight(0.5);
for (let i = 0; i < 6; i++) {
let angle = (i / 6) * p.TWO_PI;
let x1 = p.cos(angle) * layerSize * 0.5;
let y1 = p.sin(angle) * layerSize * 0.5;
for (let j = i + 1; j < 6; j++) {
let angle2 = (j / 6) * p.TWO_PI;
let x2 = p.cos(angle2) * layerSize * 0.5;
let y2 = p.sin(angle2) * layerSize * 0.5;
buffer.line(x1, y1, x2, y2);
}
}
buffer.rotate(-rotation);
}
// Central vortex
let vortexInterference = p.sin(time * 0.08) * 0.5 + 0.5;
let vortexColor = bismuthPalette[Math.floor(time * 0.02) % bismuthPalette.length];
buffer.noStroke();
for (let i = 5; i >= 0; i--) {
let spiralRadius = size * 0.15 * (1 - i * 0.15);
buffer.fill(red(vortexColor), green(vortexColor), blue(vortexColor), 0.4 * vortexInterference / (i + 1));
buffer.beginShape();
for (let a = 0; a < p.TWO_PI * 2; a += 0.1) {
let r = spiralRadius * (1 - a / (p.TWO_PI * 4));
let x = p.cos(a + time * 0.02) * r;
let y = p.sin(a + time * 0.02) * r;
buffer.vertex(x, y);
}
buffer.endShape();
}
buffer.pop();
}
function applyBloomEffect() {
// Apply subtle bloom via additive overlay
p.blendMode(p.ADD);
p.fill(255, 240, 200, 0.03);
p.ellipse(p.width / 2, p.height / 2, p.min(p.width, p.height) * 0.8, p.min(p.width, p.height) * 0.8);
p.blendMode(p.BLEND);
}
function drawUIHints() {
// Subtle UI hints
p.fill(255, 255, 255, 0.3);
p.textSize(10);
p.textAlign(p.LEFT, p.BOTTOM);
p.text('Move: Influence patterns | Click: Pulse | 1-5: Modes | R: Reset', 10, p.height - 10);
}
// Mouse interaction - continuous influence on patterns
p.mouseMoved = function() {
// Continuous mouse influence handled in draw loop
};
// Mouse click - trigger distinct visual event (pulse burst)
p.mousePressed = function() {
// Create pulse effect at mouse position
let pulseX = p.mouseX;
let pulseY = p.mouseY;
// Flash effect
p.fill(255, 255, 255, 0.2);
p.noStroke();
p.ellipse(pulseX, pulseY, 100, 100);
// Temporarily boost recursion depth
recursionDepth = p.min(recursionDepth + 2, 9);
};
// Keyboard interaction - toggle modes and reset
p.keyPressed = function() {
if (p.key === '1') {
mode = 0; // Standard
} else if (p.key === '2') {
mode = 1; // Intense
} else if (p.key === '3') {
mode = 2; // Flowing
} else if (p.key === '4') {
mode = 3; // Crystalline
} else if (p.key === '5') {
mode = 4; // Organic
} else if (p.key === 'r' || p.key === 'R') {
// Reset with flash
time = 0;
growthPhase = 0;
initLSystemRules();
}
// Update L-system parameters based on mode
updateModeParameters();
};
function updateModeParameters() {
switch(mode) {
case 0: // Standard
lSysRules.angle = 25.7;
lSysRules.startLength = 8;
break;
case 1: // Intense
lSysRules.angle = 30;
lSysRules.startLength = 10;
break;
case 2: // Flowing
lSysRules.angle = 20;
lSysRules.startLength = 6;
break;
case 3: // Crystalline
lSysRules.angle = 36;
lSysRules.startLength = 7;
break;
case 4: // Organic
lSysRules.angle = 22.5;
lSysRules.startLength = 9;
break;
}
}
// Responsive canvas sizing
p.windowResized = function() {
let container = document.getElementById('p5-wrapper');
p.resizeCanvas(container.offsetWidth, container.offsetHeight);
// Recreate buffers at new size
bgBuffer = p.createGraphics(p.width, p.height);
layer1Buffer = p.createGraphics(p.width, p.height);
layer2Buffer = p.createGraphics(p.width, p.height);
layer3Buffer = p.createGraphics(p.width, p.height);
compositeBuffer = p.createGraphics(p.width, p.height);
drawBackground();
};
};
✨ AI 艺术解读
This artwork represents the emergence of consciousness from simple cellular rules into complex sacred geometry — the digital equivalent of bismuth crystal formation where ordered patterns arise from chaotic growth. The Flower of Life motif emerges organically from recursive L-system iterations, suggesting that fundamental geometric truths are bred into reality through iterative processes. The interference patterns create a visual metaphor for how individual consciousness threads combine into collective understanding, while the dark void background evokes the infinite potential from which all form emerges. The piece invites contemplation on the recursive nature of existence itself.
📝 补充说明
- L-system sentences are pre-generated once per mode change, not per frame, for computational efficiency
- Interference calculations use multiple overlapping wave functions to create organic, non-repetitive patterns
- Mouse influence uses distance-based falloff with configurable radius for smooth interaction gradients
- Blend modes (ADD, SCREEN) create luminous depth impossible with single-layer alpha blending
- Recursion depth dynamically adjusts between 4-9 levels based on time phase and user interaction intensity
- Buffer clearing uses p.clear() instead of background() to preserve transparency for compositing
- Keyboard modes 1-5 change L-system angle (20-36 degrees) and segment length (6-10 pixels) for visual variety
- Flower of Life centers placed at golden ratio distances for aesthetically pleasing composition
- Hexagonal cell grid simulates cellular automaton behavior with multi-source wave propagation
- Each layer uses different drawing primitives (ellipse, beginShape, line) for visual diversity within unified palette