5b – Noise

random(), randomSeed(), noise(), noiseSeed()

Random

Using random() within a for structure is an easy way to generate random numbers.

random

background(0);
stroke(255, 60);
for (int i = 0; i < 100; i++) {
  float r = random(10);
  strokeWeight(r);
  float offset = r * 5.0;
  line(i-20, 100, i+offset, 0);
}

Perlin Noise

The noise() function is a more controllable way to create unexpected values. 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 random(). The noise function has 1-3 parameters.

The noise function returns a number between 0-1.

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

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

So we need to vary the Perlin noise variable slightly to get a unpredictable appearance. In the following example 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.

float n=0; //noise variable
float inc=0.01; //noise variable increase
int x=0; //x coordinate of line
 
void setup() {
  size(500, 100);
}
 
void draw() {
  float y = noise(n)*100; //generate noise value which will give us the y coordinate
  println(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:

void draw() {
  for (int x=0; x<;width; x=x+1) {
      float y = noise((n+x)/50)*100; //generate noise value
      println(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.

float 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
 
float n=0.1;
float inc = 1;
 
 
void setup() {
  size(500, 100);
}
void draw() {
  background(255);
 
  // drawMountain(2,0.2);
  for (int x=0; x<width; x=x+1) {
    float y = noise((n+x)/50)*100; //generate noise value
  //remember that noise generate values from (0,1) so that the 
  //above function will then produce values from 0-100 (which is our y axis)
 
    println(y); //lets check what it is so that we stay sane
    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
}

Exercises:

  • How can you 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.
float xnoise = 0.0;
float ynoise = 0.0;
float inc = 0.05;
 
void setup() {
  size(200, 200);
  for (int y = 0; y < height; y++) {
    //for a value of y
    for (int 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
  }
}
 
void draw() {
}

Exercises:

  • What happens when you move the for loop to void draw?
  • How could you use this in a composition by placing images or objects in the foreground?