Journey into Generative Art: Follow the Algorithm

“Creativity itself doesn’t care at all about results — the only thing it craves is the process.” — Elizabeth Gilbert

Creating generative art is a tango between the rough boundaries you’ve established and the decisions of the algorithm. At the onset, I rarely have a rigid plan for what I’m going to make. I may know my starting point, but often the ending is a mystery.

In my previous post on generative art, I talked about my creative motivations and the theory of flow fields.

In this post, I’ll shed light on my creative process and illustrate the power of incremental change. I’ll showcase how an algorithm evolves as you feed its impulses, producing lovely abstract art.

Making a Grid

Building off the principles I learned from creating flow fields, I started by creating a grid for my canvas. This helps me keep an easy frame of reference as to where points will be placed in the coordinate system.

First I split the canvas into an evenly spaced-out grid, drawing a dot in each cell.

Journey into Generative Art: Follow the Algorithm Where It Takes You
Grid of white dots

Surprisingly this is one of my favorite pieces I’ve made. I wasn’t expecting it to be an optical illusion and so difficult to look at which is cool.

This is what the code looks like:

let points = [];
let density = 25;

function setup() {
    createCanvas(windowWidth, windowHeight);
    background(30);
    let space = width / density;

    for (let x = 0; x < width; x += space) {
        for (let y = 0; y < height; y += space) {
            let p = createVector(x, y);
            points.push(p);
        }
    }
}

function draw() {
    noStroke();

    for (let i = 0; i < 1000; i++) {
        let angle = createVector(points[i].x, points[i].y);
        points[i].add(angle);
        stroke('white')
        ellipse(points[i].x, points[i].y, 10);
    }
}

In setup(), I create the aforementioned grid and iteratively step through it creating a vector that we push onto our array of points.

Then in draw(), I iterate through each of our points drawing an ellipse.

Adding Chaos to the Algorithm

From here I thought to myself, "It’s time to add some chaos to the mix."

More often than not when introducing randomness to your algorithms, you’ll want to use randomGaussian(). This allows you to use Gaussian distribution, so the numbers will be random but still slightly correlated.

For our ellipses, we originally used a width and height of 10. Instead, we are going to use the randomGuassian function to modulate the size of each ellipse.

// In setup
let p = createVector(x + randomGaussian(-10, 10), y + randomGaussian(-8, 8));

// In draw
ellipse(points[i].x, points[i].y, randomGaussian(40,25), randomGaussian(40, 10));


Looks cooler already, let’s see what happens when we only draw the outlines of each ellipse.

Journey into Generative Art: Follow the Algorithm Where It Takes You
This also turned out to be pretty cool looking but not really the direction I was looking for. So, I quickly reverted my changes and started playing with color.

Playing with Color

In order to control the randomization of color, I prefer using HSB (Hue, Saturation, Brightness) color mode provided by the p5 library.

By keeping the saturation and brightness levels relatively consistent, I am able to simply increment the hue within a controlled range. This allows you to use random colors that aren’t wildly different from each other, creating a much more pleasing aesthetic.

Note: Wide range for hue values and no alpha

Title: Green vs Blue
Journey into Generative Art: Follow the Algorithm Where It Takes You
Title: Nerdz

Final Thoughts

With this post, I wanted to showcase how an algorithm can grow, or, evolve as you dance. With patience and a curious mind, a simple idea can snowball into beautiful creations.

When creating generative art, I find it important to relinquish some control and follow wherever the algorithm takes you.