Perlin Noise

Perlin Noise
All examples are done in p5js

The noise() function is a controllable way to create a series of values that have some randomness. It uses the Perlin Noise technique, developed by Ken Perlin. Originally used for simulating natural textures through subtle irregularities, Perlin Noise is now also used for generating shapes and realistic motion. It works by interpolating between random values to create smoother transitions than the numbers returned from the random() function. The noise function has 1-3 parameters.

The noise function ALWAYS returns a number between 0-1. And it is generally used repeatedly to give a series of unpredicable values.

Putting the same parameter into the noise function, will generate the same number out. You can see this by running the following:

function draw(){
 println(noise (1)); 
}

So we need to vary the Perlin noise variable slightly to get a unpredictable appearance. In the following example we draw this pattern by drawing a vertical line at each value of x. The upper y value of each line is generated using Perlin noise which is why it has that lovely natural appearance. You can see that instead of putting the same number into noise each time, we increase the noise variable n, by inc which is 0.01 for every line drawn. Change inc (the variable holding the amount we are changing our variable) to see how the resultant noise changes.

var n=0; //noise variable
var inc=0.01; //noise variable increase
var x=0; //x coordinate of line
 
function setup() {
  createCanvas(500, 100);
}
 
function draw() {
  var y = noise(n)*100; //generate noise value which will give us the y coordinate
  print(y); //lets check what it is
  line(x, height, x, y); //draw a line at x that goes from bottom of screen to y value
  x++; //move to next x value
  n=n+inc; //increase our noise variable to get new y
}

But if we want our landscape to move, we have to shift every line left or right to give the appearance of motion. This means we have to generate all the values for our mountain scape for every loop of draw. So we use a for-loop to give us x values from 0-width for every loop of draw. So take the example above and introduce a for loop where we iterate through x.
So void draw becomes:

function draw() {
  for (var x=0; x<width; x=x+1) {
      var y = noise((n+x)/50)*100; //generate noise value
      print(y); //lets check what it is
      line(x, height, x, y); //draw a line at x that goes from bottom of screen to y value
    }
  n=n+inc; //increase our noise variable
}

Now notice that the line x++ as also been deleted. This is because we are now getting our x values using the for loop and we don’t need to increase manually using draw.

Also notice that the following line now has a few more things going on in it.

var y = noise((n+x)/50)*100; //generate noise value

This is because we need to generate a slightly new noise variable for each value of x of the for loop, if we dont put x into the noise variable, we will get a straight line (the same value of noise for the whole for loop, all values of x). Instead, as the for loop gives the full range of x values, we can add each one to the noise variable n for each loop. This will mean our noise will vary across x. We then have to divide by 50 to reduce the value of (n+x) so our noise pattern isn’t too variable. If you divide by a higher number than 50 (ie. making the noise parameter smaller) the noise variation will reduce and your landscape will get smoother, a lower number and your mountains will get choppier.

You also have to refresh background() at the top of draw.

So here is the result and the code all put together below:

//Perlin Landscape
 
var n=0.1;
 
 
function setup() {
  createCanvas(500, 100);
}
function draw() {
  background(255);
 
  // drawMountain(2,0.2);
  for (var x=0; x<width; x=x+1) {
      var p=(x+n)/50; //calculate noise variable for each x 
      var y = noise(p); //generate noise value
      //remember that noise generate values from (0,1) so that the 
      //above function will then produce values from 0-1 (which we can multiply by height)
 
       print(y); //lets check what it is so that we stay sane
      line(x, height, x, y*height); //draw a line at x that goes from bottom of screen to y value
 
 }
 n++; //increase our noise variable
}
  • Can you take the above code and change the speed of the landscape? (hint it is moving by the amount you increase the noise variable each time)
  • How can you use the same for loop and add in another set of mountains? (can you make them move at a different speed)

Two dimensional Perlin Noise

This means we can get gradual natural looking variation in 2 directions, both in x and y direction.

Screen Shot 2015-02-23 at 5.58.45 PM

//Two Dimensional Perlin Noise
//From Processing. A Programming Handbook. Chapter Math 4: Random.
var xnoise = 0.0;
var ynoise = 0.0;
var inc = 0.05;
 
function setup() {
  createCanvas(200, 200);
  for (var y = 0; y< height; y++) {
    //for a value of y
    for (var x = 0; x< width; x++) { //loop through x (horizontal)
 
      float gray = noise(xnoise, ynoise) * 255; //generate a gray value
      println(gray);
      stroke(gray); //make stroke that value
      point(x, y); //draw point
      xnoise = xnoise + inc;  //increase x value for noise
    }
    // when we need a new y value
    xnoise = 0; //set x back to zero
    ynoise = ynoise + inc; //get a new y noise value
  }
}
 
function draw() {
}