Create Realistic Bottled Liquid in Blender [FULL TUTORIAL - Cycles/Evee - Nonphysical Approach]

Creative 3D objects
9 followers
Hey there, this video is all about making bottled liquid with Blender, which is riveting, I know.
To do this, we're going to be taking a non-physical approach to rendering static and dynamic bottled liquid with both Cycles and Eevee.
So let's get started with that.
First thing we'll need is a bottle.
I'm going to add a subdivision modifier to our default cube to start, and then set the subdivisions to something like 2 or 3.
Now it's time to set up the basic shape of our bottle.
I'm selecting all of the faces like so, and then scaling them down along the X and Y axes.
Once we're done with this, it's time to select the top and bottom face, then crease them using Shift-E.
Then extrude the bottom face down to create a beveled base.
Now we're going to add two edge loops that we can scale in order to modify the shape of the body of our bottle.
This might also be a good time to tweak the base to make sure that it all lines up properly, so that nothing is disproportionate.
Selecting the top face, we're going to create the rim of the bottle by extruding up and then scaling down.
Extrude it again to create the spout, and then tweak that to your preference.
Now we're pretty much done with the bottle, so we can just delete that top face. This will be important for later.
Moving on to the cap, select the edge loop around the rim, duplicate it, and then extrude upwards.
I'm also going to tweak this edge a bit now to make sure that it fits with the flow of the bottle,
and then fill in that top face with F when we're all done.
Now I'm going to bevel this face here on the top, but I also want to go for that nice smooth effect.
So to do this, I'm going to open the bevel menu, set the segments to 2, and then the shape to 1.
This works with the subdivide modifier to create a smooth edge around the cap's top.
I think it's also a good idea to tentatively move the cap up a bit so that it doesn't obscure the spout of our bottle.
We're going to need to see that now, because we're going to add the solidify modifier,
so that we can add some depth to this bottle and its cap.
You might also want to tweak the thickness value a bit, like I'm doing here.
And I think that looks pretty good. So in just about 2 minutes, we've finished the model.
Now we can get on to the shading.
First order of business is to enable smooth shading, which helps a lot already.
Next we're going to switch to our material preview,
and now you're going to notice a disturbing lack of materials to preview in the first place.
Let's take care of this by switching to the material properties tab, and start with the bottle material.
There's already a material here, so this will be for our main bottle.
We'll create a second slot for our caps material, and then apply it to these selected faces.
Now I'm going to set some nice properties for this material.
So I'm going to go with a shiny blue color.
Set that blue first, and then to get that shiny effect, we'll turn the roughness way down, and the specular up.
Heading back to our bottle material now, we need translucency here in order to actually see the liquid that we'll be creating.
So alpha value goes down, and I'm also going to tweak the specular settings a bit to make it nice and shiny.
But in order to actually see the translucency in the viewport, we need to set it down here in the settings tab.
So I'm setting alpha blend, and disabling shadows.
It also might be a good idea here to enable backface culling so that we can hide the opposite side of the bottle.
This will stop it from looking like there are two bottles inside of each other.
That looks a lot better.
With that, our model and the shading are mostly done, which means that we can move on to actually creating the liquid effect.
First thing we're going to do here is fit the bottle's mesh cage to its subdivision modifier.
This will better fit our workflow from here on out.
Now it's time to actually make the liquid mesh.
I'm selecting all but the top few faces of the bottle and duplicating them.
Now scale inwards and separate by hitting P.
So this is now going to be a separate object, see?
This means that we can actually get rid of that solidify modifier because this mesh isn't going to need it.
With this object selected, I'm going to mask it out with numpad slash, which lets us work on it completely unobstructed.
With a clear line of sight now, we can fill in the top of the liquid mesh like so.
And now you might have noticed that this liquid object is still using the bottle's material.
To fix this, we're going to go back to the material tab where we're going to make a new one just for the liquid.
This is the important part.
I'm going to start with a light blue color first so as not to obscure the refraction too much.
This will be important for previewing it.
Then head on down to our transmission value and turn that up to 1.
Our roughness value here does impact how our material interacts with light.
Higher values yield blurrier results, so we'll just leave this at 0 for now.
I think that gauging refraction can still be difficult without a full environment for reference,
so I'm using an HDRI that I downloaded for free from HDRI Haven.
After applying it, though, it's not immediately visible,
so we'll have to enable the environment in our preview settings.
And there, now things are making a bit more sense.
Can't forget, though, that we're still in mask mode,
so I'm going to unmask the bottle with numpad slash for a little more context.
Now's a good time also to tweak the liquid material a bit,
so I'm going to change the color to a deeper blue to match that bottle cap.
We're going to set this material aside for a bit now while we set up the liquid surface,
because we're going to need that surface data to further develop the liquid shader later on.
This liquid surface will be defined by a boolean modifier, so let's set that up first.
Start by adding a plane, and then make it big enough to intersect the whole bottle at every angle.
Heading over to the object properties, we also need to set the viewport visibility to a wireframe.
Once you've done this, disable it completely in the renders via the visibility tab.
And what this does is it stops it from showing up when we don't want it to.
Now that our intersection plane is set up, we can actually add the boolean modifier to our liquid object.
Let's do that.
In the modifiers tab, I'm going to grab that and select the intersection plane as the object.
This gives us a weird result, so we just need to switch to the intersection operation,
and would you look at that, it works.
Now our problem is inconsistent surface normals.
As the intersection point moves, so does the distance from the nearest edge loop.
This is a lot more apparent in the solid shading that I'm showing you right now.
The fix for this though is still pretty simple.
We're just going to add an edge split modifier to this mesh to separate the top faces from the sides.
This masks the inconsistent topology and looks a whole lot better.
The only problem that we have now is this sharp edge that's visible around the liquid surface,
but don't worry, we'll mask this later.
For now though, we're just going to set up the bottle's hierarchy with its surface plane.
Select the plane first and the bottle second, then press Ctrl-P to parent the plane to its bottle.
I'm going to do the same thing with the bottle cap,
first separating it from the bottle's mesh, and then parenting it to the object.
Although I'm going to note that this is only really necessary if you'd like to take the cap off later,
which you might not want to do.
So we've got our hierarchy set up now, which is good because now the plane will move with the bottle,
but this also means that it will rotate with the bottle, as you can see here.
We don't want this, it doesn't look good.
Fortunately, we can use object constraints to restrict the local rotation of the plane.
I'm adding the Copy Rotation constraint, setting the target object to the bottle,
inverting the X, Y, and Z axes, and then changing the Mix setting to Add.
Now the plane's rotation is no longer affected by the bottle,
though it'll still move with it when we translate it.
Note that the surface point of the liquid now is inconsistent with the rotation of the bottle
as its distance from the center increases.
At these angles, you'll probably have to correct for this manually.
Now we're all done with the surface dynamics,
which means that it's really time to develop this liquid shader,
now that we have the right information to work with.
In order to add neat effects to the surface of the liquid,
we need to grab the intersection plane's location data.
We can do this with a Texture Coordinate node that references the plane,
so we're just going to grab that like so.
Now we're going to shuttle the positional data to a Mapping node,
where we can easily transform it, which is going to come in handy pretty soon.
So plug that object data into the Position input of this node.
We only really need the Z location here,
so I'm going to add a Separate X, Y, Z node to get just that.
I've also repositioned these nodes off to the side
to get more space for the Vector Math node we're about to add,
and, well, everything that comes after that.
So we're just going to add that Vector Math node, like so,
and plug in our Z location to either of those inputs.
We're interested in a Distance function here, so let's switch to that.
And we can use the output of this function to determine the factor of a Mix node,
which is what I'm adding now.
Now I'm setting some color values for this node as well,
so that when we plug this into our Principled Shader's inputs,
we'll get this result.
I want a slightly lower value towards the top,
so I'm just going to switch these colors really quick,
and now our transmission value decreases towards the top.
Although this transition is still way too long for my liking,
so I'm scaling it down via the Mapping node.
So just take that Z scale and turn it way up.
And by now, we have basic surface effects.
I also think this color difference at the surface point is a little too regular,
so I'm going to go ahead and add a Procedural Noise node
to offset the white color that's used in the Mix node.
Alright, now that that's done, we get to use the values from before
to set up convincing surface normals.
I'm using a Voronoi texture for this, so we'll add that node in.
And we're also going to need a Bump Map node
to convert the Voronoi value to a usable normal map.
We're going to then plug that distance value into our Bump Map,
and plug our Bump Map into our Shader.
And now the Bump Map is being applied to the entire mesh.
Before fixing this, though, I'm changing the Voronoi type to Smooth
because I think it looks better as a height map.
Alright, so to fix the Bump Map, we're going to use the distance value from earlier
to determine where the Bump Map is drawn.
To do this, I'm just plugging it into the Bump Map's Strength input.
This is the opposite of what we need, though.
Here, greater distance equals greater strength.
We want the opposite of this, so I'm adding an Invert node
to the link between the distance and the bump strength.
And that gives us the desired result.
And you might notice now that I'm tweaking the distance value
in the Bump node to yield better-looking results.
Now is a good time to do that.
And hey, while we're on the topic of tweaking,
now is also a good time to preview this in Cycles
to see if we have to make any adjustments.
Going to want to temporarily hide that intersection plane as well.
And now that we can see, this Cycles render tells us
that the transmissive gradient at the surface is way too aggressive.
So we're going to want to turn that down a bit.
I'm using a Color Ramp node to modify this Mix node value
right before it's fed into the Transmission input, as you can see here.
Increasing the effect subtlety improves it a lot.
At this point, we're pretty much done with the shader setup.
This means that we can go on to create the bubble particles next.
The first thing we're going to need is a separate mesh to emit the bubbles from.
Using a separate, smaller emission volume will ensure that bubble particles
will have a chance to collide with the bottle's exterior.
This will prevent them from flying outside of the actual liquid.
To create that, we'll start by grabbing the liquid mesh,
duplicating it, and then scaling it down a bit.
This emission volume doesn't need the subdivision modifier,
so just remove that, but be sure to keep the Boolean modifier
because it's important.
We're also going to remove these extra edge loops
because they can get in the way of the displacement modifier we're about to use.
And then I'm also going to adjust the scale a bit.
That's something we're going to need to do a lot.
As you can see here, though, this emission volume is still touching
the surface of the liquid.
This is bad because the bubbles won't have a chance to be destroyed
by the surface point if they're being generated inside of it all the time.
We're going to need a workaround for this, so like I said before,
we're going to add a displace modifier.
Selecting that now.
Initially, though, this has the opposite of the intended effect
and actually puffs things out.
By using a negative strength value,
we can procedurally shrink this emission mesh properly,
though this is still a bit too tiny, so I'm tweaking the scale a bit.
Remember that bubbles will only be emitted inside of this mesh.
Too small and it starts looking unrealistic.
With that, our emission mesh is all done.
But before we can get to the actual particle system,
we still need a bubble model to use with it.
We all know what bubbles look like, so this doesn't have to be hard.
Start with a UV sphere.
It doesn't have to be high poly, so turn the segments down to 16
and the rings to 8.
Now we get to set up the bubble's material.
This, too, is going to be pretty easy.
I'm creating a new one, and then I'm turning up that transmission value to 1.
Call it a hunch, but now might also be a good time to smoothshade the sphere.
This also makes it apparent that we should be turning the roughness down of the shader.
This is starting to look a lot more like a bubble now.
So we can head on back to that bottle model,
because we have everything we need to create the particle system.
Start by selecting the emission mesh like this,
switch to that particle system tab,
and then create a new one with that plus icon.
Now this is going to require some setup.
Firstly, I'm going to set the frame end value to 120.
That's how many frames I plan to render,
so I'm also going to set that in my timeline preemptively.
Note that the number of particles that we emit
will be emitted over this many frames.
Moving on, it's time to set the particles to our bubble model.
Open the render tab, set render as to object,
and then select the bubble model below as the particle object.
Finally, I'm going to be turning off show emitter.
Now we need to make these particles behave like actual bubbles,
so head on down to the field weights tab.
Here we can modify how different forces are going to affect our particles.
We're after the gravity value here,
so I'm setting some slight negative value to sort of emulate buoyancy.
The particles still look weird though,
and this is because we actually have to set their emission settings.
In that tab, open the source settings.
Set the emit from dropdown to volume,
and then enable the use modifier stack.
This will ensure that the bubbles are emitted
from the volume of our procedural mesh as you see here.
So now things are starting to look a little more bubbly,
but we need these bubbles to, you know,
not fly outside of the bottle like this.
Fortunately, fixing this is easy.
We need to add collisions to both the bottle object
and to the intersection plane,
so that when particles collide with these objects,
they'll just be destroyed.
With the bottle selected, visit the physics tab,
and then select collision.
Now the only setting that matters here is kill particles.
This should be pretty self-explanatory.
I'm also going to do the exact same thing for the intersection plane now,
adding collisions and enabling kill particles.
Previewing the bubbles now,
it's clear that they're not leaving the bottle at all.
This is great, but the added context really highlights
that we still need to adjust the bubble particles a bit.
Back to the emission mesh,
I'm going to be revisiting that particles tab.
First thing I'm going to do here
is lower the particles' inherited velocity.
This will reduce how much they fly away from the emission mesh,
allowing the more subtle force of gravity to be more apparent.
It also looks like these bubbles are a bit too big,
so down in the render tab, I'm going to halve the scale.
You also might want to set some scale randomness,
but I'm leaving that out for now.
So that just about does it for the bubble particles.
I'm going to switch to the Cycles viewport now
to see how it will look in the final render.
Now that we're viewing this in Cycles,
I'm going to make some tiny appearance-based tweaks.
Back in our Eevee preview, on the other hand,
you might have noticed that the bubbles have just completely disappeared.
We're going to fix this right now.
So open that liquid material,
scroll down to the Viewport Display tab,
and then enable Screen Space Refraction.
This does nothing so far, but we're getting there.
Next we're going to open the Render Properties.
Switch over to Eevee temporarily
because this will expose the Screen Space Reflections tab.
Enable it, then also enable the Refraction bool.
Now the bubbles are totally visible,
but something's still not right.
To fix this, I'm also going to adjust the thickness here.
Set the value to 0, and then things start looking a lot better.
Since we can see the bubbles properly now,
it starts to become obvious that some of the bubbles
poke out of the liquid mesh just a little.
Fortunately, it's an easy fix.
Just scale the liquid mesh up a tiny bit
until all of the protruding bubbles are covered.
When we let the animation play out, it should look something like this.
Now that the main components of this liquid are done,
we can create a test animation to bring it all together
so we can get to see the bubbles and surface dynamics
inside of our actual bottle mesh.
To start, let's head over to that Animation tab.
For this animation, I'm going to be using some sine waves
to determine the angles of the bottle over time.
We'll be needing the Graph Editor for that,
so I've opened that on our left-hand window.
We're going to need rotation keyframes
as starting values for the sine waves,
so let's add that to our bottle by pressing I and selecting Rotation.
We can see this new keyframe in our Graph Editor.
Inspecting that value shows the individual rotation axes,
which we can then add procedural modifiers to.
Press N to see the Properties tab.
In this Modifiers tab, add a built-in function.
This is the sine wave that we're going to need.
The default values here still kind of suck,
so I'm going to tweak them until they look a little more appropriate.
I'll start by turning the Amplitude down like that.
0.25 is a bit too little, so I'm going to settle for 0.5.
Next up, I'm decreasing the Phase Multiplier.
This effectively slows the rotation's rate of change.
This here is still a little bit too fast,
so I'm going to further reduce that to 0.125.
That seems to be a good value.
Now we're going to do the exact same setup, but for the Y-axis.
I'm going to add that built-in function modifier first,
and then I'm going to set values that are roughly half of what we used for the X-axis.
That means 0.25 for the Amplitude,
and something like 0.1 for the Phase Multiplier.
Combining those functions gives us this nice swivel effect that you're seeing here.
What's still lacking, though, is that nice inertial reaction from the liquid.
Doing this involves modifying the plane's rotation and bump map,
along with the bottle's movement.
I'm going to start with the latter.
Back in our Shading tab now, go to that Voronoi Texture node.
Select the dropdown and switch the 3D value to 4D.
This exposes that fourth scalar, which, when adjusted,
modifies the appearance of the texture.
You probably know where this is going.
We're going to animate this value to warp our liquid surface as the bottle moves.
This can be done quickly by creating a new window below our shader graph.
Set this window to the timeline so that we can use it to keyframe this value.
Keyframe at the start by pressing I on that value,
set it to something like 2.5, and then do that again at the final frame.
When we let this play, the animation is obvious.
However, the rate of change is not consistent due to how the value is being interpolated.
Back in our Animation Editor, we can get the curve for this value
and adjust it to make it a little more linear.
When we play the animation now, we start getting much improved results.
Last thing to do here is rotate the Boolean intersection plane.
So I'm going to basically get the parameters of the functions from the bottle
and copy them to the plane.
Selecting the plane, I'm going to frame 1 of our timeline
and then adding a rotation keyframe for us to work with.
Get the Y axis in our Graph Editor and add a Sine Wave modifier.
Once that's in there, just set our values from before,
0.25 Amplitude and 0.1 Phase Multiplier.
That looks good, but what we really want is a slightly delayed effect to give a sense of inertia.
So set the Phase Offset value to something like negative 1.
Now that looks even better.
Alright, let's set the same thing for our X axis now.
Get those values from the bottles function and then copy them to the plane.
So add that modifier, set the Amplitude to 0.5 and the Phase Multiplier to 0.125.
Then also set the Phase Offset to something like negative 1.
So there we have our inertia effect.
It's cool, but personally I think it's a bit much,
so I'm going to halve the intensity of the plane's modifiers.
I'm going to be doing that in both the X and the Y axis to keep it proportional.
Of course, you might want to leave that intensity at its original value.
Really, it's up to you.
Before we can actually render this though, there's one thing left to do.
Now that our movement dynamics are all done, we can finally bake our bubble particle system.
Select the Emitter and in the Particle System tab,
scroll down to the Cache and then click Bake.
Once that's done, this wraps up the bottled liquid effect that we were going for.
Now we can render it and see how it looks.
We're not done yet though.
In the thumbnail for this video, I've also added a surface ripple effect to the liquid that you can see here.
This is actually really, really simple.
All we have to do is procedurally warp the surface plane.
So we'll need a subdivision modifier set to Simple Mode, so let's add that.
Set the Viewport and Render Subdivisions to something like 7 so that we now have the vertices to work with.
Now we add the Displace modifier and add a new texture.
Before we set this texture up, make sure the Collision modifier for our particles is listed last.
So drag that down. We don't want bubbles phasing through the mesh.
Naturally, the plane is lower now because the texture is all black.
Let's fix this by setting it to a clouds texture.
Now we start to see an effect here, but it looks really weird.
To get this right, I'm going to start by tweaking the scale of the clouds texture.
Then head on back to our Displace modifier and turn down the Strength.
I think 0.5 looks good for this value.
You're also going to want to make sure that your plane is smooth shaded in order to avoid weird surface normal artifacting.
I prefer the Surface Displacement method for static renders,
though I did try rendering it out in an animation to less than satisfactory and even sometimes unpredictable results.
So I recommend leaving it out for animations.
Finally, on screen right now is some footage of me tweaking the shader values a bit to better accommodate the displacement.
What we were using before for the flat surface might not cut it for an actual wave effect.
And that just about does it for the bottled liquid tutorial.
Thanks for watching, and I really hope this video was informative.
Don't forget to subscribe to the channel if you want to see more of my content in the future, and I'll see you next time.
