Noisy Foam - Bubble Emergence
Generated by GridFlow AI | Tags: perlin-noise, bubble-simulation, emergent-behavior, fluid-dynamics, generative-art, noise-field, soft-body-physics
💡 AI 提示词
Perlin noise driven bubble dynamics where foam-like bubbles interact through soft-body physics and respond to evolving noise fields, creating emergent patterns and iridescent visual effects🔧 核心算法要点
- Initialize array of bubble objects with position, velocity, and unique noise phase offsets
- Sample 2D Perlin noise field to generate directional force vectors influencing bubble movement
- Apply soft-body attraction physics when bubbles approach within minimum distance threshold
- Update bubble positions based on accumulated acceleration from noise field and neighbor interactions
- Render bubbles with HSB color cycling based on noise values, trailing lines, and specular highlights
- Evolve noise offsets over time to create dynamic, non-repeating movement patterns
🎨 原始代码
var sketch = function(p) {
var bubbles = [];
var numBubbles = 60;
var noiseScale = 0.003;
var timeOffset = 0;
var container;
var Bubble = function(x, y, r) {
this.pos = p.createVector(x, y);
this.vel = p.createVector(p.random(-1, 1), p.random(-1, 1));
this.acc = p.createVector(0, 0);
this.radius = r;
this.phase = p.random(1000);
this.noiseOffsetX = p.random(1000);
this.noiseOffsetY = p.random(1000);
this.trail = [];
};
Bubble.prototype.update = function() {
var n1 = p.noise(this.pos.x * noiseScale + this.noiseOffsetX, this.pos.y * noiseScale, timeOffset);
var n2 = p.noise(this.pos.x * noiseScale + this.noiseOffsetX + 100, this.pos.y * noiseScale + this.noiseOffsetY, timeOffset + 50);
var angle = n1 * p.TWO_PI * 4;
var magnitude = n2 * 0.8;
var force = p5.Vector.fromAngle(angle).mult(magnitude);
this.acc.add(force);
this.vel.add(this.acc);
this.vel.limit(3);
this.pos.add(this.vel);
this.acc.mult(0);
this.trail.push(this.pos.copy());
if (this.trail.length > 15) {
this.trail.shift();
}
if (this.pos.x < 0) this.pos.x = p.width;
if (this.pos.x > p.width) this.pos.x = 0;
if (this.pos.y < 0) this.pos.y = p.height;
if (this.pos.y > p.height) this.pos.y = 0;
};
Bubble.prototype.attract = function(other) {
var dir = p5.Vector.sub(this.pos, other.pos);
var d = dir.mag();
var minDist = this.radius + other.radius + 20;
if (d < minDist && d > 0) {
var strength = (minDist - d) * 0.02;
dir.normalize().mult(strength);
this.acc.add(dir);
other.acc.sub(dir);
}
};
Bubble.prototype.display = function() {
var n = p.noise(this.phase + timeOffset * 0.5);
var hue = (n * 360 + timeOffset * 20) % 360;
var alphaVal = p.map(n, 0, 1, 80, 180);
p.stroke(hue, 80, 100, alphaVal);
p.strokeWeight(1.5);
for (var i = 0; i < this.trail.length; i++) {
var alpha = (i / this.trail.length) * alphaVal * 0.5;
p.stroke(hue, 70, 90, alpha);
p.line(this.trail[i].x, this.trail[i].y, this.pos.x, this.pos.y);
}
var shimmer = p.noise(this.pos.x * 0.01, this.pos.y * 0.01, timeOffset * 2) * 30 - 15;
p.noFill();
p.ellipse(this.pos.x, this.pos.y, this.radius * 2 + shimmer, this.radius * 2 + shimmer);
var r = this.radius * 0.3;
var highlightAngle = p.noise(timeOffset + this.phase) * p.TWO_PI;
var hx = this.pos.x + p.cos(highlightAngle) * r * 0.4;
var hy = this.pos.y + p.sin(highlightAngle) * r * 0.4;
p.fill(hue, 30, 100, 60);
p.noStroke();
p.ellipse(hx, hy, 4, 4);
};
p.setup = function() {
container = document.getElementById('p5-wrapper');
p.createCanvas(container.offsetWidth, container.offsetHeight).parent(container);
p.colorMode(p.HSB, 360, 100, 100, 255);
p.background(0, 0, 10);
for (var i = 0; i < numBubbles; i++) {
var r = p.random(10, 40);
var x = p.random(p.width);
var y = p.random(p.height);
bubbles.push(new Bubble(x, y, r));
}
};
p.draw = function() {
p.background(0, 0, 10, 25);
timeOffset += 0.008;
for (var i = 0; i < bubbles.length; i++) {
for (var j = i + 1; j < bubbles.length; j++) {
bubbles[i].attract(bubbles[j]);
}
}
for (var i = 0; i < bubbles.length; i++) {
bubbles[i].update();
bubbles[i].display();
}
};
p.windowResized = function() {
p.resizeCanvas(container.offsetWidth, container.offsetHeight);
};
};
✨ AI 艺术解读
This piece explores the emergent beauty of foam dynamics governed by noise-driven forces. Each bubble responds to an invisible Perlin noise field while simultaneously interacting with its neighbors through soft attraction forces, creating organic clustering and separation patterns. The iridescent color shifts and trailing movements evoke underwater foam or cosmic nebulae, suggesting the boundary between order and chaos in natural systems.
📝 补充说明
- Perlin noise creates smooth, organic movement unlike random or linear forces
- Soft-body collision produces emergent clustering without hard constraints
- HSB color mode enables easy rainbow cycling with noise-based hue mapping
- Trail rendering adds temporal depth showing recent movement history
- Time-evolving noise offsets prevent repetitive patterns and maintain visual interest