Electric Deep - Perlin Lightning Root System
Generated by GridFlow AI | Tags: perlin-noise, lightning, root-system, branching, emergence, electric, organic, generative
💡 AI 提示词
A generative art piece depicting a lightning-like root system growing downward from the top of the canvas, using Perlin noise to create organic, unpredictable branching patterns. The system features multiple depth levels with varying thicknesses and hues, electric particle effects, and a glowing trail aesthetic.🔧 核心算法要点
- Perlin noise field influences branch growth direction by mapping noise values to angular offsets
- Branches spawn child branches at decreasing thickness ratios (0.65x) creating natural taper
- Lightning jitter effect: random angular impulses that decay exponentially over time
- Depth-based hue progression shifts from cyan toward magenta as branches extend
- Particle emission from branch tips adds electric field visualization
- Glow buffer graphics combined with trail effect creates luminous lightning aesthetic
- Continuous root regeneration maintains visual density of the growing system
🎨 原始代码
var sketch = function(p) {
var branches = [];
var particles = [];
var noiseScale = 0.008;
var time = 0;
var glowGraphics;
var Branch = function(x, y, angle, depth) {
this.pos = p.createVector(x, y);
this.prevPos = this.pos.copy();
this.angle = angle;
this.vel = p.createVector(0, 0);
this.life = 0;
this.maxLife = p.random(300, 600);
this.thickness = p.random(4, 10);
this.depth = depth;
this.noiseOffset = p.random(1000);
this.hue = 200 + depth * 15 + p.random(-20, 20);
this.saturation = 70 + p.random(30);
this.brightness = 90 + p.random(10);
this.branchChance = 0.015;
this.jitter = 0;
};
Branch.prototype.update = function() {
this.prevPos = this.pos.copy();
var noiseVal = p.noise(
this.pos.x * noiseScale + this.noiseOffset,
this.pos.y * noiseScale,
time * 0.008
);
var targetAngle = this.angle + p.map(noiseVal, 0, 1, -0.6, 0.6);
// Lightning jitter effect
if (p.random() < 0.05) {
this.jitter = p.random(-0.4, 0.4);
}
this.jitter *= 0.9;
targetAngle += this.jitter;
this.angle = targetAngle;
this.vel.x = p.cos(this.angle);
this.vel.y = p.sin(this.angle);
var speed = p.map(this.depth, 0, 10, 3, 1.2);
this.pos.x += this.vel.x * speed;
this.pos.y += this.vel.y * speed;
this.life++;
// Spawn child branches
if (this.depth < 8 && p.random() < this.branchChance) {
var branchAngle = this.angle + p.random(-0.7, 0.7);
var branch = new Branch(this.pos.x, this.pos.y, branchAngle, this.depth + 1);
branch.thickness = this.thickness * 0.65;
branch.maxLife = this.maxLife * 0.6;
branch.branchChance = this.branchChance * 0.85;
branches.push(branch);
}
// Spawn particles
if (p.random() < 0.08) {
particles.push({
pos: this.pos.copy(),
vel: p5.Vector.random2D().mult(p.random(0.5, 2.5)),
life: p.random(15, 45),
maxLife: 45,
hue: this.hue + p.random(-10, 10)
});
}
};
Branch.prototype.display = function(gfx) {
var lifeRatio = this.life / this.maxLife;
var alpha = p.map(lifeRatio, 0, 1, 100, 15);
var thickness = this.thickness * (1 - lifeRatio * 0.4);
gfx.stroke(this.hue, this.saturation, this.brightness, alpha);
gfx.strokeWeight(p.max(0.5, thickness));
gfx.line(this.prevPos.x, this.prevPos.y, this.pos.x, this.pos.y);
};
p.setup = function() {
var container = document.getElementById('p5-wrapper');
p.createCanvas(container.offsetWidth, container.offsetHeight).parent(container);
p.colorMode(p.HSB, 360, 100, 100, 100);
p.background(0);
glowGraphics = p.createGraphics(p.width, p.height);
glowGraphics.colorMode(p.HSB, 360, 100, 100, 100);
// Initialize multiple root sources
var rootCount = 4 + Math.floor(p.random(4));
for (var i = 0; i < rootCount; i++) {
var x = p.random(p.width * 0.15, p.width * 0.85);
var angle = p.PI / 2 + p.random(-0.4, 0.4);
branches.push(new Branch(x, -20, angle, 0));
}
};
p.draw = function() {
// Create depth with slight trail
p.fill(0, 0, 5, 35);
p.noStroke();
p.rect(0, 0, p.width, p.height);
time += 0.015;
// Clear glow buffer with trail effect
glowGraphics.fill(0, 0, 5, 30);
glowGraphics.noStroke();
glowGraphics.rect(0, 0, glowGraphics.width, glowGraphics.height);
// Update and display branches to glow buffer
for (var i = branches.length - 1; i >= 0; i--) {
var branch = branches[i];
branch.update();
branch.display(glowGraphics);
// Remove dead or escaped branches
if (branch.life > branch.maxLife ||
branch.pos.y > p.height + 100 ||
branch.pos.x < -100 ||
branch.pos.x > p.width + 100) {
branches.splice(i, 1);
}
}
// Update particles
for (var i = particles.length - 1; i >= 0; i--) {
var part = particles[i];
part.pos.add(part.vel);
part.vel.mult(0.92);
part.life--;
var alpha = p.map(part.life, 0, part.maxLife, 0, 80);
glowGraphics.stroke(part.hue, 100, 100, alpha);
glowGraphics.strokeWeight(2);
glowGraphics.point(part.pos.x, part.pos.y);
if (part.life <= 0) {
particles.splice(i, 1);
}
}
// Apply glow effect
p.image(glowGraphics, 0, 0);
// Add occasional lightning flash
if (p.random() < 0.003) {
p.fill(60, 20, 100, 15);
p.noStroke();
p.rect(0, 0, p.width, p.height);
}
// Spawn new roots to maintain density
if (branches.length < 150 && p.random() < 0.04) {
var x = p.random(p.width * 0.1, p.width * 0.9);
var angle = p.PI / 2 + p.random(-0.3, 0.3);
branches.push(new Branch(x, -15, angle, 0));
}
};
p.windowResized = function() {
var container = document.getElementById('p5-wrapper');
p.resizeCanvas(container.offsetWidth, container.offsetHeight);
glowGraphics.resizeCanvas(p.width, p.height);
p.background(0);
glowGraphics.background(0);
};
};
// p5 init stripped
✨ AI 艺术解读
This piece explores the tension between order and chaos in natural systems. The downward growth mimics both lightning seeking ground and root systems seeking water, yet the Perlin noise creates an unpredictability that feels genuinely organic rather than mechanical. The electric blue-to-magenta palette evokes the cold beauty of electrical discharge while the glowing trails suggest energy lingering in space. It is a meditation on how simple rules generate complex, living-looking structures.
📝 补充说明
- The glow effect uses a secondary graphics buffer with reduced opacity trails for performance
- Perlin noise offset per branch ensures varied behavior even at same position
- Lightning jitter uses exponential decay (multiply by 0.9) for natural-feeling impulse response
- Maximum branch depth of 8 prevents excessive computational load while maintaining visual complexity
- Random lightning flashes at low probability (0.3%) add occasional dramatic moments