minimalism
p5js
20 lines of code

20 lines of code

written by cino

06 Sep 2022277 EDITIONS
No active listing

I started working on this piece to free my mind from my upcoming fxhash project, which is spiralling in complexity. I needed a break, wanted to work for a while on something simple, and so I came out with the idea of making a generative algorithm as small as possible, while still maintaining the capacity to create visually interesting outputs with a good enough amount of variety.

I was able to reduce the script to 20 lines, conceptually even less since a few are just closed parentheses or interactions with fxhash. I used P5.js, as usual, and chose to focus on two aspects: color (mostly) and composition (just a bit).

function setup() {
  colorMode(HSL);
  randomSeed(fxrand()*9999999999999);
  noStroke();
  createCanvas(min(windowWidth, windowHeight), min(windowWidth, windowHeight));
  let u=width/(random(50,300));
  let h = random(0,360);
  let n = random(0.62,0.98);
  let a = random();  
  for (let y=-height*1.2;y<height;y+=u*random()) {
    for (let x=-width*1.2;x<width;x+=u*random()) {
      let s = random()<n ? abs(abs((map(x,0,width,-100,100)))-100) : random(0,100);
      let l = random()<n ? map(y,0,height,90,10) : map(y,0,height,20,90);
      fill(color(h,s,l,random(a,1)));
      let newy = random()<n ? y : y-u*random(1,5);
      rect(x,newy,u*random(1,5),height);
    }
  }
  fxpreview();
}

Color

I chose to work with a single hue (color shade) , varying its saturation and lightness based on the distance from the center of the canvas. Going up, lightness would increase, while going down it would decrease, and going either left or right would reduce saturation. I think this gives the effect of a distant light, like a sun, in the middle of the canvas.

Composition

I used a simple grid composition, iterating through the canvas vertically and then horizontally, and drawing a rectangle at each step.

Randomness

There's no generative art without randomness, because all outputs would be identical. In this case I chose to randomize the hue, the size of each rectangle on the grid, and to introduce a chance for the rectangle to be higher than the rest, or of inverted color: maintaining the same hue, it would be darker going up from the center and vice versa, as well as more saturated to the sides and greyer in the center, in contrast with the majority of the other rectangles.

The 20 lines explained

function setup() {

Here i just call p5js setup function to initialize the script.

colorMode(HSL);

I switch the color mode from RGB (pretty unusable for me) to HSL (I also sometimes use HSB).

randomSeed(fxrand()*9999999999999);

I define the random seed using fxhash's function based on transaction hashes

noStroke();

I don't want my rectangles to have a border.

createCanvas(min(windowWidth, windowHeight), min(windowWidth, windowHeight));

Here I create a canvas based on the window dimensions, so it can maintain its quality at any resolution. I used the shortest between width and height to avoid stretching and overflow at different ratios.

let u=width/(random(50,300));

I define u, my unit of measure, as a fraction of the canvas width. I randomize it from 1/50 to 1/300, to have varied outputs: some with bigger rectangles, some with smaller ones.

possibilities not included: u = width/10
possibilities not included: u=width/1000 (takes forever to render)
let h = random(0,360);

Here I define the random hue (color shade) of the piece.

let n = random(0.62,0.98);

Here I set the "noise": the probability, for each rectangle that I will draw, that it may have an opposite saturation, lightness, or height than the others. A lower value will result in a more uniform piece, an higher one in a more noisy one. The minimum and maximum values of 0.62 and 0.98 have been chosen after a process of trial and error.

Possibilities not included: no noise (n=1)
Possibilities not included: extreme noise (n=0.5)
let a = random();

This variable sets the minimum alpha value of the rectangles: the lower it is, the more transparent they can be.

for (let y=-height*1.2;y<height;y+=u*random()) {

Then I start my loop. I begin by iterating through the vertical axis, following steps that are varying based on the u value I defined earlier. Here there is also a bug: I start iterating from above the higher edge of the canvas, to avoid the risk of blank spaces at the top, and that's correct, but I should have started from 20% above (-height*0.2) instead of 120% (-height*1.2), thus saving resources.

for (let x=-width*1.2;x<width;x+=u*random()) {

Same as above - bug included :( -, but through the x axis.

let s = random()<n ? abs(abs((map(x,0,width,-100,100)))-100) : random(0,100);

This is a ternary operator that I use to define the saturation of the rectangle drawn at the intersection of each x and y values. Basically it says: is a random number smaller than the "noise" value I defined earlier? If so, draw the rectangle with the standard saturation (higher closer to the center, lower towards the sides); if not, use use a random saturation value.

Media not found
Possibilities not included: saturation decreases towards the center
let l = random()<n ? map(y,0,height,90,10) : map(y,0,height,20,90);

Similar as above, but for the lightness. If the random number is smaller than the noise value, the rectangle will follow the standard rule: lighter towards the top, darker towards the bottom. If it exceeds the noise value, it will instead do the opposite.

fill(color(h,s,l,random(a,1)));

Here I give instructions to fill the rectangle with the defined hue, saturation and lightness values chosen. The alpha (transparency) will be picked at random in a range between the minimum alpha value defined earlier and 1, which is full opacity.

let newy = random()<n ? y : y-u*random(1,5);

Ternary operator to define exceptions to the rectangle height: if the random number exceeds the noise value, it will be 1 to 5 times higher than normal. This operation is not needed for the width, because the iteration goes through y values first and x values last.

Media not found
Possibilities not included: all rectangles the same height
rect(x,newy,u*random(1,5),height);

I finally draw the rectangle!

}

I close the x loop

}

I close the y loop

fxpreview();

I tell fxhash to take the screenshot for the preview

}

The end. Thanks for reading!

project name project name project name

feedback

stay ahead with our newsletter

receive news on exclusive drops, releases, product updates, and more