Come on! Feel the noise! Part 2

Come on! Feel the noise! Part 2

This guide is for beginners who want to master noise() and learn how to apply it effectively. In part 1, I explained the character of noise() and made some still images. In this part 2, we will challenge to make some animation with noise().



Note:
I only explain the noise() function in Processing and p5.js.
The example codes in this article are written in Processing. And I linked to the OpenProcessing for codes of the p5.js versions. Most code snippets in this article are released under the CC0 license, but please note that the featured artworks (full examples) are licensed under the GPL. Feel free to use the snippets for learning, but respect the GPL for the larger works.

[Japanese version / 日本語版はこちら]

 

Let me show you how can I enjoy creative coding with noise() in Processing and p5.js and let's dive into creative coding with noise() together! 😀

 

The Dimension of Time

In 1D, 2D, or 3D noise, the D stands for dimension—but you don't have to think of them strictly as lines, planes, or volumes.

For example:

      fill(noise(i * j * 0.01) * 360.0, 80.0, 90.0, 100.0);

This 1D noise creates plane surface looks.

An image that was created with 1D noise.

In this example, The 2D noise creates one-dimensional lines.

      float y = noise(i, j) * 100 + j * h;
Some lines that was drawn with 2D noise.

You can see that i means line length and j means line number.

Let's see this line number, top to bottom, as the past to the future.


This is the animation with noise()!
Now, you can see that j means time. The second dimension now represents time. This shift in perspective is the secret to smooth animation.

 

Creating a 2D Noise Animation

Let's turn the still image from Part 1 into an animation.

A still image that was drawn with 1D noise.

In the previous example, we used 1D noise like this:

noise(i * j * 0.01)

To animate this, we add a second dimension to represent time, effectively turning our 1D noise into 2D noise:

noise(i * j * 0.01, t) // 't' means time

You can define t as frameCount number.

  float t = frameCount;

Animations in Processing/p5.js work much like a flipbook. So the animation smoothness depends on frames per second (fps). We can specify the fps with frameRate();
Now, we specify 10 fps. Do not forget to comment out the noLoop().

  // noLoop();
  frameRate(10);

Here is the code. I made the matrix size larger to be able to see the moving well.


/**
 * Come on! Feel the noise! Part 2
 * Animation : With the same parameter absolute value.
 * 
 * @author @deconbatch
 * @version 0.1
 * @license CC0 1.0 https://creativecommons.org/publicdomain/zero/1.0/deed.ja
 * Processing 3.5.3
 * 2020.11.07
 */

void setup() {
  size(640, 480);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  //  noLoop();
  frameRate(10);
  
  background(0.0, 0.0, 90.0, 100.0);
  stroke(0.0, 0.0, 0.0, 100.0);
  strokeWeight(1.0);
}

void draw() {
  int div = 20;
  float w = width * 0.5 / div;
  float h = height * 0.5 / div;

  float t = frameCount;
  
  translate(width * 0.5, height * 0.5);
  for (int i = -div; i < div; i++) {
    for (int j = -div; j < div; j++) {
      float x = i * w;
      float y = j * h;
      fill(noise(i * j * 0.01, t) * 360.0, 80.0, 90.0, 100.0);
      rect(x, y, w, h);
    }
  }
}


View the p5.js version on OpenProcessing

 

Let's run!


Oops! It's too jerky! 😖

Then? Yes! We should make the change rate of a parameter smaller. It's jerky along time. So let's make the change rate of t the time dimension smaller.

  float t = frameCount * 0.05;


Yes! Much smoother! With a little extra flavor, it looks great!


 

Let Make an Animation with 3D Noise.

Next, let's try to animate the still image that we made it with 2D noise in part 1.

An image that was drawn with 2D noise.

In the same way, we can add the time dimension to the 2D noise and make it to the 3D noise.

    let s = noise(x * 0.005, y * 0.005, t);

 

Here is the moving example. I changed the rectangles to the circle.



/**
 * Come on! Feel the noise! Part 2
 * Animation : THIS IS THE 2D NOISE!
 * 
 * @author @deconbatch
 * @version 0.1
 * @license CC0 1.0 https://creativecommons.org/publicdomain/zero/1.0/deed.ja
 * Processing 3.5.3
 * 2020.11.07
 */

void setup() {
  size(640, 480);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  //  noLoop();
  frameRate(10);

  background(0.0, 0.0, 90.0, 100.0);
  fill(220.0, 90.0, 60.0, 100.0);
  stroke(40.0, 60.0, 90.0, 100.0);
  strokeWeight(5.0);
}

