Bubbles Again: Simulating Soap Swirls Using FLIP

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] bubbles again by now you realize bubbles are one of my more beloved topics in computer graphics and i enjoyed covering building a soap bubble shader building soap film geometry and in general marveling at the beauty of soap bubbles however one thing we deliberately didn't cover yet is how to get those beautiful fluid swirls that happen inside of soap films and how to use a houdini flip simulation on a sphere to create high detailed swirls in a soap film shader so to finally build this setup in houdini i want to start by dropping down a sphere and diving in there then i want to set my sphere up to have only a scale of 0.5 that's just a value that made sense in my previous tests when i was preparing this one here and when i set the primitive type to polygon and increase the subdivisions here by increasing the frequency quite drastically to 96 like so next let's give this normals using a normal node here set to generate point normals and then let's attach a uv texture and give this one uv coordinates in our case i want to use polar coordinates and i don't bother about fixing the boundary seams just yet however i want these uv coordinates to be point coordinates and to visualize those i could either use a uv quick shade or an attribute from map which will just color these fierce points by using this uv coordinate here now i want to draw your attention to this area here that is where the uv coordinates wrap around that means one of the sides here has a u coordinate of zero and the other side here has a u coordinate of one now what happens when we blur the v coordinates here which we're going to do later you can see we are getting these seams that is because now the values between zero and one get blurred out and sodium tries to interpolate between those and to prevent these weird seams from happening there's a very simple workaround which i want to employ here which is basically just mirroring the u coordinate let me show you what i mean and let's drop down a point triangle and with the help of a bit of vex let's just remap our uv coordinate so our vector uv we want to remap the first coordinate that's the x should be equal to a channel ramp which we're going to call remap u and which takes us an input rx coordinate here let's create this ram slider here drag this down a bit and down here you can see the ramp we just created and in here what i want to do is just drag down this value here to a position of 0.5 so it sits flush in the center and create a new point here with a value of zero and now you can see we got rid of most of these artifacts here by basically mirroring this uv coordinate along the middle of this whole sphere and that's just to get rid of most of the visible artifacts that we would get otherwise if we would not do this like here next as i want to use a flip sim for my soap film and a flip simulation is always a combination of particles and volumes i'll have to create the particles which i'm going to use in my case i want to use the new scatter and align node here which i'll wire below my pointer angle here highlight it i want to set the point count method to point spacing here and later i will link up the spacing to another parameter that i'll create in my flip sim however currently i just want to uncheck minimum spacing and set the spacing manually to 0.01 which gives me this distribution here a bit random so let's relax those under point generation here let's increase the relax iterations to 128 and also let's increase the coverage up here to one so now we have uniformly distributed points on that sphere new middle mouse on it we can see around 36 000 points which luckily have the normal and the uv attribute with them now i want to set the p scale of those individual points explicitly using an atrip create i'm going to call the attribute p scale it's going to be a point attribute of type float and in this case i want to set the value to exactly half of this point spacing here so let's right click on this copy parameter go to our create here and as our value just in here let's right click and paste a relative reference so that now is a value of 0.01 and let's just again click here on the name go to the end of this expression multiplied by 0.5 so now we're getting always exactly half of the value that we have here in the point spacing and i think we're good to feed this into a flip simulation just to find this a bit easier later let's attach a null and call this one out underscore particles save this and drop down a dot net in which we're going to build the fluid sim which i'll set up just below the out particles here and dive in there and in here what we need are two three things a flip solver to solve our flip simulation and to keep the data necessary for our flip sim we need to attach a flip object as well which goes into the first slot here in the flip object the first thing i want to do is exchange this visualization here so under guides particles let's set the visualization to be particles those tiny points here that's better then i told you i wanted to drive this initial particle spacing here this value by some attribute that we're going to set up in the flip sim and this attribute is the particle separation so let's set this to 0.01 right click on here copy that parameter go up into our scatter underline highlight this and right click in here and paste as a relative reference so now this one is linked to the setting we have in our flip sim down here next let's bring those particles on that sphere that we created under the initial data tab here in here we want to bring in a particle field and let's point it to that out node we created the out underscore particles here except that and now you can see we brought in those particles the grid scale up here is a scaling factor for the volumes that flip internally creates to solve pressure and divergence fields and a default of two will just multiply this particle separation by 2 resulting in a slightly coarser volume and the default of 2 just worked for me however the particle radius scale becomes important later when we're trying to push and keep those particles apart and in my attempts a value between 5 and 4 usually worked out well so i'm just going to set this to 5 for now and gonna go to the flip solver and set that up so a few of the main settings necessary to keep those particles apart evenly and have the simulation not collapse in later frames are the min max sub steps and the cfl condition what that drives is how many sub steps how many iterations the solver runs and as with every solver in computer science we have numerical errors and they accumulate over time and what we do with running this over and over again for more sub steps is we're trying to minimize those numerical errors so in my previous attempts in my previous tests maximum substeps of 4 with a cfl condition that i lowered to 0.1 were necessary to keep the simulation together what that means is if a particle in a subset of a simulation travels further than 0.1 units we have to run another iteration of simulation in order to increase the precision next let's go to particle motion and in here i want to disable reseeding reseeding tries to keep the particle density constant by killing and respawning particles which in our case can become a problem as this reseeding interpolates the attributes in our case the uv attribute which is the main thing we're caring about and this can make the simulation appear to pop and flicker instead what i want to use to keep the particle density constant is the separation here on the separation tab so let's check that and in here i want to increase the separation iterations this is similar to the point relax or the relaxation on the scatter node so here we're just running four iterations to push apart those particles so they're more evenly spaced next for the volume motion so the behavior of the volumes that we're going to create the overall limits so the size my simulation can never exceed is 50 by 50 by 50 units which is quite a lot for this sphere here so let's dial that back to maybe two by two by two and up here we can choose between two methods for transferring the velocity from our particles to our volume and back in my case i want to use the apic the swirly kernel as that keeps the uniform spacing on this whole sphere a bit better than the splashy kernel the only other thing i want to set up is in the solver tab here where when i scroll down here i enable use opencl that depends a bit on the type of graphics card you have and the vram available on your graphics cards in my case my gpu is able to handle the situation and it speeds it up a bit not massively but a tiny bit and i'm happy to take any speed up that i can get here okay let's save this and finally for our simulation we need some forces in here something that stirs around these points of it so we get a bit of the swirliness and in my case i want to use vex you could use vops let's just drop down a pop-up and dive in there and in here could use the really nice curl noise which has lots of settings to generate a curl noise from all those underlying noises and it's got quite a few parameters here to dial those in and especially creating those noise and noise parameters in vex can be a bit cumbersome however there's a neat trick to be able to use those functions that exist involves in your vex code as well i'm going to show you how so let's go back to our simulation here and drop down a pop wrangle like this and this one goes in the last slot of the flip solver like this so the trick to be able to access all those nice functions in the vops let's drop down a pop-up again and drop down this curl noise down in here just wire it up for now p goes into position and let's just take the output again to the position here let's go up and right click on the pop-up and go to vex bop options and view the vex code so all these bobs do is just generate this bunch of vex code and this is really verbose and a bit unusual however you can see down here we're calling a noise function and that's our curl noise and this function hides in a library that side effects developed called the voplip here so let's just copy this line of code here and paste it over in our proper angle here and now what we did is we imported all those functions available in the box here namely these two curl noise function and one expects a vector 3 and another one expects a vector 4 as an input in our case as we want to animate this we're going to use the vector4 using a vector containing three coordinates in space and the fourth will be time so let's just copy this line here like so just copy this one close this head over into our proper angle and let's just paste this one here and comment it out for now otherwise this will result in an error so what we're going to do in here is first we'll create a vector a vector 4 which we're going to call sample position or sp pause and we're going to set this vector to something and this something that i want to set this vector to is going to be another vector in this case vector 3 which is just my current particle's position times frequency in our case let's use it times 2. so this will make sure our position is varying quicker in space and let's call this vector my p for my position so i want to set my new vector to my p dot x my p y and my p dot z and as a fourth argument i want to use our current frame number let's slow it down a bit so multiply this by 0.07 again this value here and this here was just out of experimentation when i set up and prepared this file here also let's get a normal so i'm gonna create another vector call this one my n for my normal and it should be equal to my current particle position but i'll just normalize this which i can do as all of my particles are supposed to reside on a sphere with a center of 0 0 0. next let's finally take this noise function here and put it to use so again let's just copy this one here and create another vector which we'll call i don't know nse short for noise let's paste this function down here so lots and lots of code going on here let's drag this out so this one takes in a position in our case we're going to use the sample position here so sp pause so this one here is the noise type this should be the frequency offset and default position and for now i'm only interested in those two parameters one is the roughness let's set that to 0.8 and the other one is the turbulence which i'm going to set to 5. so now we generated this curl noise vector called nse using this function that we get out of vops so let's take it to some use by first checking its length so let's create a flow called a for amplitude which is equal to the length of our noise vector and next we want to make sure that our noise vector has exactly a length of one so we're going to normalize it like so now let's create a force vector which will push around those particles let's call it at force boudini standard for the force vector and in this case i want to make sure that the force is always perpendicular to the surface here and i can do that by using a neat mathematical trick called the double cross product so i'll take the cross product of my normal here my surface normal and our noise vector and for that it's important that both my normal vector and my force vector have a length of one and then i will take another cross product of that result so again against my normal again and now to give it back its strength which might be varying i want to multiply this by the original amplitude and then by another scaling factor which just determines how strong the overall effect is in my previous attempts a value of 0.25 was good in here finally the last thing i want to do per simulation step in here is make sure that all those points after they've been advected around and moved around the sphere are projected back onto the sphere's surface by setting the point position to the normalized point position again and as this sphere has only a radius of 0.5 let's multiply this by 0.5 like so okay quite a bit happening in here let's go over this one more time up here these four lines import the library that we're going to use later to create this curl here then these three lines here just create a four dimensional vector with the sample position consisting out of our coordinates in this scene here which have been multiplied by a factor so they change a bit quicker make the noise a bit more interesting and the time which we multiplied by a quote unquote slow down factor to make this whole thing move slowly finally we created a normal just out of our position because we know all of these particles should be on a sphere which is centered around the origin of zero zero zero so we can use that shortcut here then we use this quite elaborate curl noise function from our vap lip to generate a curl noise and for that we fed it the sample position as p pos here then we measured the length of that noise vector because now we have to normalize it in order to use it in this double cross product trick to make sure my force vectors are perpendicular to the sphere surface and then as we normalize this vectors here so they all have a length of one we are multiplying back the original length so scaling the original strength of force back in and multiplying this just by an art directable factor and you could break that out into a slider as a parameter for your artist to drive how strongly this whole force field influences our simulation finally after all that's been done we are making sure each step in our simulation that our particles are still on the sphere surface here by moving them back to their normalized position and as this sphere has been scaled down so it's got a radius of 0.5 and not one we'll have to multiply that in here okay that's it let's save this go up one level and let's just keep our fingers crossed hit real time and hit play and you can definitely see something happening here let's try and visualize this again using an ad trip from map to use these points uv attribute here to color them so in here we can see if we switch our background to dark so i just pressed d over here to bring up this menu now we can see we are getting the seduction in here and maybe just maybe i have to tweak some of those parameters because that's quite an intricate noise however let's just roll with it for now so in order to create a soap bubble that i can render and shade i'm just going to create another sphere here again making sure its radius matches the original sphere setting its primitive type again to be a polygon and in here i will give this again quite a high subdivision in this case 128 subdivisions resulting in a really really highly subdivided sphere next i'm going to use an attribute transfer to transfer the point attributes from my simulation onto that sphere here and let's move the attribute from map down here highlight it so we can see what's happening here in our attribute transfer everything is already set up as we wish so what we can do if we skip through this we can now see we are projecting those uv coordinates from our original points onto the sphere here and you can see that due to the spheres cause resolution and the quite few points actually only 36 000 points coming out of the simulation here you can see that my uvs are a bit jagged and rough and we can fix this by as mentioned before just attribute blurring the out of them just wire this in here set this to uv attribute and now if we give this like i don't know two or four iterations we can see we are getting smooth attributes again another thing i want to do before we go into shading this is generate an attribute which describes the sphere's film thickness the overall thickness of the wall of the sphere so to speak because what's happening in real life bubbles and soap films is that gravity pulls down the liquid down here so the sphere's walls are thicker down here than they are on top which makes up lots of the effects that we're seeing in spheres so again let's use a bit of vex here this time a pointer angle and in this case we want to read out a relative position within this object's bounding box let's call this vector relative position rail p equals to rail b box which returns a relative position in a bounding box ranging from zero zero zero at i think the bottom left corner to 1 1 1 at the top right corner we're going to find that out in a second so this takes in our zero input slot so this one here and it evaluates it against our current point position let's just visualize this one and maybe write it out like this again in the visualizer let's set this one to relp for relative position and yeah you can see in fact that's what it's doing okay also what we can see here those artifacts here which look a bit like those swirls are the normals which get transferred so maybe we want to exclude them up here just going hat in so now we're not transferring them basically all i want to transfer here is just the uv coordinate nothing else so if i put uv in here and uncheck primitives you can see we're now only transferring the uv coordinates all right back down here to our point triangle let's take this relative positions y remap it and remember to a thickness so let's call the thickness maybe f at t thickness equals to channel ramp that means a ramp let's call this one bubble wall thickness and we're going to use the relative y position here let's just delete this one and in our visualizer let's just visualize the t just created and all we have to do on our pointer angle here is create our ramp by clicking here and now i want to have this thing very thick down here and very thin up here so let's just switch around those points here and maybe let's dial in this ramp a bit by setting this points to be a b spline this one as well let's move this over to maybe 0.1 and create another point down here and let's set the position to 0.3 and the value to 0.2 like this again trial and error when i prepared this setup but this curve resulted in decent shading okay only two lines of x and a bit of curve tweaking here one last thing uh soap bubble is never perfectly spherical so let's just abuse the mountain sub to slightly distort this bubble and that's a bit too drastic so let's set the height to 0.1 and the element size maybe to 2 dial back the maximum octaves to 2 and let's write a short expression in here so we can have this animate here over time so dollar t is the current time and let's multiply this by 0.2 to slow it down a bit so if we now hit play we can see this slowly wobbling undulating bubble here let's skip to maybe frame 72 and let this simulate a bit and after a while we're there let's just attach another null call this one out underscore bubble all right now let's shade this and this time i want to use octane again because i really like its thin film shader if you want to share this in redshift we released a free acid and a tutorial about how to use a thin film shader inside of redshift however this time i just want to stick with octane so i'm just going to close all these tabs here pin this one hitting ctrl t three times when i set one tab to the out the other to the shop and the second one to the matte contacts all right let's create a camera by control clicking on the camera in here and go to the obj context go up again here and make sure the camera is pinned to the viewport and zoom out a bit so i have my bubble framed here also let's create a backdrop for this bubble using a grid which i'll wire in below the camera and in the grid here i'm going to set this to be an xy plane go up again make sure my grid scale on the x is 1.7 which is just about the aspect ratio of 16.9 and then let's just give this a negative coordinate of i don't know minus 50 and scale it up again until it fills the frame like this in my octane tab here i want to create the render target and the octane node i want to head over to the shop where i can set up the camera and the environment here on the render target so i want to set this to be a path tracing and want to use a texture which i'll set up in the text environment by pointing this to a file which i downloaded from hdr haven which has a gamma of i think one and then in the matte context i'm just going to create two materials two octane vap mats call one bg for background and the other one bubble let's start with the easy shader and the bg i'm just going to drop down a diffuse material which i'll set to a darkish gray color let's go with this wired up here and in the obj context i'll assign this to my grid by going to the render tab here and pointing the material to the material i just created called bg let's do the same thing for the sphere here and in the render tab here i want to point this to the bubble material i just created okay let's just for fun render this by going to the ipr and here you can see that we haven't set up our bubble shader yet so let's close this again and create our shader in the matte context let's select the bubble material here and go in there so the main material i want to be working on is a specular material which is kind of the refractive material in octane goes into the out here again let's keep the ipr open so we can see what we're shading here so you can see now we have this solid glass ball here which we don't want so down here let's check thin wall and now we have this thin walled bubble also as for the ior i want to set this to 1.33 the ior of water and i want to set my film ior to 1. as we are looking at thin film interference here the main thing we're interfering with and we're refracting off is air so let's set this to one all right now what i could do is bring in my attribute that i've written out called t for thickness to do that in the obj level on my sphere i'll go to my octane tag here and under attributes i want to make sure that i export this flow attribute i created on the points called t and in the bubble material let's apply a float vertex attribute node which also reads in the point values here i want to read in the t the thickness and just for fun let's write this in straight into the film with the width of our thin film which generates all these interference let's reload our ipr here and you can now see some of this interference pattern starting to appear here where the sphere gets thicker gradually let's see if we can bring out this pattern a bit better by tweaking our lighting and maybe our camera settings in the shop octane render target here but first let's in the material for our background here maybe make this a good bit darker by setting its value to 0.01 like so or maybe even further 0.005 like so it's now in my shop render target here what i want to do in my texture environment is increase the power here to maybe two or even four to give this a bit more stronger reflections also let's see if by rotating this hdr here around its y-axis let's see if we can increase the shading or improve the shading here [Music] and i really like what's happening when i rotate this 120 degrees so i get these types of reflections here okay now let's bring in some of that swirliness we just created so let's close this for now and in our material again let's go to our bubble material here i want to use these uvs that i created and that swirl around to get some additional detail in our film in here and there are two ways that i found useful in doing so one is just using an image texture in our case a grayscale is completely sufficient and i want to point this to a file i downloaded which comes from texture haven and it's just tiling rough plaster brick texture which looks like this and i'm loading this in as a grayscale image and this by default is set up to already use the uvs that we generated so i'll just wire this into our film thickness here instead of the t attribute that we created and restart our ipr and now i can start seeing some stuff happening here especially if we tweak those texture values here by inverting it and setting its gamma to one so now you can see some of those turbulent effects happening up here and coming through also to make this a bit more prominent we can use a multiplier to dial in how thick the overall film is here by dropping down a multiply node in this case called multiply texture which you're going to wire in here and we want to use a single float value to drive this thickness which in our case is called a color grayscale so wireless up here and now by multiplying this image's values by this single value here we can drive the overall film thickness and thus the overall strength and color of our interference pattern like so let's mix in some of that thickness down here however i want to be able to also control the overall thickness scale so let's copy those two nodes we just created paste them down here and just wire our thickness in here so we have a multiplier for this as well and then let's just add those two together using an add node my texture here my thickness down here and again let's create an overall multiplier for the overall texture we created by mixing those two here like so and this node tree finally goes into our film width here let's just make sure and refresh the ipr here and now we both have the thickness as well as these swirls coming from the texture in here in my previous experiments a multiplier of 1 for the texture 2 for the thickness and then to bring it back into a 0 to 1 range 0.33 as the overall strength proved quite successful in bringing out those swirly patterns here you could in the shop render target here now under the imager for example check neutral response and add a lot here for example i think the portraits down here for example the portrait 800 are quite contrasty and then to compensate increase the exposure or maybe dial back the gamma to give this a bit more contrast and maybe add a bit of saturation here to bring out all those beautiful interference colors here also maybe let's add a bit of highlight compression so we don't burn out those highlights as strongly and also make sure we are saturating to white a bit so we're not getting those overblown colors so maybe 0.25 here all right that's a good bubble however what if we don't want to use a texture or if we don't have one well instead of using a texture we could use noises which are also mapped onto these meshes here and onto these bubbles here using the uv coordinates we generated using that flip sim so to do that let's copy most of that tree here except the texture lookup and paste it down here and wire it up to our film width cut the texture here and instead of a texture we want to multiply two noises together i could use the single noise i just found it gave a bit more detail if i multiply together two noises so again i'm gonna drop down a multiply texture node which goes into where our original texture used to be and in here i wanna pipe two noises so procedural noise and to drive the mapping and the scale of this noise i want to attach a transformer projection node here which is going to be a projection uvw which reads in our uv values and uses that as a basis for the noise and then a transform 3d where i can dial in the scale and offset of my noise like this so the only thing i want to change here is set my scale to 0.25 on all axes and then in the noise itself let's drag this down let's just set it to circular copy these three nodes here and paste them below and in the second transform here i want to set the scale to three by three by three so a bit bigger in the noise itself i want to set this one to be a purlin noise and let's just multiply those two noises together and hit refresh here just to make sure and now we can see we also get a really nice swirly pattern here which although our uvs are quite coarse admittedly has lots of detail one final trick to add more detail to this is to take these noise or these noises in our case i'm just gonna take the top noise here and take this value that comes out of it ranging between zero black and one white and remap it using a gradient wiring listen to the input and going to the output and hitting update here on our ipr nothing changed so instead of just having these two values here i want to add a bit more variation to this let's just take a snapshot of our current rendering here and make sure we are disabling aces here like so and now let's work on this gradient here let's add three notes one in the center 0.5 one at 0.25 and one at 0.75 and i want to make the center one a value of 0.2 the edge ones i want to make black and those two middle ones here at 0.25 and 0.75 i want to make them white so now we're basically having twice as much frequency twice as much change in the values we're generating here again let's just reload for good measure let this converge a tiny bit and then snapshot it and compare it to our previous rendering here in rm play so you can see by adding this ramp we added quite a bit more high detail noise and you make up your mind and you decide what you like better it's just another technique of adding more detail into your shading here i must admit i like both quite well maybe i'll just go with the first one in this case all right that is how you create a flip fluid sim to generate those swirly patterns on soap films if you want to know how to use the generated data here in unreal and create a similar appearance for a bubble in unreal just let me know that might be a good topic for a future tutorial and in general if you want to learn more about houdini or unreal gain access to more in-depth courses or just plainly want to support us you might want to consider becoming one of our patrons and to all of you guys already supporting us huge thank you by now you know that without you guys and tag mine this form would not be possible and a very very special thank you goes out to important looking pirates patrick fillion and riffey canado thanks so much guys so until next time as always it's cheers and goodbye
Info
Channel: Entagma
Views: 15,629
Rating: 4.9805193 out of 5
Keywords:
Id: 7YVAD-BHsYU
Channel Id: undefined
Length: 29min 53sec (1793 seconds)
Published: Mon Dec 21 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.