Perlin Noise

So far, we've been often using randomness in our compositions, but you might have noticed that the results are often quite "choppy". This is particularly obvious in the very last image we generated as part of the second tutorial, the circle with added randomness. The top and bottom look a bit smoother, mainly because many lines are overlapping, but as we go towards the center, we start noticing more sharp corners.

2021.11.10-19.55.08-0-675505.png

What if we wanted to insert randomness into our drawings, but somehow make the results smoother? And by smoother I mean avoiding transitions between values at the opposite ends of the random range we're working with, and therefore remove some corners / jumps in our end results. This is where noise comes in.

Perlin Noise

As mentioned in our previous tutorial, good pseudo-random numbers should follow a certain, uniform distribution, and not be related to each other. However, patterns and processes found in the real world are rarely independent in that way – they often evolve over time, based on their previous state. Think of measuring the temperature in a specific place, over the course of a few hours. The temperature at time 0 is going to be very close (but not exactly identical) to the temperature 5 minutes in. An hour later, things might have shifted by a few degrees, but in a way that is continuous and smooth. Another analogy that's helpful to think about are terrains & landscapes. Valleys, hills and mountains all "flow" into each other, continuously, while still keeping elements of chance.

Simulating such processes can be done using regular pseudo-random generators, but things can get tricky fast. Fortunately, the Perlin Noise was created for this exact reason: the ability to more accurately (from a visual point of view, rather than scientific) simulate natural processes / textures / patterns / etc. If we think of generating random numbers over time, regular random functions will simply create numbers that are not related to each other. A Perlin noise function will make sure that two numbers that are generated one after the other are also close in value.

Note 1: This is a very high-level and non-technical explanation of Perlin Noise, bound in many ways by my understanding of it. Dan Shiffman from the Coding Train has, as usual, a great explanation of what's going on.

Note 2: The canvas-sketch library technically uses a different type of noise, which is called Simplex Noise. It is an updated version of the same algorithm, developed by the same author (Ken Perlin.)

Let's take a look at some of a differences between randomness and noise. To that end, we're simply going to "plot" the results of a random function, and the results of a noise function, by drawing line across the page and altering their Y coordinate with random or noise values.

const paths = [];

// In this piece of code, we are drawing a line from left to right on the screen.
// This line will be made of many small segments, each with a length of stepX (1 milimeter in this case)
let stepX = 0.1
// The Y coordinate of the line is constant: in this case, we are drawing it at 1/5th of the screen
let lineY = height / 5
// We create our path and move its head to the beginning of the line, an x coordinate of 0 (left-most column on the page), and the y we've created.
let p = createPath()
p.moveTo(0, lineY)
// Moving in small increments, we draw the segments that make up the line
for (let x = 0; x <= width; x += stepX) {
  // At each step, we alter the constant Y coordinate with a random value between 1 and -1.
  let randomY = lineY + Random.range(-1, 1)
  p.lineTo(x, randomY)
}

This should produce a result similar to the one below:

2021.11.17-19.16.34-0-325916.png