Hello hello!
This time - using noise for motion.
One “solution” to the cloud-like motion exercise in p5.js from the end of last week’s post is simply adding time as a third argument to the noise
function:
noise(SCALE*i, SCALE*j, 0.0005*millis());
millis()
is a function provided by p5.js that gives us the number of milliseconds since the code started running, and we multiply it by a very small value so that the animation moves smoothly. To understand why and how this works, let’s analyze a more direct visualization of what the output of noise
looks like in 1, 2, and 3 dimensions.
A lot of different functions in the creative coding world return a “normalized” output between 0 and 1, and noise
is no different. By default, p5.js uses a range from 0-255 for colours (I’ll get into why that is in a future post), and so we can convert the output to a grayscale value by multiplying the returned value by 255 (0 black, 255 white, any values in between will be some grey).
Now that we’ve got a clearly defined way of visualizing the value, we can sample the function at a whole lot of points and draw each of these points using the colour from our method above. Because of how noise
calculates its outputs, I’ll be using the three argument version for all of these examples to ensure that it remains consistent between them.
Repeatedly incrementing x by small values and getting the output of noise(x, 0, 0)
produces a line with a smoothly changing gradient. Doing the same on both the x and y axis via noise(x, y, 0)
produces a square with a cloudy or smoky effect. You’ll notice that the line created with noise(x, 0, 0)
looks identical to the top row of the square, which makes sense because that top row is where y=0 and is therefore equivalent to noise(x, 0, 0)
. It’s a bit harder to visualize this next step in 3D, so we’ll do noise(x, y, z)
and step through a few values of z, showing the square as we did for the 2D case with just x and y. You can see that the gradients change subtly over the course of the three frames - you can think of each of these frames as “slices” at each labelled z-coordinate of a cube. Similar to the comparison between the line and the first square, the first “frame” with z=0 is exactly the same as the square for the pure 2D case noise(x, y, 0)
.
With that, I’ve shown you one way of visualizing a small region of the Perlin noise field. This was done under the pretense that I wanted to map spatial dimensions to each component of the function. However, there’s no reason that it needs to be used this way.
As in the cloud example from the beginning of this post and the end of the previous post, we can substitute time for the third argument (or any one, really) and then constantly redraw the result to get some interesting organic motion. We also don’t need to be visualizing the noise field directly at all in a grid-like spatial context. I use noise
for all sorts of things, so here’s a few examples:


And some pointers (t
in any of the points below will be a variable representing a scaled time value, such as 0.0001*millis())
:
If you just want a single smoothly changing organic value over time,
noise(t)
is all you need.Using an offset of the form
noise(i + t)
can be a cool way to get a “cascading” effect across multiple values in a loop, since larger values ofi
in an animation context will be sampling “in the future” in comparison to smaller values ofi
at the same time value (all of the animations above except for the fish are examples of this).While
noise
can only produce smooth gradients in 3 dimensions, you can still use it for an arbitrary number of outputs so long as they don’t need to be smooth relative to one anotherFor example, if I wanted to get some values to rotate a cube along the x, y, and z axes while also changing its size and grayscale colour, I’d need 5 different values that change smoothly. I consider it to be ideal if none of these values follow the same patterns over time to emphasize their independence and create the effect of organic motion. Therefore, I only need to use the 2D version of
noise
since all we’re looking for are an assortment of smooth values in 1D - we use the second dimension simply as an offset to separate the “lines” that we’re sampling from (refer back to the first diagram if this is confusing - think of it as looking at rows in the 2D square that are far apart).x = noise(t, 0)
,y = noise(t, 10)
,z = noise(t, 20)
, etc.
The value of
noise
at any given point doesn’t need to be used directly nor independently - add, subtract, or multiply its value with other values or mathematical functions to produce interesting results.
Harkening back to the exercise in 1 - “A Blank Canvas” where I really tried to drive home the point of getting very specific with describing things, consider how you might describe the image/motion of the following using noise
(specifically, what variables could be driven or augmented by the output of noise
):
A mountain range
A tree blowing in the wind
An eyeball looking around a room
Code for some of the animations earlier in the post is available here.
Have a nice week!
Happening Things
Pals of mine have some exhibitions on at InterAccess Gallery in Toronto, Canada this week for a very limited time!
Magpie Online by Christina Dovolis - May 22-23 11am-6pm, May 24 10am-5pm
MOVES by Tara Morris - May 24, 10am-5pm
Weekly quote:
“Make something beautiful
and it will kick away and
outlive the trouble from
which it was created.”
Album of the week: “The Joy of Motion” (2014) by Animals As Leaders
If you have any feedback or questions about this or any other post (or just want to say hi!), I’m always happy to chat. Thank you for taking the time to read!