void draw() {
  int divX = 16;
  int divY = 12;
  float w = width  / divX;
  float h = height / divY;

  float t = frameCount * 0.05;

  translate(w * 0.5, h * 0.5);
  for (int i = 0; i < divX; i++) {
    float x = i * w;
    for (int j = 0; j < divY; j++) {
      float y = j * h;
      float s = noise(x * 0.005, y * 0.005, t);
      ellipse(x, y, s * w, s * h);
    }
  }
}


View the p5.js version on OpenProcessing

 

You may have got a hang of it. Then we'll try to make some animation with a new idea.

At first, we make something like this with 1D noise.

The curve that was made with many circles.

Placing circles side by side.

A line that was made with many circles.

Changing angle with noise one by one. The parameter of 1D noise is the number of circles. Then, it becomes a smooth curve.

A smooth curve that was made with 1D noise.

Next, we draw many lines.

Many lines with 1D noise.

If we used 1D noise, all the lines are the same curve. So, we add the number of lines to the 2nd parameter of noise.
With this 2D noise, the lines will be like this.

Many lines with 2D noise.

Finally, we add the time dimension. The creepy animation complete!
How creeeeeeeepy! 😱


/**
 * Come on! Feel the noise! Part 2
 * Animation : Creepy one...
 * 
 * @author @deconbatch
 * @version 0.1
 * @license CC0 1.0 https://creativecommons.org/publicdomain/zero/1.0/deed.ja
 * Processing 3.5.3
 * 2020.11.07
 */

void setup() {
  size(640, 480);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  frameRate(24);

  fill(220.0, 90.0, 60.0, 100.0);
  stroke(40.0, 60.0, 90.0, 100.0);
  strokeWeight(5.0);
}

void draw() {
  int lines = 5;
  int steps = 16;
  float w = min(width, height) * 0.5 / steps;
  float t = frameCount * 0.01;

  background(0.0, 0.0, 90.0, 100.0);
  translate(width * 0.5, height * 0.5);
  for (int l = 0; l < lines; l++) {
    rotate(TWO_PI / lines);
    pushMatrix();
    for (int s = 0; s < steps; s++) {
      float theta = map(noise(l, s * 0.1, t), 0.0, 1.0, -0.5, 0.5) * PI;
      translate(0.0, w);
      rotate(theta);
      ellipse(0.0, 0.0, w, w);
    }
    popMatrix();
  }
}


View the p5.js version on OpenProcessing

 

Here is the 3D noise. l means lines, s means circles, and t means the time. I multiply s by 0.1 to make the curve smooth. I left l coarse on purpose to getdistinct noise values for each line.

float theta = map(noise(l, s * 0.1, t), 0.0, 1.0, -0.5, 0.5) * PI;

I said "You do not necessarily associate with the line, the plane surface, and the solid shape" before. This animation is a good example of it I think.

It is fun to see how this animation changes its look by trying to change the change rate of a parameter.
Can you spot which part of the code I changed? 🤔


 

Going Beyond Three Dimensions

We can easily animate a 2D image by adding a third parameter for time. But what happens if our still image already uses 3D noise?

The noise() function in Processing and p5.js is limited to three parameters. Since we can't add a 4th dimension, we have to get creative.

noise() \ Language (API) \ Processing 3+
noise() | reference | p5.js

At first, we'll make a still image with 3D noise like this. It's just like layers of 2D noise still image we made in part 1. The number of layers is the 3rd parameter of the noise().

Let's lay over the red, green, and blue layers.

The red layer that was drawn with 2D noise.
The green layer that was drawn with 2D noise.
The blue layer that was drawn with 2D noise.
Three layers that was drawn with 2D noise.

Here is the code. I wrote this code for animation, but it does not move yet that because I did not apply the time dimension to the noise().


/**
 * Come on! Feel the noise! Part 2
 * Animation : The layers with 2D noise.
 * 
 * @author @deconbatch
 * @version 0.1
 * @license CC0 1.0 https://creativecommons.org/publicdomain/zero/1.0/deed.ja
 * Processing 3.5.3
 * 2020.11.07
 */

void setup() {
  size(640, 480);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  frameRate(24);

  noStroke();
}

void draw() {
  int divX = 40;
  int divY = 30;
  int divZ = 3;
  float w = width  / divX;
  float h = height / divY;
  float t = frameCount * 0.02;

  background(0.0, 0.0, 90.0, 100.0);
  translate(w * 0.5, h * 0.5);
  for (int z = 0; z < divZ; z++) {
    fill(z * 360.0 / divZ, 60.0, 80.0, 100.0);
    for (int i = 0; i < divX; i++) {
      float x = i * w;
      for (int j = 0; j < divY; j++) {
        float y = j * h;
        float s = noise(x * 0.005, y * 0.005, z);
        if (s < 0.5) {
          ellipse(x, y, s * w * 2.0, s * h * 2.0);
        }
      }
    }
  }
}



