6 Types of Noise Textures in Godot, and how to make them!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
it's been over a year since I made my first shader tutorial the fog one where I first figured out how to make that noise texture that I would then go on to use in so many of my subsequent shaders since then I've learned a lot about procedural shaders and noise textures so I thought I'd make another dedicated video today on six different types of noise textures with some improvements upon the noise that I've made in the past and some better information and insights about those noise textures as well a big part of my knowledge of noise textures actually comes from the book of shaders calm which is a great website that explains in detail many aspects of procedural noise and shaders with interactive code and examples so I'll leave a link in the description and it's definitely worth checking out the shader scripts I end up with in this video will also be on my github repository confused shaders link in description finally I'll put time stands for each type of noise in the description but I would recommend watching this video from start to finish since some of the later parts are built on top of things that are covered earlier in the video with that being said here are six types of noise textures and how to make them in get out alright first off we have random noise just a reminder that a shader is basically a program that is run for every single pixel on your image and the coordinates we'll be using is our UV coordinates which is 0 to 1 0 to 1 like that for the whole image multiplied by 10 so that we can see a bit more of it and it's scaled down now randomness is one of the most fundamental elements of noise textures and procedural generation and it's a whole topic within itself with many different algorithms people have developed over the years each with their strengths and weaknesses of course true randomness doesn't exist in computers so all these algorithms are actually pseudo-random algorithms the one we will be using is the very famous yet mysterious canonical random function also known as the one-liner I found somewhere on the internet this random function is very famous among the shader community and has been reused many times on the internet but no one knows who came up with it or where it originated from the way it works is it first takes a vector 2 as an input and in order to just come up with one random value as and outputs it gets the dot products between that and some random vector to here then it plugs that output into a sine function and usually a sine function is actually it gives a smooth sine wave which is not random at all but we multiply it by this gigantic value over here so that any small change in the output of the sine function will be magnified too many times then the fraks function just takes the fractional or the decimal part of that output which means for example if we have twenty three thousand five hundred and six point seven four or something like that we'll just get the point seven four part as you can imagine getting just the decimal parts of a wildly varying value will end up being pretty random now why were these specific values chosen no idea but I decided to respect the canonical one-liner and keep it consistent with the rest of the Internet let's check out what this random function looks like here and there we go it's just random noise there is a problem with this function when you may the input too large because let's say we add a vector2 with both values being for example 10,000 then as you can see we started getting these horizontal stripes and it starts to becoming less random if we were to make that I don't know a hundred thousand it gets even less random make it a million it's even worse now this was a problem I ran into in my earliest shader tutorials specifically the fire one and it was especially because I thought well you know since they're random values here why don't I just put my own values in them to add a bit of my own twist to this function this is the random function I used in the fog tutorial with 5678 thousand a thousand and I actually made the problem even worse with this striping and decrease in randomness happening even when the values are inputs it weren't that large so I guess that's another reason to respect the original values because they seem to work pretty well anyways in order to combat this decrease in randomness we can put our input corner through a mod function so that when it gets too big it just resets to zero every factor that I found to work well is ten thousand and since we've multiplied our coordinates by ten let's set this offset to nine thousand nine hundred ninety five which is five less than ten thousand and as you can see the top half of our image is getting a decrease in randomness but halfway down it hits that 10,000 mark and it resets back to zero and we're getting some good randomness again ten thousand is a good value because the randomness doesn't really decrease too much but we're not resetting it too many times so that our random noise is repeating too much either now we're gonna need a 2d random function as well which outputs two values in the form of a vector two instead of just a single floats here I've copy and pasted a function that I found on the book of shaders calm which gets two different dot products with two different vector two's for the X&Y value that's how it's able to get two different values whereas the other one only gets one dot product who knows how many times this function has been used on the internet but anyways I'll just copy over the mod function to preserve its randomness as well and we can get the X components of this new 2d random function to see its randomness there you go looks like that our next type of noise is value noise which is basically just random noise but we add a grid system to it we split our image into many 1 by 1 squares and of course how many squares we have depends on how much we multiply our coordinates the original untouched UV cornice will just give the whole image a 1x1 square and basically for each corner of each square we'll just assign a random value to it and whatever pixel we're trying to calculate in the middle will just interpolate its value from the four corners depending on how far the pixel is from each corner now the first thing we have to do in our value noise function is make two vector twos one called I and one called F I is the floor or the integer part of our coordinates so for example for 12.75 the integer part would be the 12 and that tells us which square were in that's also how we're able to make 1 by 1 squares because integers increase in increments of 1 now F will be the fractional part of our coordinates so out of 12 point 7 5 it'll be the 0.75 and that'll just tell us what our position is within that square now for each corner of our square we're gonna have to generate a random value for it using the coordinates of that specific corner that is the input the eye vector will simply be our top left so we can use that as the input for our top left value and to find the other 3 corners of our square we can just add an offset to it now we have to interpolate between the 4 corners we could just use the linear distance between the pixel and each corner but using the linear distance will cause a sharp transition between neighboring squares if we instead make a cubic position factor like this then this is how our distance value will change throughout the square as you can see near the edges it changes a bit slower so that's how it's able to transition smoothly between different squares I'm gonna be honest I don't really understand how this works but I found this on the internet and it works and that's all that matters now we can find the average between the top left and top right then between the bottom left and bottom right using the x value in our cubic position and then we can find the average between those two using the Y value and then we'll return that if we put that as our value then here's what we get a simple blocking noise now the problem with the value noise as I said is that it looks a bit blocky some guy called Ken Perlin invented a different type of noise in 1983 that looks a bit smoother and more pleasant the way Perlin noise works isn't completely different - value noise actually we're still splitting our image into 1 by 1 squares but this time instead of assigning just a random value to each corner will assign a vector with length 1 to each corner pointing at a random direction then our pixel will find the distance vector between its and that corner and then find the dot products between that distance vector and the random vector that the corner has been assigned and then once we've got the dot products for all four corners will just interpolate between them the reason Perlin noise ends up being smoother is because the four values that were interpolating between aren't just random values that we made for each corner these values actually have something to do with the position of our pixel since its distance vector goes into the dot product so not only does the interpolation depend on where the pixel is the values being interpolated also depends on where the pixel is and that's where per the noise is unlike a value noise so let's copy over the first part of our value noise function which finds out what Square were in and which part of the square were in and then generates a random value for each corner of the square these random values will be used to randomly rotate a vector of length one at each corner but they're currently in between 0 and 1 which means they can only rotate a maximum of one Radian which is a very small range we want to multiply it by two pi which is approximately six point two eight three in order for it to be able to rotate the full 360 degrees now let's actually make a vector of length one for each corner and rotate it by that random amount now the way we rotate a vector and make it into new values is using this formula right here which I found out Wikipedia basically the new x value will become old x times cosine of that angle that we want to rotate minus why times sine of that angle and then the Y component will be old x times sine of the angle plus y times cosine of the angle we can start off with a vector pointing downwards though which is 0-1 which means we don't actually have to worry about the first part of each expression in the x and y values because X is equal to 0 and we can just ignore it so we just end up with vectors with negative sign of the random value as their X value and the cosine of the random value as their Y value now getting the dot products is just putting in these new random vectors that we made into the dot function along with the distance vector between our pixel and each of the four corners to get the distance pixel we can just find out the difference between the pixels position in the square and the coordinates of each of the four corners which is 0 0 1 0 0 1 and 1 1 the 0 0 can obviously be ignored and now we can just cubic interplay between the four values according to the position of the pixel and then return it let's see how our noise looks wait a minute why is it so dark the reason our for the noise ends up being so dark is because the dot products actually end up being between 0.5 and negative 0.5 so in order to shift that range to between 0 and 1 we have to add 0.5 to our return value and there we go we got for the noise it does look a lot smoother their value noise now the dot products aren't exactly between 0.5 and negative 0.5 if we find out the difference between that return value and the return value clamps between 0 & 1 we can't see that there is a tiny little bit of color being clipped here so there are some parts which end up being above 1 once we add the 0.5 but it's close enough and it should be fine alternatively we cannot add the 0.5 to the final value and instead just get the absolute values of the dot product and we can also get a different interesting effects using that although it wouldn't be traditional Perlin noise our next noise is cellular noise also known as Warley noise or Voronoi noise a guy called Stephen Worley invented this in 1996 to explain cellular noise let's give each pixel in our image a value based on how far they are from a certain point in the image for example the middle that's what it looks like but what if we had two points in our image and each pixels value was based on how far they are from the closest point to them then it looks like this what if we had three points four points so cellular noise is basically where we divide our image into 1 by 1 squares again and generate a random point in each square then each pixel for example this blue one right here will check for the closest random point to it and use its distance from that point as its value of course going through all the points on the image is impossibly performance intensive since there's an infinite number of points but our picture only has to check for the point within its own square and its neighboring squares so we only have to go through nine points like so so first of all let's copy over our good ol INF which tells us which square were in and what position we are in that Square and now let's make a double for loop to go through the nine squares around the pixel will go through x values of negative 1 0 & 1 and then for every x value will go over Y values of negative 1 0 & 1 and then we can add these x and y values onto our eye coordinate to find the coordinates of either a neighboring square or the square of the pixel itself then whatever square we loop through will generate a random points in that square using its coordinates as the input this is where the random function with two outputs is useful we also have to add on the X&Y value to properly account for whether it's a neighboring square that way we'll get the right distance when we minus the position of that point from our current pixel which is the F coordinates our goal is to find the shortest distance to a random point so let's make a variable called minimum distance up here and set it to something very large and every time we get at new distance we'll compare that to our existing variable and see if it ends up being the new minimum distance if it is then we set it to that and at the end we'll return that minimum distance value let's multiply our coordinates by 10 again and that's how we get Cellular noise this type of noise looks very interesting fractal noise also known as fractal Brownian motion noise there's not a type of noise in itself but rather a technique that we can apply to an existing noise pattern to make it more detailed we basically start with a noise Heckscher then we get a smaller version of that noise section and add it on top then an even smaller version and add that on top and then an even smaller version and it repeats in our fvm function we'll need a value variable to store the sum of all the noises we'll eventually add together a coordinates value which we multiply by two every iteration to make the next image smaller and a scale value which decides how much we want to multiply the noise by the scale will start as 0.5 and multiplied by half every time so every next smaller noise section will have a smaller and smaller impact on our final sum it'll end up being 0.5 plus 0.25 plus 0.125 and so on which means the total sum never reaches one and will not cause clipping in our image of course we also need to decide how many iterations or how much detail we want to add since we can't just go infinite we do that with the Oxus variable which decides how many times to four loop runs and it is now set to four this is what it looks like on one this is what it looks like on two and this is what it looks like on three keep in mind the more octaves the more noise you're adding on so the brighter the overall image will get so we can normalize our fpm texture to make it the same brightness regardless of how many opposites we have let's make a variable called normalized factor up here and every iteration will just add on our scale to our normalize factor because our scale is the maximum possible value that our noise would have the noise multiplied by the scale up here is just something between 0 and 1 multiplied by our scale so our scale is the maximum and if at the ends we know what the maximum possible value is then we can just use that value to scale up our whole image to make it a consistent brightness right now for example if we set octaves to 1 then our image is pretty din it's only between 0 and 0.5 our normalized factor would be 0.5 so if we were to just divide our value by that factor and as you can see it Broughton's up again and if we change it back to four authors it's still the same brightness so yeah right now we're using value noise for our fpm but we could really use any type of noise for example we can use Perlin noise and it would look like this looks a lot smoother actually I think it looks better and I can see why further noise is the standard type of noise that people use and we could also use cellular noise which looks like this and it looks pretty cool it's got that bit of cell action going on we can see cellular shapes in the noise so that's why procedural generation is so cool because you can combine many different techniques and procedures together to make completely different results fractal Brownian motion is one of those techniques and it's very useful our last type of noise is simplex noise which we can get by adding a sprite and in the texture just say new noise texture and then click open the noise texture under where it says noise click new open simplex noise this isn't something that we write in our own shader this is something that Godot added in 3.1 I believe it's called open simplex noise and what simplex noise is it's basically similar to per the noise but the algorithm it uses is slightly more efficient and as you can see it looks pretty similar to right now the width and height is 512 by 512 if we were to change that to for example 1,000 by 1,000 drag it around to reset it then as you can see we've got a bigger noise section with more detail however I'm just gonna make it back to 512 by 512 if you click open the open simplex noise you'll get a bunch of options here here we see a familiar variable octaves which is just how many noise sectors it stacks on top of each other period just means basically how big the noise texture is in general so we don't actually have to change it from 512 to a thousand we can just change the period and as you can see the noise gets smaller or it can get bigger persistence means every new noise texture how much it contributes to the overall image with our fbm function every new layer of noise was multiplied by 0.5 and that's what it's set to right now as well as you can see the persistence is 0.5 if we set it to 1 however then that means every new layer will contribute the same amount and this open simplex algorithm seems to be normalizing the final value as well since it's not clipping even though we've got three octaves each contributing a full amount if we decrease the octaves down to one as you can see it's not dark as well so yeah the lack you narrative variable down here means how much smaller in scale does each new noise texture get if we increase it then as you see the smaller noise textures are getting a lot smaller instead of just multiplying by half every time if we decrease it though then the new layers aren't really getting that much smaller from the previous layer the seed variable up you can just change that to get a completely different noise section every time and if you check seamless up here then that means the edges of the noise structure gets blurred with the opposite edge so if you were to tile this there won't be an ugly seam in the middle as normal map just makes it into a purple normal map and all these values are covered in the Godot documentation on the open simplex Noyes page there are advantages and disadvantages to this type of noise obviously it's very convenient you can just click a couple buttons and you got the noise you can also save this noise texture as a resource to easily reuse it for other cases for example as a uniform sampler 2d for a shader of yours there's a lot of control especially with the persistence and lack you molarity but the disadvantage would be that it has a fixed width and height and you can't really make a scrolling noise texture with the time variable in a shader to keep things changing it's basically just a static noise texture if you do want it to scroll even just a little bit you'd have to make it with a very large width in height which is probably very resource consuming so yeah the SEPA noise would be much better if there was a coordinates option down here which would allow you to offsets it so that's six types of noise textures in Godot if you made it this far in the video good job give yourself a high five and also high five that like button or even subscribe if you want to see more similar videos what's that being said I'll see you next time
Info
Channel: Gonkee [OLD]
Views: 16,879
Rating: 4.9521275 out of 5
Keywords: gonk, gonkee, gonkmakesvideos, godot, shaders, noise texture, noise, perlin, value, voronoi, procedural, worley, cellular, 6 Types of Noise Textures in Godot, simplex, tutorial
Id: ybbJz6C9YYA
Channel Id: undefined
Length: 22min 10sec (1330 seconds)
Published: Mon Jan 13 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.