字幕列表 影片播放 列印英文字幕 (horn toots) - Hello, welcome to a coding challenge entitled 4D Open Simplex Noise Loop. That's got to be a click bait title if I ever heard one, right? (laughs) Anyway, let me thank somebody. The artist Etienne Jacob, who I've referred to in like the last 307 coding challenge videos that I've made, because I keep doing this topic over and over again, has been really an inspiration for these videos. Makes these amazing noise loop GIFs, and I've talked a little bit about some techniques for doing that using classic Perlin noise, the noise function in processing, which you can also refer to as fractal noise. Recently, through feedback and research, been turned on to this idea of Simplex Noise and Open Simplex Noise and I made an entire video all about that and the differences and a little bit about the history there. I'll refer you to that video if you want to find out more. In this particular video, all I'm going to do is I now have the processing 3D noise example, which you'll see nothing is three-dimensional here. There's really a two-dimensional space of noise and the third dimension is what's creating the animation frame. You can think of that third dimension almost as time. I'm seeing frame by frame by frame. What I want to do with this is take this and make it loop. I want to have this noisy scene, and this is using Open Simplex Noise, which has a different quality and character to it. It has less what are known as directional artifacts that I referred to in the previous video as like this herky jerky feeling of what the noise algorithm can sometimes do if you also stop and turn around. The smoothness of this is quite pleasant and has a visual quality that's, for a lot of scenarios, better. There's more to say about that, you can go watch the other video. What I want to do is make this run just over a few seconds and then render it as a GIFs that loops seamlessly. I took a quick break there just to render out that processing sketch. I rendered out a few seconds, and as you'll see, I rendered it to a GIF and every few seconds, you see this jarring thing happen where it goes back to the beginning. The last frame of this noisy scene doesn't match the first frame. This is something that I talked about in previous coding challenge videos, how to get a sequence of values, a one-dimensional array of random values where the last value matches up with the first. You close that loop. The way that I did that was, I want one dimension of values, let me walk around a circle, a circular path in a 2D noise space. Now what we're doing is I want two-dimensional looping values, so I need to basically walk around to space of a torus. I need all of these values to move around and come on back. First, what I want to do is... Let me just be clear, this is the processing noise 3D example and the only changed is I've added this OpenSimplex Noise code from Kurt Spencer. I will link to where that code and some background about this open source implementation where it comes from in the video's description. Instead of calling Processing's noise function, I'm calling noise.eval from Kurt Spencer's OpenSimplex Noise and that gives me a double, so I have to convert that into a float. It also gives me a range of values between -1 and 1, which is different than the values between 0 and 1. What I would like to do is make this a bit more visually obvious what's going on, so I'm going to change this. I'm going to threshold this to render the color either black or white. One way I can do that is with a nice little ternary expression. I can say brightness equals, like is noise greater than zero? If the noise value that comes out is greater than zero, then I want to see 255, otherwise I want to see 0. If I do that, you'll see we get this. I can play with the increment values, like maybe let me make the increment a little less but make it go through the zSpace faster, I don't know. So, now we can see. So this, this would be... I should've rendered this to a GIF, so you could see it not looping, but this is what I want to have loop. Also, look at the beauty of this particular noise algorithm. It's very smooth, it doesn't feel like it's... It doesn't have that directional art effect. It doesn't feel like it's slowing down to a stop and then going backwards, it just keeps going with this kind of beautiful organic randomness. Now that I have this, let's turn this into a GIF loop. All of these videos are now kind of, this series, everything's depending on each other. I did have a previous coding challenge where I made processing code that just renders out the frames for a GIF loop and at the demonstration is just a rotating square. What I want to do is, I'm going to use that as my basis. Let me grab all the code before set up from here, which is all of this. I'm going to put that into my GIF loop code. Then, I wanted to make the new OpenSimplexNoise object, and I'm going to put that in here. Now, it's complaining to me, it doesn't know what OpenSimplexNoise is, so I do need to make a new tab. I'm going to call it OpenSimplexNoise.java. And... whoops. It needs to be .java because this particular OpenSimplexNoise class is using some features of the Java programming language that don't work super elegantly in processing. I can then just go copy and paste it over. Certainly, there's more streamlined ways of importing a Java class, but just copying it over is one way. Then I'm going to come back to here and what I'm going to do is everything that's in draw() is what should go into this render function. This render function should now have all of the drawing code. Here, now we have this running. It's not looping yet, I've got to figure that out. I also want to give myself more frames probably and... Actually let's make it short, 'cause I really want to make sure it's looping. Let's make it 640 by 360, it's kind of nice to have that aspect ratio. Now, this is what I want to render as a perfect loop. So, what's going on? Here's the thing, the thing that needs to loop is the z-axis, the z-axis instead of moving forward in time should move around in a circular path to create that donut in three-dimensional space. How do I do that exactly? It turns out that the way I can do that is let me actually get rid of this idea of z offset and I want to have... Let's see if I can diagram this. Alright, this is my two-dimensional plane of noise in three-dimensional space and at any given point, what I want to do is kind of walk around in a circle. If this were the flat plane, the circle would come out like this. I don't know if this is really... So, what I need is an angle. I need to rotate around, I need to use that polar coordinate formula, to rotate around a circular path within one plane of three-dimensional space. To do that, I used four-dimensional noise, because what I'm doing here is, I get... Remember, in looping a GIF, I want a percentage from 0 to 100%, so I can not now have an angle which is equal to map that percent which goes between 0 and 1, to between 0 and TWO_PI. Then I can have, I'm going to call this u offset for the third dimension and I'm going to call this a v offset for the fourth dimension. What those are is I'm going to say cosine of the angle and sine of the angle, right? I'm going to use the polar to Cartesian coordinate transformation and map these values, which go between 0 and 1. No, sorry, they go between -1 and 1, to between some noise radius and noise diameter. This is a concept I talked about in the previous looping video, but it's very hard to type and talk at the same time. Sometimes I do a good job, sometimes I'm a mess, and right now I'm a mess. This is very hard to explain. This is exactly the same technique that I did in the first noise loop video, where I just had an x and a y. Now, I have an x and a y, but the looping is happening in the u and the v. That's where the size of this circle is important. I'm not sure whether in the Open Simplex Noise algorithm whether I can have negative values or not, but to be safe, I'm just going to map these between 0 and 2. I'm picking sort of an arbitrary, this I think we called noise diameter or something like that, I'm picking an arbitrary value. Now, down here, change this to u offset, v offset, and let's run this. Did I get everything right? No, no. Oh, I have an extra 0 in here, because I'm going crazy. z offset is not a thing anymore, and here we go. (bell dings) Okay, so one this to note here, (laughs) is that 4D, the implementation for getting 4D noise is quite slow. You can see this frame rate sort of chugging along. The good news is we're here to render out to a loop, so I don't care about the speed, the frame rate, I am just going to turn record to true and I'm going to run this again and I will see you when it finishes rendering. (playful synth music) All right, it finished rendering. The good news, just to reiterate, because 3D noise worked quite smoothly, if you're not rendering out to a loop, you don't need that fourth dimension! You can just use the third dimension and watch your real-time software in your media art installation work beautifully. But, if you're rendering it out, I want to close that loop, I do need that fourth dimension. Okay, I'm going to switch over to my terminal window and I'm in the GIF_loop_4D sketches folder and now I'm going to use ffmpeg to render all those frames into a GIF. So, I'm going to say ffmpeg -for image2, and ffmpeg is a utility you would have to install separately. I'll include a link to how to do that in this video's description. - f image2 -framerate, let's give it 30 frames per second, - i, the file path, which is output/gif... Each file is gif dash and then a number, so %3d.png and then I'll call it noiseloop.gif and I'm going to render that out. I am going to take a look at it, here it is. Let's take a look. By golly, if that doesn't loop, I don't know what loops. This is about four seconds long. Of course, you can see. (laughs) You might be able to detect the loop because it's so short, but if I made I a little longer and if there was a bit more, if I was more artistic and had more creative ideas about how to vary the visual quality, we might be able to create something more like what I showed you in those original Etienne Jacob GIFs. Hi, so this might be the strangest, most nontraditional ending of a coding training video ever, 'cause you probably were just watching me in the studio coding, but I was going to record a new ending to it today in the studio, but it's a snow day. Just buried in snow here, can barely walk. (laughs) Anyway, what you have just seen is a coding challenge where I added Open Simplex Noise. Really, I think what you should take away from this is the quality of Open Simplex Noise rather than classic Perlin noise and think about the kinds of projects you might make that run in real time that don't actually need to loop. But, if you're making a looping GIF, this is sort of an interesting technique. I'm going to show you right now this terrain. This is basically my coding challenge before but with Open Simplex Noise instead of classic Perlin noise. That's a challenge to you. If you can make this looping terrain happen, then try that. I'm going to do that in a video, I'll come back this Wednesday during my regular livestream and I will create this terrain with Open Simplex Noise as a follow up video. I hope you enjoyed this short coding challenge with Open Simplex Noise and looping in four dimensions and all sorts of wackiness like that, and I'll see you next time on the coding train, choo choo! (upbeat pop music)
B1 中級 編碼挑戰#137:4D OpenSimplex噪聲環路 (Coding Challenge #137: 4D OpenSimplex Noise Loop) 1 0 林宜悉 發佈於 2021 年 01 月 14 日 更多分享 分享 收藏 回報 影片單字