Random paint effects - HTTP 203

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
120. does that mean that doesn't mean we've done 120 episodes i mean 120 120 things like that including trailers and stuff but yeah i think actually i think new ones these ones have a little close to 100 episodes because we had another little in between but yeah it's close should have bought a cake anyway just like one party pop-up [Music] okay today i want to talk about random paint effects random paint effects this is paint effects but random yep absolutely um nice this effect is done with a css paintwork like newfangled technology um yeah i didn't make this uh this was done by george francis i saw this codepen oh pretty lovely in it look at all look at all the colors and i i wanted to recreate this uh i wanted to start with you know the simplest solution in my head we're like oh i can do better well well yes of course well no actually because the reason i'm saying this is the first solution we're going to look at is way worse than what george said i'm not going to this is not making fun of someone's code i'm going to start deliberately a lot worse than what george did so we can discover make it more realistic for what you would usually yeah and so discover some of the problems uh here to solve in order to make this work uh i would say if you've not if you've not seen css paint workloads before we have this lovely website houdini.how yeah because you can use them to do different border effects which is i think it's actually a really good key use of this uh because if you've got the box with the arrow coming out of it speech bubble thing speech bubble or tabs which have the rounded corners on top but also the the outward rounded corners can do those kind of no easily at least well you end up just using a bit of svg or something but then you're locked into the color the one color that the svg is using or what anyway paintworklet lets you destroy it with javascript and it's all good uh but i wanna talk about these random effects yeah because i think there's a lot of interesting problems to solve here how do we start doing this so i'm gonna start off with a little bit of css this is newfangled at property uh this is where you define a custom property and give it a title the javascript version to declare a custom property with the type has existed longer but now we can do it declaratively hurrah yes i do i'd forgotten that there was a javascript version for this yeah it always annoyed me because you know you you kind of feel like wait i'm already declaring my properties or you use your properties in css but you haven't really told the browser what they are and then later on javascript like eight seconds later kicks in was like oh by the way it is a number exactly and and that's what this is doing right it's really just giving it a type which means it can animate it and that's really important yeah because you couldn't animate these properties before if you had like you know if you had red and black and you had a transition it would just snap because they saw them as two strings it's a string so here we're saying color plus which is some colors separated by space and give it a default value which is great to say it inherits all of that sort of stuff i like fleck by the way that's not me that's georgia so he he picked a name for it so german for steam is it yeah so it should be paint stains it's a paint stain i see where you went with fleck it is better isn't it um i know we've got the count as well which is how many stains we're going to make on our canvas and uh and then here is this is just us using that stuff so give it a background color give it some colors and for the background image use this fancy paint thing yeah paint my stains and give it a a name which is in this case fleck the rest of our work is going to be in javascript that's the whole point that's it well it's not well no but that's the main thread that yeah uh the rest of the work is going to happen in this magic workload thing uh and here's what this looks like so we're going to give it this name fleck that's what we used in the css and uh give it a class and the first thing i'm going to say is like here's the properties that i care about yeah for this thing because this way the browser knows when it actually needs to repaint if a property changes that you don't care about no need to repaint and that's actually quite a nice optimization yes so that means if you change like text color um it knows that this background drawing is isn't part of that it can use the cached version it can use a cached version it's good so we carry out the count care about the colors and now everything else happens in this paint function so we've got uh there's this context object which is like a 2d canvas like ish pretty close i think it's some stuff missing like text yes and some bitmap stuff it's a subset of 2d canvas so it's very familiar uh and then we've got the bounds there the width and height and then these properties which is the stuff we've asked for it makes a lot of sense and there we go get the count get the colors by the way this is type 2m so because flat count was declared as a number we will immediately get a number with colors we will get an actual color and can even tell and i think you can even say stuff like give me this as an hsv or as a hexadecimal i think in this case it just gives you as a string but i'm not 100 sure it would make sense and maybe that's the message between type to m and the spec and type to end what has been implemented yeah it could just be something that chrome hasn't done but yeah that dot value comes out as a number if we didn't do that property thing before it would come out as a string because it wouldn't know any better that's an important part of it and now we're just going to draw blobs uh so for however many for the number that we want to draw i'm going to draw a blob and if you wanted to know exactly how i was going to draw that blob you're going to be disappointed because i'm just going to hide it all behind this function and pretend it doesn't exist i'll put the code in the description if you want to take a look at that i don't think it's the interesting part i actually reused the blob code from squoosh ah yeah you spent a lot of time on that one yes exactly just use circles but fine getting my money's worth i worked out how to draw blobs uh so yeah and now i'm just going to say you place that at a random x and y so random between zero and width height whatever random size um it's a little bit more complicated than that i always say like just no bounce just any size yeah uh let's pretend that a size between zero and one is fine uh which is what this case is it's not the relevant part the interesting part yes if you want to see have a look at the code in the description and then just a random color there make sense drop down cool oh here's a random function that is the standard random function it will get you through a google code interview maybe probably so i mean there's some good maths going on there look yeah minus and plus like a minus from in a plus form that cancels out so you know should have done a yeah a divide in there just to just to you know use all of the operators there aren't any more operators out there it's just those exponentiation you can do a double star well we'll get there later on hold on to that oh boy um so here's the result pretty yeah well then you what i'm gonna do i'm gonna animate the width of it don't animate with it's a bad thing well so i am animating with here but that this same thing could happen just with the contents changing that changes the size of the element yeah and yeah it was random in it here's an interesting one i'm going to scale it so you saw it change right at the start but then not for the rest of the animation and that is because of layer promotion so because it's yeah chrome does its scaling on the compositor thread as it should on as a texture and so it had to do a paint right at the start to lift that into its own texture does the scale and it just does that as a bitmap scale so you're not seeing that random thing that also gets slightly blurry no no bad sermon incorrect no it will draw a full resolution that's the the promotion because it because it's a declarative css animation it will uh draw a full resolution at the start because it knows like it so it's a big resolution scaled down rather than a small resolution scaled up exactly that it looks a bit blurry you just need better glasses mate i think that's what's going on here uh yeah but now we're talking about a chrome implementation right like the effect we've created is leaking chrome's implementation this is going to work different in other browsers yeah some people are sensitive to flashing images that stuff is happening out of our control so we're going to fix that let's fix it and the way we're going to fix it is using seeded random numbers this has been one of my long one of the long-standing issues i have with javascript because we have math.random we do great but you can't it it is a pseudo random number generator so it it has a seed and it calculates those random numbers but you can't control that seed you will always get new random numbers which maybe sounds desirable at first but in many scenarios you actually want to recreate the same random sequence of numbers which is exactly what we want to do here uh so this is mulberry 32 it's a good name um let's go through how this works now i'm going to go i have literally no idea hey it looks smart though it does it looks really clever there's a lot of math i think it's the kind of the math dot i'm all integer multiplication to make it extra fast yes and that is why i use this okay so this is a a random number generator that uses 32 bits of state whereas the one in chrome uses uh 128 120 the only reason i know that is because whenever i need seeded rng in javascript i look up this old block not even that old on blog post on v8.dev where we had a report that the rng that v8 uses isn't actually random enough and people had found a couple of images where they filled in random pixels and you could see patterns yes and so we post a blog post hey we have a better rng now it's called xor shift 128 i think and in this blog post yes just like this one little function cpus plus and always copy paste that one turn it into javascript and i have seatable rng yeah the reason i picked mulberry 42 is it it was it's the smallest and the fastest and yes because it's got 32 bits of state rather than 128 it's number's going to come back round more frequently but we're still talking about the billions or you know worst case i guess yeah and also what you want to do with this is you want to create blotches on the screen yes don't ever use either of these any of these for cryptography because for cryptography you don't want pseudo-random numbers you want actual random numbers yes which is why we've got crypto.org random values i can't remember it off the top of my head it's encrypted somewhere it's in crypto somewhere we do have an actual random number generator all right so we're going to use this instead of math.random uh because it means like i can give it a seed called next three times get three random numbers and later random to me it looks it's definitely like even just from those three we know it's going to be random and is this random yeah look at it big long numbers and that one starts with seven one starts with a one wow it's the same ones every time with the same seed but if you change the seed you get different random numbers which is exactly what we were talking about um so i'm going to add another property so people using this can provide their own seed so they can have different patterns different fits on the page you could animate this if you really wanted to because you would get that random effect back of it drawing every frame uh whatever here's how i'm going to integrate that so the seed is one of the the input properties there and down here get that number pass it to mulberry 32. there's our new random number generator oh and here instead of random it's random.net makes sense ta-da there we go here it is yeah moment of truth [Music] there you go that was uh different this time it's not random anymore it's not not changing every frame yeah all right look at the way [Music] very good i i kind of expected the the blobs to grow but i guess from the code it's actually the the the blob size was independent of the canvas size while the position is not so like yes again it is exactly happening as you wrote it down but it just yeah yeah at first it sort of looks like it the canvas is stretching but those blobs are all staying exactly the same size and shape yeah it's the centers that are just being stretched exactly and that does have a bad side effect i think it's like this looks very sparse and this is quite dense and that can probably be quite undesirable if i think about because you might use it on a very small element as a background image in the corner for a sidebar but also as a big background image for your header or whatever but you would want them to look consistent exactly and it's going to look not consistent inconsistent that's the word we have for that word professional so we're going to fix that um what we really want is instead of a count like a you know static number for every box we're going to make it identity so it's not an integer it's going to be a number which means we can use decimals and this is going to be the the chance of each pixel being a blob or something yeah or something like that whatever that's what i went for um so yeah not count density and get that number and our count is now just going to be width times heights times density job done that makes a lot of sense here it is and there we go this is quite a nice effect i think i feel like for cases where you don't animate this is good right if you just use them once cool yep but obviously you know sometimes these things happen someone resizes their window or portrait to landscape and then you have it looks a bit odd i guess yeah it could it could be annoying yeah i think it's fine i think what would be classic css behavior would be it just reveals more blobs yeah you kind of want to actually have just a really large image and just use a crop and then you make it bigger which is obviously hugely wasteful yes but that would be the nicest effect around this so let's achieve that effect but without the waste and the way i would do that is by splitting this up into a grid and we are going to deal with each cell independently so we're going to pick a number of blobs to put in each cell deal with that and then move on to the next cell and we only create as many cells as we need right and so you have you have maybe a tiny bit of wastage which you can see around the corner i guess because you know not every can the size will be perfectly tileable with your tile size but i mean that's the very definition of trade-off yeah right so yeah i used 300 by 300 for these cells if you use one that's too small then it's going to start looking too uniform because it's you know going to be placing 50 blobs for each tiny little square it's going to look too uniform if you make it too big you get more of this waste yeah so whatever 300 i didn't do any science to pick that number i just went 300 and it looked fine so i stuck with 300. so let's let's implement that we're not using density anymore it's now going to be per cell count per cell whatever that makes sense going back to account uh and so cell size 300 we could make that configurable yeah like whatever whatever and then um yeah the purcell get that from the the type 2 m and so instead of iterating over just the number of blobs we're going to draw we're going to iterate over the columns so x you could start with y it really doesn't matter then we're going to do y now we're dealing with the the cell level and then for however many we're going to draw per cell we're going to draw one of these blobs so instead of these things being between zero and height and zero in width it's going to be somewhere within that cell that makes a lot of sense job done here it is and uh pretty tada job job solved done end of episode i i was just thinking because when you had the numbers you were go iterating over them in in column major as it's called is that what it's called okay yeah okay what what happens when you animate height yeah quite well quite wet right it's all gone wrong that works on the x-axis it's it's a 50 percent improvement yeah that's fine just don't animate height you know and genuinely i didn't see this coming the way you did uh here's what's happening so we've got our different cells and keep an eye on cell number two we'll say and as we resize it down it moves and this is the problem here is our cells are moving around yeah uh yeah number two specifically there with that dark blob at the bottom just left of center you'll see as we it's to the right of number one and then it becomes below number one and it's the same cell because we can see those blobs are in the same place yeah we've created a problem we don't want those cells to move around so the solution use coordinates oh yeah so my mind your friend you basically you you turn those coordinates into a seed for a new number random generator for each tile pretty much yeah pretty much so the benefit of this is yeah no matter how wide or tall it gets like these cells aren't going to move around because they've got both their exposition and their position like it's it's fully coded into it the way i achieved this you might have done it a different way but i created multi-dimensional random numbers oh that's a mouthful doesn't sound clever doesn't it it's not actually that clever but it worked and it worked because i actually in the end needed more dimensions than just x and y because we've got like a count that the number of blobs is a kind of it's like a third dimension to these numbers right because maybe in a scenario you might want to increase the count but that doesn't mean that you want all your blobs to repositions you just want once to be added on top of what you already have so it makes sense to model it as an additional dimension yes exactly and that's what i did i added this fork function to a mulberry thing oh that's very elegant i like it better than my version it's well and here's our exponential um so this is just creating a new mulberry 32 and it's using its own random number generator to create a new seed uh between 0 and 32 right so that means just like the the number sequence of the fork fully depends on the current state of the current rng and so it's completely reproducible despite having multiple yeah dimensions like i guess it's the right word even though it sounds very pretentious it does sound pretentious um it just makes me feel smart though so i'm going to stick with it i did the original solution to this was just incrementing the seed by one and you're wrapping it at 32 bits but that became observable in the css when you were increasing the seed you could see that it's like oh yeah i just handed hands it down to the next dimension then doesn't it yeah you can see that stuff shifting around it's like oh that box just moved over there when i increased the seed where you would have expected it to be completely different yeah but yeah anyway so that's what i did uh so now uh oh the only thing we have to change is down here we've got our random number uh generator at the top random number generator so to speak the root number yeah because because we still want to be taking that seed into account you change the seed we want everything to change we fork it for the columns we fork it for the cell and now we have a random number generator that is scoped to that cell and anything that happens to that is not going to be affecting the the stuff that happens in in other cells and yeah so now um instead of random we're going to be using cell random and that's it do the animation i want to see it oh my god we've seen that one hey that's nice and i really like this effect because it gives this impression that it's an infinite by infinite canvas right that you can just send it by infinite we're drawing all the memory yeah yeah but but it's optimized so when it's small it's it's you know just placing a few random blobs but when it's big it's having to you know that work is scaling up which is exactly exactly what you want it gives the illusion that that stuff is all there all the time and it is like you make a small you reveal it again those dots are in the same place because it's using the you know the seeded random number generator so yeah for for this kind of like generation of art you really that you want to have random in there but you want your random to be deterministic because you want to be able to reproduce it that's as counter-intuitive as it may seem exactly make it deterministic with css your random needs to be not random like it just needs to look random and we i see a lot of um it's obviously early days for css paint worklets but a lot of the random effects have this problem where you change the size of it and it completely redraws george francis that blobs thing he he actually used mulberry 32. he didn't have this problem uh but a lot of them do so if you want to fix that this is these are the sort of techniques you use um all the code will be in the description go and have a play um [Music] what did we say last time [Music] so so
Info
Channel: Google Chrome Developers
Views: 12,351
Rating: 4.9623232 out of 5
Keywords: purpose: Educate, pr_pr: Chrome, series: HTTP203, type: Interview, GDS: Yes, random paint effects, http 203, http, http developer, developer, developers, chrome developer, chrome developers, google chrome, google chrome developers, google, chrome, Jake Archibald, Surma
Id: ALKqavp9Fg0
Channel Id: undefined
Length: 22min 2sec (1322 seconds)
Published: Tue Aug 31 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.