Placeholder Image

Subtitles section Play video

  • (bell dings)

  • - Hello, and welcome to a Coding Challenge.

  • Woof! (gasps)

  • If you can't tell, I'm really excited about this one,

  • so I found this GIF the other day by Etienne Jacob,

  • Etienne Jacob with my American pronunciation,

  • and look at it.

  • It might look familiar to you.

  • It looks like that heart curve

  • that I made in a Coding Challenge previously.

  • Now, I can't say for sure whether this GIF was made

  • based on my heart curve Coding Challenge,

  • but I can say for sure that the work of Etienne

  • is amazing, and phenomenal, and uses a special technique,

  • one that I have recently rediscovered in a dream.

  • It came to me in a dream, (giggles)

  • and yet it's been on the Internet at least since 2017,

  • if not before that,

  • so what's going on here that's so fabulous and exciting

  • is this chaotic scene,

  • this scene of randomness and smoky heart beauty

  • is actually a perfect GIF loop.

  • How is it that the end matches the beginning?

  • And this is something I talked about

  • in my previous Coding Challenge, GIF loop,

  • where we looked at, ah-kay, well,

  • we can move something across the window.

  • We can rotate something, and as long as the last frame

  • matches up with the first frame it will loop,

  • but if it's all random and chaotic, how do you do that,

  • and so there is a technique for doing this.

  • Golan Levin actually also has an example bit of code

  • which describes this in more detail,

  • which I will show you later in this video,

  • but mostly what I want to do is highlight to you

  • this blog post from Necessary Disorder,

  • Etienne, from November 15th, 2017,

  • which explains this technique of creating GIFs like this.

  • Here's another one!

  • How could this even possibly work?

  • And so to begin this discussion,

  • I mean, hopefully we're going to get to lots,

  • I mean, I could probably make videos on this topic

  • for the rest of my life, (giggles)

  • but to begin this topic

  • I'm going to return to a previous Coding Challenge.

  • You may remember me from Coding Challenges

  • such as Coding Challenge number 36, blobby.

  • It's when I used to wear T-shirts

  • with this other logo on them during my Coding Challenges,

  • so what is the issue with blobby,

  • so I'm actually, even though I could just pull up that code,

  • I'm going to (fingers snap) speed-code blobby again.

  • You're going to see, watch,

  • this is like two Coding Challenges in one,

  • so I'm going to what I'm going to do is I'm just going to say,

  • let a equal zero,

  • a is less than TW0_PI,

  • and what I'm going to do is

  • I'm going to use my polar-to-cartesian coordinate

  • Song

  • and I'm going to say let x equal

  • r times cosine of that angle.

  • Let y equal r times sine of that angle,

  • and then I'm going to make up some value of r.

  • r is going to be 100.

  • I'm going to translate to the center of the window,

  • and then I am going to say beginShape.

  • I am going to say endShape, and I'm going to set a vertex,

  • vertex at x, y, and I'm going to say,

  • and I spelled TWO_PI with a zero,

  • which is really complaining.

  • I mean, I'm just saying, stroke 255, and noFill,

  • and there we go.

  • Look, I just wrote the code for drawing a circle

  • because this is a for loop,

  • I'm going to go through all these different angles.

  • I'm going to calculate.

  • I'm going to increment the angle.

  • I'm going to keep the radius constant,

  • and I'm going to set all the vertices x, y of the circle.

  • Now, if r is random,

  • and this is basically what I did in blobby,

  • if I say random 50 to 100, look what we've got.

  • We've got this kind of like crazy, flickering thing,

  • and that's almost, that's kind of interesting unto itself,

  • and I could make this a little more evident

  • by making the time step,

  • not the time step, the delta angle, the amount of angle,

  • the amount of vertices I'm drawing, fewer.

  • I could make sure it connects at the end by saying CLOSE,

  • and I could also, just for right now, say noLoop

  • so we only get one of them,

  • so each time I run this sketch

  • I'm going to get a new random pattern.

  • Now, here's the thing.

  • This actually looks like it's a nice, closed loop

  • because it's all random.

  • It doesn't matter if the last vertex

  • doesn't match up with the first vertex,

  • and I, it would be somewhat smart of me

  • to be more thoughtful about what this delta angle is,

  • like maybe it should be something

  • that divides perfectly into TWO_PI,

  • or the radians equivalent of 360 degrees,

  • but again, I'm not going to worry about that.

  • What I'm going to do is

  • I'm now going to add Perlin noise to this.

  • Now, if you've never heard of Perlin noise before,

  • I will refer you to a playlist

  • where I talk about what Perlin noise is, and how it works,

  • and a whole bunch of other videos (giggles) related to this,

  • so go and watch those now if you want,

  • or I also link to some articles about Perlin noise,

  • but I'm going to assume knowledge of Perlin noise

  • for the purpose of this Coding Challenge,

  • so right now, what I'm going to do is

  • I'm going to say let t equal zero,

  • so I'm going to use t as my offset

  • through the one-dimensional Perlin noise space.

  • I'm going to change that to x offset in a little bit,

  • but let's just keep it at t right now.

  • Then I'm going to say r is noise

  • of t times 100,

  • so interestingly enough, let me,

  • we get a different size circle every time I run the sketch

  • because we're getting a new,

  • randomly seeded set of Perlin noise values, (sighs)

  • and I'm never moving through that time space,

  • so each vertex is exactly the same,

  • so what I want to do now is say, in the loop,

  • t plus equal some amount of delta,

  • so you now you can see look at this,

  • ew, the amount is changing, but it doesn't match up,

  • so first of all, let me clean this up a little bit

  • by saying map, let me use the map function,

  • which I think will make things a little simpler.

  • Perlin noise always has a range between zero and one,

  • and let's say I want that range

  • to go between like 100 and 200 now,

  • so we can see, look at that.

  • Now, there's just this little every time I run it

  • you can see that the last Perlin noise value

  • doesn't match the first one.

  • This is the problem.

  • This is getting at this idea of a perfect Perlin noise loop,

  • and let's also have delta t,

  • the way I move through the Perlin noise space.

  • Siri, what should delta t be?

  • (crickets chirping)

  • (computer boops)

  • Let me change that to this

  • and you could see even if I move t faster,

  • and I get this kind of smoother blobby-like shape,

  • it always has this artifact: the last and by the way,

  • if I took off this close, this will be more evident.

  • Why, right?

  • The last vertex doesn't match up with the first one.

  • This is the problem,

  • so I have my title of this video right here,

  • Perlin Noise Loops.

  • Perlin noise,

  • if we're talking about one-dimensional Perlin noise,

  • Perlin noise values in a one-dimensional space,

  • with this being the t-axis, the time axis,

  • although really I should call this x offset,

  • 'cause it's like the x offset.

  • This is maybe a graph of those values,

  • and if I'm arbitrarily going

  • from zero to some fixed endpoint

  • as I get to the end of that circle,

  • whatever value I get here, which may be, let's say,

  • if this is between like zero and one,

  • maybe this is 0.3,

  • and this is like 0.621, right?

  • They don't match up.

  • If I were to take this and twist it around into a circle,

  • they don't match up.

  • There is another way

  • to look at a space of Perlin noise values.

  • This is a way of looking at it in one dimension.

  • Let's now look at it in two dimensions,

  • so instead of having a sort of one-dimensional graph

  • of Perlin noise values,

  • I present to you

  • a grid of Perlin noise values.

  • The idea is each one of these represents some value

  • between zero and one.

  • Now, in this two-dimensional space,

  • each one of these values represents,

  • uh, is also a number between zero and one,

  • so I might have like 0.2 here, 0.3 here, and 0.31 here,

  • and 0.26 here, and 0.19 here, right?

  • Every single space has a value.

  • Now, here, in one dimension,

  • any number in one-dimensional space

  • is quite similar to its neighbors,

  • and it only has two neighbors:

  • a neighbor on the left and a neighbor on the right,

  • or a neighbor after and a neighbor before.

  • Here, each value has how many neighbors?

  • One, two, three, four, five, six, seven, eight.

  • It has neighbors above, and neighbors below,

  • and neighbors to the right, and neighbors diagonally down,

  • so the idea here is that

  • what if I could walk around

  • through a two-dimensional Perlin noise to get space

  • to get random values and always end up back where I started?

  • And why not just walk in a circular path?

  • I mean, that's kind of what I'm programming anyway,

  • so why not just do that?

  • What if I were to start here

  • and get this Perlin noise value, then this one,

  • then this one, then this one, then this one,

  • then this one, then this one, then this one, then this one,

  • then this one, then this one, then this one,

  • then this one?

  • I would have one, two, three, four, five, six,

  • seven, eight, nine, 10, 11, 12,

  • 13 random numbers,

  • and the last one is going to match up with the first one

  • if I keep going,

  • so I could get those random numbers over and over again,

  • and if the amount of numbers there is so vast,

  • it's going to appear

  • like it is a continuous sequence of total randomness,

  • smoothed with Perlin noise,

  • so this is the theory,

  • so let's now go and apply this theory

  • to this particular blobby shape,

  • so before I get back to the blobby code,

  • what I have here is a processing sketch

  • that is visualizing Perlin noise in a two-dimensional space,

  • so this a pretty sort of like classic visualization

  • of 2-D Perlin noise as this cloudy like texture,

  • and this is literally (giggles) exactly this,

  • where each number,

  • each random Perlin noise value in the two-dimensional space,

  • is represented as a pixel

  • with a brightness value between zero and 255,

  • and when you look at that you get this cloud-like pattern

  • because the color seamlessly, smoothly moves between white,

  • to black, to gray, to black, to gray, to white,

  • so the idea here is what is what I want to do

  • is walk around this space and pull those numeric values,

  • but map them to something else besides a pixel value,

  • and walking around in a circle

  • is a nice way to create a loop,

  • but you don't necessarily

  • have to have that be in the circle.

  • All right, so let's go back to the blobby code.

  • Now, there's a (giggles) a bit confusing about this,

  • because in addition

  • to the walking around the Perlin noise space

  • in a circular path,

  • I also happen to be walking around the 2-D canvas

  • in circular path to draw this circular shape,

  • so I'm kind of using the same idea,

  • but with two different points of view,

  • and hopefully that is something that makes sense to you.

  • Hmm, okay, so what I want to change this is

  • I no longer want to have t.

  • What I want to have is x offset

  • and a y offset,

  • and I want to get the Perlin noise at x offset, y offset,

  • so this is now what I had before if the,

  • if the x offset and the y offset,

  • right, basically, if what I'm doing is

  • I'm asking for what is the Perlin noise value at this spot

  • it's going to give me some random value,

  • and then it's going to make that the radius of the circle,

  • the blob shape, as it goes all the way around,

  • so I want to start moving,

  • but I actually don't want to start here.

  • I want to start over here, so I have to deal with the fact

  • that I need to find this point

  • if zero, zero's in the top-left,

  • 'cause I can't have negative values

  • in the Perlin noise space,

  • so this is a little bit of a tricky piece of this,

  • but I want to use that same

  • polar two-cartesian-coordinate formula,

  • or I want to say x offset equals cosine of that angle,

  • y offset equals sine of that angle.

  • Now, look at this.

  • I've kind of got something, but it's weirdly symmetrical,

  • and the reason is this exactly what I just alluded to.

  • These x offset and y offset values

  • are going between negative one and one,

  • and so in fact I'm trying to look at Perlin noise values

  • over here, right, and these, this doesn't exist.

  • The Perlin noise space is all positive,

  • so there's actually a very simple solution to this,

  • which is just to add one,

  • and let me add the CLOSE back in,

  • and let's run this a bunch of times,

  • and we can see, there we go,

  • we have this nice random blobby shape

  • where the end matches the beginning.

  • Now, I want to do, let's do some more stuff here.

  • All right, so first of all,

  • what happened to that like incrementer?

  • What happened to t plus equal 0.01?

  • Now I have x offset and y offset.

  • Why aren't I saying x offset plus equal one,

  • 0.1 y offset plus equal one, one,

  • well, actually, the incrementer is this.

  • It is the 0.1 here.

  • It's cosine of the angle,

  • and in truth (giggles) I could (gasps)

  • have a separate variable

  • from the one that's incrementing in the loop,

  • 'cause I could move through,

  • but I need to go all the way to TWO_PI,

  • so that I don't want to do.

  • I think a way for me to vary this in a more flexible way

  • is actually to use the map function,

  • so if I map cosine of a,

  • which goes between negative one and one,

  • and then map that to a range between zero and two,

  • we have, and this is sine,

  • we have exactly what I had before, and I can keep,

  • I can keep rewriting the sketch,

  • and I'm getting a new version of the shape,

  • but interestingly enough, what happens?

  • This is really now something that I should make a parameter,

  • so for example, what if I were to say let,

  • I'm going to make this a global variable,

  • let, I'm going to call this noiseMax equal two,

  • and I'm going to put this here,

  • and watch what happens if I make this five,

  • versus 10, versus 120,

  • versus 0.1,

  • and look at this, 0.3, 0.5, look at this.

  • This is really kind of interesting.

  • With just a little bit of noise,

  • I have what appears almost like a perfect circle,

  • but it kind of looks like a human being like me

  • with faults, I have lots of faults,

  • drew that circle.

  • It's got some slight so Perlin noise

  • can actually be used as a nice way,

  • with a little subtle Perlin noise,

  • of making some perfect shape,

  • like a letterform, or a circle, or a square,

  • have a little bit of wiggle to it

  • that makes it seem more hand-drawn,

  • so that's a nice thing to see.

  • The other thing we could see here very quickly is like,

  • it would make sense for me to create a slider.

  • I'm going to say,

  • and this I'm using the p5 dom library to do this,

  • which is a really quick way.

  • I'm going to create a slider which has a range

  • between like 0.1 and 10,

  • and I'm going to start it at,

  • actually let's make it between zero and 10,

  • and I'm going to start it at zero,

  • so I have the slider here now,

  • and then I want noiseMax to equal,

  • noiseMax to equal slider.value, so watch this.

  • Okay, that didn't work. (giggles)

  • Oh, I have noLoop in here.

  • No wonder.

  • Take out the noLoop, and now let me slide it.

  • Oh, we need to make that,

  • so first of all I need to give myself smaller time steps

  • when moving the slider, so let's do this.

  • Oh, look at that.

  • Look how it kind of like unfurls,

  • because it's the same noise space;

  • I'm just stretching or shrinking it.

  • That is a really

  • imagine now if I oscillated that like along a sine wave,

  • so another thing that I could demonstrate to you

  • is interesting, like a always starts at zero,

  • 'cause I'm going from zero to TWO_PI,

  • but if I am walking around the path of a circle,

  • there's no reason why I couldn't start over here

  • and then go around, or start over here and then go around,

  • and why not vary that?

  • That would be like the phase.

  • You go back to my Fourier, all of this stuff,

  • it's so crazily interrelated it's amazing,

  • but if you go back to my Fourier transform videos,

  • where we created these orbiting epicycles,

  • we had this concept of phase,

  • which is where does that orbit start,

  • so let me show you another thing here.

  • Okay, what I'm going to do is show you

  • so let me make a variable called phase,

  • and we have that be zero.

  • I'm going to have cosine of angle plus phase,

  • sine of angle plus phase,

  • what do you think's going to happen if I increment phase?

  • Well, it looks like the shape is rotating.

  • I mean, it is rotating, or it's not rotating.

  • I mean, visually it's rotating,

  • but I'm actually just starting

  • at a different point in the noise space.

  • Interestingly enough, like,

  • and if I make that much smaller, you'll actually see that,

  • like smaller than the amount of vertices I have,

  • you start to see a wiggle between them, so interest,

  • like I could make this 0.2,

  • and that's going to be even more apparent.

  • Like, look at that crazy weird wiggle

  • as those vertices adjust their spot,

  • and then I want to show you something even crazier, I think,

  • like let me put it back.

  • Let me sync it so this is like a nice perfect rotation.

  • What if I only apply the phase

  • to the x offset or the y offset, like different phases?

  • That is really, oh, it's kind of too fast,

  • so let me do like this.

  • Like, this is really weird.

  • You can sort of see

  • it's almost like there's something crawling around the edge.

  • (screams in mock horror)

  • There's so much weirdness stuff going on,

  • so anyway you see the sort of like exciting possibilities

  • of thinking about Perlin noise values

  • as one-dimensional,

  • values that might pull over time

  • in a sort of one-dimensional fashion,

  • but actually pull them from the path of a circle

  • in the two-dimensional Perlin noise space.

  • Now, what I happen to be doing in this

  • is taking a very literal approach. (giggles)

  • I'm taking those Perlin noise path values

  • walking around a circle,

  • and applying them to like the distance

  • from the center of a circle over,

  • as I'm drawing it, so it's very like,

  • it's a very literal sort of like visualization

  • of Perlin noise values in a circle

  • to the edge points of a circle,

  • but if you start to think of other ways

  • you could apply those values,

  • the creative possibilities explode,

  • and so in other words, if this is what I started with,

  • I have Perlin noise at the beginning.

  • Sorry, I have Perlin noise values in one-dimensional space,

  • but they don't loop,

  • why not take those looping values here,

  • along the path of a circle,

  • and then unfurl them

  • back into the sort of one-dimensional line,

  • and then use those

  • to apply to any value in any visualization

  • to make a perfect GIF loop.

  • That's the idea, so I'm going to just put that out there.

  • I'm putting this out into the universe.

  • I mean, I didn't put it out in the universe.

  • Lots of other people, Etienne, and Golan,

  • and many others I'm sure I'm forgetting to reference,

  • have done this for years, so give that a try.

  • In the next video I'm going to come back and actually do that,

  • so I'm going to see if I can take this idea

  • and just apply it to something.

  • Probably won't be that visually interesting,

  • but this will hopefully give you lots of ideas

  • of what you might make.

  • Let's add one more thing to this.

  • I think I can.

  • This video's not too long so far.

  • All right, let's add one more thing, so first of all

  • let me take out this idea of phase for a second.

  • Just going to comment that out and put it back to what it was,

  • which is just this,

  • so every time I run it I get a new Perlin noise space,

  • and incidentally,

  • the only reason why I'm getting a new Perlin noise space

  • is because p5, behind the scenes,

  • will seed Perlin noise with a random seed each time,

  • but I could actually control it.

  • If I were to say noiseSeed,

  • and pick some arbitrary seed value,

  • and random number seeds is maybe a topic for another video.

  • Every time I run this

  • I'm going to get exactly the same shape each time,

  • so anyway, just pointing that out,

  • but there is something else.

  • There is another way I could animate this,

  • and it has to do with three-dimensional Perlin noise,

  • and Perlin noise can exist in any n-dimensional space.

  • In p5 and in processing,

  • I think the functions that give it to you

  • just support one, two, and three dimensions,

  • but let's talk about

  • how you might use three dimensions here,

  • so for example, if this is my visualization of Perlin noise

  • in two-dimensional space, that cloudy image,

  • well, I could make sort of like a cloudy set of cubes

  • in three-dimensional space,

  • but another way of thinking about it is

  • have that third dimension be slices of an animation,

  • so I could show you the Perlin noise space

  • over time

  • while incrementing a z-value, a z offset,

  • and show you Perlin noise for a z offset equals zero,

  • then z offset equals 0.1, then 0.2, then 0.3,

  • and so that actually, all of those will have numbers.

  • Each one of these numbers is now

  • has all of its neighbors to up, and down,

  • and left, and right, and forward, and backward,

  • are similar random values,

  • so this is actually a really easy thing for me to add.

  • I just need one more global variable called z offset,

  • and this needs to be global

  • 'cause I'm not resetting it back every time through draw.

  • Each time through draw I'm incrementing it,

  • and I can just add zoff right there

  • to the Perlin noise function,

  • and then I can say zoff plus equal some amount, like 0.1,

  • and you can see we get this wiggle.

  • I can make it 0.01,

  • and I'm going to move through the Perlin noise space

  • much more slowly,

  • and once again we could see, like,

  • there's all sorts of things I could do here,

  • like this could be 0.3, and this could be 0.1.

  • There's so many parameters that you can explore here.

  • I think we've made, actually, a super-interesting shape

  • for like a crazy animated game version of Asteroids,

  • like you can imagine having Perlin noise

  • jiggling, oscillating, looping, noisy,

  • polar Asteroids.

  • That's a thing you should make,

  • so anyway, so I hope you find some variations for this,

  • and I look forward to seeing what you make,

  • and stay tuned for the next video.

  • (bell dings)

  • (playful music)

  • (bell dings)

(bell dings)

Subtitles and vocabulary

Click the word to look it up Click the word to find further inforamtion about it