Shader Coding: Making a starfield - Part 1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
everyone welcome to you out of code my name is Martine and one of the first effects that I ever did back in the day when I first started programming was a star field effect and I decided to make a 2020 version of that so that's what you see behind me here and in this video I'll explain how to make this from scratch so if that interests you then so the first thing I'm going to do is like new rid of this thing and let's see here let's start with cleaning this up a little bit if you're new to shader toy and I recommend this video but if not then let's just do what we normally do so I first I'm going to make that make it that the V corners have their origin in the middle and that their aspect ratio correct it and then I'm going to make a black screen so I'm gonna go over here I'm just gonna go back three that and I'm going to do the same thing are not the same thing I'm just gonna do that so that will give me a black screen and then let's start by drawing one star and in order to draw a star we need the distance from every pixel to the center so for that I'm just gonna use a float D for distance and I'm gonna take the length of the UV coordinate and because the UV coordinate has its origin in the middle the length of UV just just gives me the distance to the center and if you follow any of my other videos then you might think well we could just use a smooth step to draw a circle so let's just do that real quick so I could do for instance this and that will just cut me out a circle and then I have to add it to my color and there is a circle right and I could I could change the size of that or whatever have you but the thing is if you want any kind of effect that is simulating a light then this is not the best way because the the fall-off here so it goes from fully brights to fully black the fall-off is not the same as what a light would would have one major thing here is that it actually goes to zero over here and then it's just zero everywhere where as you get a much nicer fall-off if it if it goes close to zero but it's an asymptote so it never actually gets to zero so so wherever you are on the screen there is always some contribution to the light and so what is a lot nicer is you if we do something like this we say one divided by the distance and that it will give me a wide screen because I need to make that a little bit smaller so if I do let's say point zero one divided by D then you get something like that and that looks a lot nicer just make it a bit bigger it looks a lot more like a light so let's use that instead I'm going to make it a little bit smaller something like that get rid of this and then the next thing I want to do is I want to make I want to make some some rays on that like our lip a lens flare on that like a two two rays that come in across like this and for that let's see what we can do let me just repurpose this M here for one second let's just use it look at the UV coordinate so the UV coordinate is zero in the middle and then it goes to zero point five and it comes from 0.5 or negative zero point five over here if I take the absolute value of that then I will just fold this part over and let's zoom out a little bit so to zoom out I can just multiply my UV x some larger number over here because right now I'm looking at like I see minus 0.5 0 and 0.5 but if I multiply this then it would go from minus 1 point 5 to plus 1 point 5 and that's why this would zoom out okay so that's 4x I can do the same thing for a Y and then it will just give me a horizontal line and if I multiply these two together don't you be that x times you read out why I get something like this which which you could use to make to make that star shape so let's play around with this a little bit well first of all I don't obviously I don't want that star to be dark and then the rest to be white I want it to be the opposite of that so for that I could just do 1 minus this thing and then it will turn that around and now let's try to make it a bit smaller so I can multiply this by some larger number to make it smaller and ah let's see here let's call this raise just for now so float raise equals that and then here I'm adding my my star itself and then here I can add the raise as well so plus a raise and so right now the Rays are obviously too large for this so let me just make it smaller so I can play around with these numbers until I find something that works okay so apparently this needs to be quite large okay there is another there's another effect at play here which is that which is that this raise can get smaller than zero right now and that's what's what's deleting the rest of my star so I can't see it this can get smaller than zero because this can get arbitrarily large right so so we want to make sure that it doesn't get negative so that we don't subtract in the black areas so for that I could just do max is zero and this and so now if I multiply this by some larger number then okay well I have to multiply by a very large number for for look for me to see the actual star so let me make the star bit bigger okay so Derek's coming okay so something like that and let's see or what else we can do I guess well if we do this then it's gonna be smaller okay okay well I guess that's okay that looks that looks good so let's just stick with this and I'm going to add a second set of of lines here at a 45 degree angle and because I'm gonna rotate something I'm just gonna add a rotation function here so rotation function I've done it before in other videos it just takes an input an angle a and then for a 2d rotation that's quite simple you make you keep track of this sine of that angle so sine of a and then you keep track of the cosine of that angle cosine of a and then we're gonna return a matrix that is the the cosine minus the sine and then the sine and the cosine and that gives me a 2d rotation matrix that I can use to rotate things around so let's go over let's go over here now let's go over here and let's rotate to UV coordinates so I'm gonna rotate it and this is in radiance so an entire 360 degrees is two pi radians so 180 degrees is PI radians so pi radians pi would be dot and then so that is 180 degrees so if I divide that by two then I would have 90 degrees and if I divide two by two again so by four in total then I get 45 degrees so this would be a 45 degree rotation and then I can just use this whole thing again so I can go over here stick that over there and let's see so it adds me to second one and I don't know why the first one doesn't go all the way up the rotate it one does but we're gonna get rid of that later anyway so don't worry too much about it I'm just gonna make it that the second one is not as bright as the first one something like that and if you have more time you can probably compact this a lot but I'm not going to deal with that now I leave that up to you because we have to move on so yeah I think that looks okay again we're gonna we're gonna fade it after don't worry about it so let's make a few a few of these actually no before I do that let me just take this thing and put that in its own function in a star function so I'm just gonna cut that out I'm gonna go over here float star which takes as an input a a UV coordinate and also I want to be able to to attenuate that flare so I'm gonna say I'm gonna add a flare parameter here that if it's zero then we don't have to cross on the star and if it's one we do so I'm just gonna copy that and I'm gonna I'm gonna have to see here so we don't have a call inside of here so I'm just gonna get rid of that over there and then over here I'm just gonna say M plus equals raised and M plus equals raised and it's going to return my value M mmm and then over here I can test if that works I could just say plus equals star of UV and then with with the flare on it like that so I compiled it nothing change so that tells me it worked but now I can also turn that flare off I could just say okay well I have to obviously added so here is my flare I have to go over here and I have to say Ray's times flare times flare and over here also raised times flare okay so now I have no no flare and now I have now I have a flare on there and yeah as I said before this can be refactored in order to make it less in order to make it less instructions but I'm just gonna leave it like this for now okay so now let's make a bunch of these so for that I'm going to go over here I'm gonna say back to GV GV 4 grid UV and I'm gonna make a bunch of boxes first so I'm gonna say it's the tract of fractional component of my UV so let me just visualize that so we could see what we're looking at call that our G equals GV ok so that gives me a bunch of boxes because fracked so my UV goes from minus 3 to 3 and frac just makes it that it just returns the the the fractional component to each time and so that's how I get this model some this repetition here and I can get as many boxes as I want if I just multiply this by a larger number I get more boxes so now for each box I want the origin because right now the origin is in the lower left corner I want the origin in the middle so I'm just gonna subtract 0.5 from that so right now this goes from 0 to 1 right and also over here from 0 to 1 and so if I subtract point 5 from it then I will just remap the middle point to be the origin so then you get that and now if we use over here in if instead of UV we use GV then we get a bunch of stars for the price of one which is pretty cool let me also visualize the edges of each box so we can see better what we're doing so I'm going to save GV dot X is larger than point 4 8 or GV y is larger than point 4 8 then make it let's say red so that we have a red outline on everything so we can see the boxes right so now what I want is for each box I want that star in a different position and if we want something different for each box then we first need a value that identifies each box and so for that I'm going to make an ID and the ID is just gonna be the floor of my UV floor so again my UV corner goes let's say minus 3 over here and then of the minus 2 and it goes you know you're gonna goes to zero and then it goes all the way to 3 over there and what floor does is it just rounds off or it just truncates the number so that we only have the integer component so I've said that many times before fracked and floor are our are two sides of the same coin basically so floor keeps keeps t integer component of a number and fracked keeps the fractional component of a number so if you add these two together then you have the original number that you started with so that we can also visualize this so I go over here and I say Cole dot rg+ equals ID now I can see that every box has a different color although over here it's saturated so you can't really see it but if I multiply this by a smaller number mmm maybe a bit larger than this well something like that you can see that every box has a different color but for every pixel in the box the colors are the same if you like if you don't take wait and like just ignore the star for now so we can use that to position to position these stars all right so to in order to position these stars we want these starts to be randomly positioned so I have to make a random number generator so for that I'm gonna go over here and again we've done this many times before I'm gonna make a hash function that takes two numbers as an input and it returns one number as an output so as an input it's going to take a vector to call it P and then I'm just gonna do this I'm gonna say multiply my vector P by some other vector 2 over here that is larger or on the larger side so now my P is is a lot larger than I was before and now I take the fractional component of that so now that P is gonna have an x and a y component that are somewhere between 0 and 1 and now I'm gonna add to that the dot product of P and P plus some other number and this is just some mathematical screwing around to twist the number in such a way that it that the end result looks around them even though it isn't really random so I'm gonna return the fractional component of P dot X times P dot Y yeah and and that just gives me a pseudo-random number and so we can look at that so if I go over here and I say call plus equals hash 21 of the UV coordinate then I get a bunch of snow television snow because every for every pixel that UV coordinate is different but if I take I D then you'll see that every box now has from value but inside of the box it has the same value so that's exactly what we want so now we can use that in order to position the the star all right so now how do I reposition this star well this star function makes a star at the origin makes a star around zero right and so if I want to move the star if I want it to appear somewhere else then what I have to do is I have to remap the origin to somewhere else and so in order to do that I could just subtract here something from that right so if I obviously if I subtract zero zero nothing's going to happen but if I wanted to move it up for instance I could just subtract a little bit from that position and now I can move all of them up or down or left or right and but I don't want to move them by a fixed amount I want to move them by a different amount for for each for each star so let me first make it that random value for each star so that's my hash 21 of my ID all right so now that's a random value so that's around them but between 0 & 1 and so now I could use that for instance in my X component so now I have stars that are randomly moved from left to right it's it's just that because this is between 0 & 1 and and my box goes from minus 0.5 to 0.5 a lot of stars actually move completely outside of the box we have to subtract point 5 from this in order to in order to get them all inside of the box still and now I need to do the same thing for y but if I'd use the N for y as well then I can only move stars on the diagonal which is obviously not what we want we want we want another random value for the Y and so I could use this hash 21 again with a different input but like another way of doing it is I could just do something like this well actually in here I could if I so my number and this between 0 & 1 I rode between oh and once between zero on one yeah so so if this is between zero and one and if I multiply this by let's say 10 now it's between zero and ten and now if I take the fractional component of that now it's again between zero and one but now it depends on where it where the original end was right because if the original end was let's say point one nine then if I multiply it by ten and I have one point nine and if I take the fractional component of that I get point nine so that's so I like basically I'm extracting another random number that is just that is just part of the original number but it's but it's past a certain decimal place and you don't have to multiply this by 10 that was just for illustration purposes you could multiply this by any number and and get another pseudo-random number out of it so and I know over here I would also have to do minus 0.5 in order to in order to get that random all right so now I've round them up down left right one thing here is if I multiply or if I subtract 0.5 from both the X and the y then I could just take that out and put that outside here so minus 0.5 and mmm what did I do wrong here oh yeah okay so I would have to put brackets around this two for for that to be correct right so if I don't want this brackets then I have to actually add 0.5 to get the same to get the same effect all right so now we have a bunch of stars that are all moved around now there is obviously a very obvious problem with this which is that around the boundaries it doesn't look so nice because these every box should really take it to account like the a potential glow or a potential part of a star or a part of a flare from a neighboring box right so so let's do that so what we need to make is we need to for each box let's say for this box we need to add contributions from from this star from this star from all of these neighboring stars we need to add the contributions to this box and we need to that for every box so that there are no boundaries no visible boundaries so I'm going to iterate through the local neighborhood of each box ok so each box has a local 3 by 3 neighborhood right and so for that I'm going to go over here I'm gonna say 4 y equals -1 and then Y is smaller than or equals 1 and y plus plus so this Y is gonna start at minus 1 and then the second time around is gonna be 0 and a third time it's gonna be 1 I'm gonna do the same thing for X so I'm gonna go over here I'm gonna say X and X and X all right and then I'm gonna stick that in there and I'm gonna stick this in there I'm gonna close my loops ok so now I have a loop that that goes through the well that loops 9 times and now I now four you'd like each time I get through this loop I have to add the contribution from a neighboring star right and so for that I have to get the ID for the neighboring star so that I can get a random value for the neighboring star and so for that I have to make an offset so I'm gonna do back to offset that is that is just the X and the y of my loops all right so so yeah it's gonna start at minus one and it's gonna end at at one and in the middle for the for the box that we're currently and as this off is gonna be zero so so that's so if I add that over here the offset then that's gonna that's gonna add the contribution from all of the neighbors and then I just have to make sure because this Givi here is it is if we if we want the distance to a neighboring star that's in a different box then we have to add this offset here as well because otherwise because this just calculates the the the distance with respect to the to the box that we're looking at so for that I have to over here subtract the offset so offset - okay and that should add all the contributions from all neighboring from all neighboring stars but I have to obviously say int over here otherwise it's not going to work and I'm over here also have to see int and that does that look correct well yeah I guess it is okay looks a bit weird to me let me see here now that's obviously still not good why is that not good look at him struggling with us maybe we should give him some time I figure that this is a good spots to stop part 1 of this video if you're a patron you can go to patreon if not you're you're gonna have to wait a week unless you're watching this two weeks from now or three weeks or a year from now and then you can get it right away oh okay yeah well we obviously still need to Paul op ghost goes on forever right so it goes on past
Info
Channel: The Art of Code
Views: 18,848
Rating: undefined out of 5
Keywords: ShaderToy, Shader, Shaders, Shader Programming, Shader Coding, Shader Live Coding, Live Coding, glsl, webgl, The Art of Code, shader tutorial, shadertoy, space, star, stars, universe, starfield, star field, part 1, computer graphics coding tutorial
Id: rvDo9LvfoVE
Channel Id: undefined
Length: 24min 26sec (1466 seconds)
Published: Mon Jan 27 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.