AI Flow Field - Perlin Noise Particle Trails Mesmerizing generative art using Perlin noise flow fie

56 views ยท Dec 16, 2025

Create a Perlin Noise Flow Field visualization! Generate a grid of flow vectors using noise(). Draw

#xelsedia#xelsedai#xelsedp5flashalpha6
๐Ÿ”€ Remix This ๐Ÿ“– View Docs โ›ถ Full Screen โ† Back to Gallery
๐Ÿ“‹ Embed Code

Copy this code to embed this sketch on your website:

<iframe src="https://p5js.ai/embed/417ae9b6-5566-420d-92dc-aae031198dd7" width="400" height="400" frameborder="0" allow="autoplay" title="AI Flow Field - Perlin Noise Particle Trails Mesmerizing generative art using Perlin noise flow fie"></iframe>

Adjust width and height as needed. Preview embed โ†’

โ“ About This Sketch 3 questions

What visual effect does the AI Flow Field sketch create?

The AI Flow Field sketch generates mesmerizing particle trails that flow and evolve over time, using Perlin noise to create a dynamic and organic visual experience.

Is there any way for users to interact with the AI Flow Field sketch?

The sketch is primarily passive, but users can resize their browser window to adjust the canvas size, allowing for different visual perspectives.

What creative coding technique is showcased in this sketch?

This sketch demonstrates the use of Perlin noise to create a flow field that influences particle movement, showcasing the concept of generative art through algorithmic design.

๐Ÿ’ฌ AI Chat History 2 messages
๐Ÿ‘ค You
Create a Perlin Noise Flow Field visualization! Generate a grid of flow vectors using noise(). Draw thousands of particles that follow the flow field, leaving colorful trails. Use HSB color mode where hue shifts based on particle position. Dark background. Click to regenerate noise seed. Mesmerizing organic movement patterns. Advanced generative art technique!
๐Ÿค– AI
This is a fantastic idea for a generative art sketch! A Perlin Noise Flow Field with thousands of particles creates truly mesmerizing and organic movement patterns.

Here's the complete code for your project, including the necessary p5.js CDN in `index.html` and a `Particle` class to manage the individual moving elements.

---

### `index.html`

First, we need to ensure p5.js is loaded in your HTML file. The current `index.html` is missing the p5.js script.

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Perlin Noise Flow Field</title>
<link rel="stylesheet" href="style.css">
<!-- Load p5.js library -->
<script src="https://cdn.jsdelivr.net/npm/p5@1.11.3/lib/p5.min.js"></script>
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
```

### `style.css`

Your current `style.css` is perfect for this sketch. It removes default margins and ensures the canvas takes up the full browser window without scrollbars.

```css
body {
margin: 0;
padding: 0;
overflow: hidden;
}

canvas {
display: block; /* Removes default canvas margin */
}
```

### `sketch.js`

This file contains the core logic for generating the flow field and animating the particles.

```js
// --- Global Variables ---
let particles = []; // Array to store all Particle objects
let numParticles = 2000; // Number of particles to draw
let noiseScale = 0.01; // Controls the "zoom" or granularity of the noise field
let flowStrength = 4; // How strongly particles are influenced by the flow field
let noiseOffset = 0; // Offset for the noise function to make the field evolve over time
let noiseStep = 0.005; // How much noiseOffset increases each frame

// --- Setup Function ---
function setup() {
createCanvas(windowWidth, windowHeight); // Create a canvas that fills the browser window
colorMode(HSB, 255); // Use HSB color mode for easier hue manipulation
background(0); // Initial dark background

// Optional: Adjust noise detail for different patterns
// noiseDetail(4); // Default is 8, lower values are smoother, higher values are more detailed

// Initialize particles
for (let i = 0; i < numParticles; i++) {
particles.push(new Particle());
}

// Set an initial random noise seed for a unique pattern
noiseSeed(random(10000));
}

// --- Draw Function ---
function draw() {
// Draw a semi-transparent dark background to create fading trails
// The alpha value (10) controls the length of the trails
background(0, 10);

// Update noiseOffset to make the flow field gradually change over time
noiseOffset += noiseStep;

// Update and display each particle
for (let particle of particles) {
particle.update();
particle.show();
}
}

// --- Particle Class ---
class Particle {
constructor() {
// Random initial position within the canvas
this.pos = createVector(random(width), random(height));
this.vel = createVector(0, 0); // Initial velocity
this.acc = createVector(0, 0); // Initial acceleration
this.maxSpeed = 4; // Maximum speed of the particle
}

update() {
// Calculate the noise value at the particle's current position
// We add noiseOffset to the x and y coordinates to make the noise field evolve
let angle = noise(
this.pos.x * noiseScale + noiseOffset,
this.pos.y * noiseScale + noiseOffset
);

// Map the noise value (0 to 1) to a full circle (0 to 2ฯ€ radians)
angle = map(angle, 0, 1, 0, TWO_PI);

// Create a force vector based on the angle
let force = p5.Vector.fromAngle(angle);

// Scale the force by the flowStrength
force.mult(flowStrength);

// Apply the force to the particle's acceleration
this.acc.add(force);

// Update velocity and position
this.vel.add(this.acc);
this.vel.limit(this.maxSpeed); // Limit the velocity to prevent particles from moving too fast
this.pos.add(this.vel);

// Reset acceleration for the next frame
this.acc.mult(0);

// Wrap particles around the canvas edges
if (this.pos.x > width) this.pos.x = 0;
if (this.pos.x < 0) this.pos.x = width;
if (this.pos.y > height) this.pos.y = 0;
if (this.pos.y < 0) this.pos.y = height;
}

show() {
// Set stroke weight and color
strokeWeight(1);
noFill();

// Map the particle's x position to a hue value (0-255)
// This creates the colorful trails
let hue = map(this.pos.x, 0, width, 0, 255);
// Set stroke color with hue, high saturation, high brightness, and semi-transparent alpha
stroke(hue, 200, 255, 100);

// Draw a short line segment in the direction of the particle's velocity
// This creates a more visible trail than just a point
line(this.pos.x, this.pos.y, this.pos.x - this.vel.x, this.pos.y - this.vel.y);
}
}