View the p5.js version on OpenProcessing

 

The noise() has three parameters. So we can not add any.

        float s = noise(x * 0.005, y * 0.005, z);

So, how we can add the element of time? Let me try to add to the first parameter.

noise(x * 0.005 + t, y * 0.005, z);

Ummm. It's changing along the time, but it just looks scrolling. x + t means increasing x but not time passing.

The second parameter (y) will be the same result. So, we can move it up and down, left and right, and obliquely.


We can make the creepy animation synchronized something.


I got sidetracked. 😅

How about this for dimension lack problem?

noise(x, y, z + t)

Oh! It looks good!

It's scrolling on the z-axis, so the plane surface looks changing with 2D noise. You can imagine that you are pulling a plane surface in three-dimensional noise space.

This trick works for 2D planes because the shifting noise looks like organic change. However, for 3D objects, simply offsetting the Z-axis (z + t) will look like the entire shape is just sliding through space, rather than truly morphing.

Ideally, we want to use noise(x, y, z) to define the shape and use 't' independently as a fourth dimension for time.

Maybe this?

noise(noise(x, y, z), t)

Ummmmmmm! It does not look like scrolling, but it is awkward moving. noise(x, y, z) returns fix value and do not change along the time, so this cause this wooden movement?

Then, how about this?

noise(noise(x, y, t), z)

We should go more further? Adding t even more to the outside noise!

noise(noise(x, y, t), z, t)

...Now, I can't make out what it's all about.

To tell the truth, I have no good idea about this. It's enough with noise(x, y, z + t) for this example. I think a suitable answer will differ depending on one's purpose.

We used nested noise() this time. And using some other function may be worth considering.

noise(func(x, y, z), t)

Another option would be to implement 4-dimensional noise yourself. If you had some ideas, please let me know.

 

The noise() Tips

A Substitution for an Array of Random Values

One of the noise() features is noise() returns the same value for identical input parameters.

And if you specify the change rate of a parameter big, noise() returns almost random values. So, you can use noise() as an array of random values when you treat a noise() parameter as an array's index. However, keep in mind that this consumes more CPU cycles than pre-generating an array.

 

Want the Same Set of Noise Values

noise() returns different results for each execution. So you'll get a different set of noise values for each execution of your code.

It will be fun to see the different image drawing for each execution. But when you are tuning the parameters to polish your works, the same set of noise values will suit your purpose.

You can use noiseSeed() in this situation.

noiseSeed() \ Language (API) \ Processing 3+
noiseSeed() | reference | p5.js


You can get the same set of noise values every execution if you specified like this.

noiseSeed(0);

And when you change the parameter of noiseSeed(), you can change the set of noise values.

 

Want More Dynamic Changing Values

You'll see the set of return values of noise() sometimes changes widely and sometimes changes narrow.

A line that was drawn with noise()
A line that was drawn with noise()

If you want to get widely changing values like from 0.0 to 1.0, you can normalize with the min/max value of noise(). Though, you should treat the problem that it tends to cause jerky changing.

 

Want to Get Cyclic Noise Values

Sometimes you will want to get cyclic noise values. Not like this:

Not noise values like this.

But like this:

The cyclic noise values like this.

One of the answers is using parameters of tracks of a circle in 2D noise. (Sorry, it is written in Japanese.)

 

Mind the Repeated Results

noise() has the character that it returns repeated results in the case of long-range values of the parameters.

It's a pattern that was drawn with 2D noise.

noise(x, y);

It looks normal.


But when I double the area?


You can see the repeated pattern. You don't have to worry about this in many cases. But you had better mind when you make a big scale image.

 

Fun Time! Let's Make Some Animations with Noise().

Let's make an animation with your code that makes a still image in Come on! Feel the noise! part 1.

If you had no idea, how about making an animation that draws a moving point with 1D noise? Or how about to draw a circle that changes it's size with 1D noise, and increase that circle and changes these size with 2D noise? It will be fun when you clear with background() before every drawing, and it will be fun also when you do not clear at all.

And these tweet of mine are various example works with noise(). Please use it as reference.


Thank you for reading! Enjoy your creative coding with noise()! 😀👍

Next Post Previous Post
No Comment
Add Comment
comment url