// --- Interaction: Regenerate noise on mouse press ---
function mousePressed() {
// Generate a new random seed for the Perlin noise function
noiseSeed(random(10000));
noiseOffset = 0; // Reset noise offset so the new pattern starts fresh
background(0); // Clear the canvas to start new trails

// Reinitialize particles with random positions for a completely new start
particles = [];
for (let i = 0; i < numParticles; i++) {
particles.push(new Particle());
}
}

// --- Responsive Canvas ---
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
background(0); // Clear canvas on resize
noiseOffset = 0; // Reset noise offset
// Optionally reinitialize particles or let them adapt
particles = [];
for (let i = 0; i < numParticles; i++) {
particles.push(new Particle());
}
}
```

### Explanation:

1. **`index.html` Update:** The most crucial change is adding the p5.js library script (`<script src="https://cdn.jsdelivr.net/npm/p5@1.11.3/lib/p5.min.js"></script>`) before your `sketch.js` file. This makes all p5.js functions available.
2. **Global Variables:**
* `particles`: An array to hold all the `Particle` objects.
* `numParticles`: Defines how many particles are in the simulation.
* `noiseScale`: Controls the "zoom" of the Perlin noise. A smaller value creates larger, smoother patterns, while a larger value creates more turbulent, detailed patterns.
* `flowStrength`: Determines how much the particles are pushed by the flow field. Higher values make particles move faster and follow the field more aggressively.
* `noiseOffset`, `noiseStep`: These variables make the flow field *evolve* over time. By adding `noiseOffset` to the `x` and `y` coordinates when sampling the noise, the entire field appears to shift and change, creating dynamic movement.
3. **`setup()` Function:**
* `createCanvas(windowWidth, windowHeight);`: Creates a canvas that fills the browser window.
* `colorMode(HSB, 255);`: Switches p5.js to Hue, Saturation, Brightness color mode. This is ideal for shifting colors based on a single value (like particle position). Hue ranges from 0-255, Saturation 0-255, Brightness 0-255, and Alpha (optional) 0-255.
* `noiseSeed(random(10000));`: Sets a random seed for the Perlin noise function. This ensures you get a different, unique pattern every time the sketch starts or when you click.
* The loop populates the `particles` array with new `Particle` objects.
4. **`draw()` Function:**
* `background(0, 10);`: This is the key for the colorful trails. It draws a black background *with a low alpha value* (10 out of 255). This makes the previous frames slowly fade out, creating the trail effect.
* `noiseOffset += noiseStep;`: Increments the noise offset, causing the flow field to animate.
* The loop iterates through each `particle`, calling its `update()` method (to move it) and `show()` method (to draw it).
5. **`Particle` Class:**
* **`constructor()`:** Initializes a particle with a random position, zero velocity, zero acceleration, and a maximum speed.
* **`update()`:**
* Calculates the Perlin noise value at the particle's current position, incorporating `noiseOffset` for animation.
* `map(angle, 0, 1, 0, TWO_PI);`: Converts the noise value (which is between 0 and 1) into an angle in radians (0 to 360 degrees). This angle dictates the direction of the flow at that point.
* `p5.Vector.fromAngle(angle);`: Creates a vector pointing in the direction of the calculated angle.
* `force.mult(flowStrength);`: Scales this direction vector by `flowStrength` to determine how much the particle is pushed.
* The particle's acceleration, velocity, and position are updated based on this force, following standard physics principles.
* `this.vel.limit(this.maxSpeed);`: Prevents particles from accelerating indefinitely.
* The edge wrapping logic (`if (this.pos.x > width) this.pos.x = 0;` etc.) ensures particles that leave one side of the canvas reappear on the opposite side, maintaining a continuous flow.
* **`show()`:**
* `strokeWeight(1); noFill();`: Sets a thin stroke and no fill for the particles.
* `let hue = map(this.pos.x, 0, width, 0, 255);`: This is where the color magic happens! The particle's `x` position across the canvas is mapped directly to the `hue` value. Particles on the left will have one hue, and particles on the right will have another, creating a beautiful gradient.
* `stroke(hue, 200, 255, 100);`: Draws the stroke with the calculated hue, high saturation, high brightness, and a semi-transparent alpha.
* `line(this.pos.x, this.pos.y, this.pos.x - this.vel.x, this.pos.y - this.vel.y);`: Instead of just drawing a point, we draw a short line segment from the particle's current position back along its velocity vector. This makes the trails more visible and gives a sense of movement direction.
6. **`mousePressed()` Function:**
* When you click the mouse, a new random `noiseSeed()` is generated, `noiseOffset` is reset, the background is cleared, and all particles are reinitialized. This gives you a fresh, new flow field pattern with each click.
7. **`windowResized()` Function:**
* Ensures the canvas resizes if the browser window changes, maintaining responsiveness. It also clears the background and reinitializes particles for a clean look.

This sketch provides a solid foundation for a Perlin Noise Flow Field. You can experiment with the global variables (`noiseScale`, `flowStrength`, `numParticles`, `noiseStep`, `maxSpeed`) to achieve different artistic effects!
๐ŸŽฌ Video Preview