In today’s blog post we’ll take a peek behind the scenes of a recent 3D Consumer Product Animation project and show how to use displacements in LightWave 3D to animate rippling water waves. This is a rather quick and easy way to simulate all sorts of water waves rather than trying to use a more complicated fluid dynamics approach. In this sample we’ll animate the general water wave motion as well as more targeted water ripples where objects rise up through the water’s surface and then sink back below the water’s surface.
We’ll use animated procedural textures to build up a displacement map for the water surface. We’ll then use that animated displacement map to drive geometry displacement of the water object to create pretty realistic looking animated waves. We’ll tie the wave motion to a set of reference nulls for easy animation adjustments so you can tweak the motion until it’s just right for your purposes.
The following behind the scenes, step by step tutorial shows how to use displacements in LightWave 3D to animate rippling water waves. It examines each step that was used to create the displacement map that drove the water surface’s motion and appearance in this project. This should be enough information for you to be able to use the same techniques in your own projects.
Setting up the Water Surface Object for Displacment Mapping
In this project the object used to create the water surface effect was built as a simple 2.5 m disc that met the skydome as the horizon along the edge. Any shape would work as long as you can subdivide it.
With the water surface object selected open the Object Properties Geometry tab. Set the Display SubPatch Level to a high enough level to produce a dense mesh, 24 in this particular case. Set the Render SubPatch to Per Object Level and set that to 24 as well.
With the water surface object selected open the Object Properties Deform tab. Turn on the Enable Bump checkmark and set the distance to 50mm. This will let the surfaces bump/displacement map drive the geometry displacement of the waves.
Create five nulls that we’ll use to fine tune the wave animation. These nulls will be used as reference items within the surface’s node map. Name the nulls so that you know what each will be used for. In this case I named them as follows:
- Wave Main – Null
- Wave Swells – Null
- Wave Crumple – Null
- Ripple Location Null
- Ripple-Motion-Null
Setting up the Water Surface Displacement Node Map
Here is an overview of the water surface’s entire node map as seen in LightWave 3D’s Node Editor.
This surface node map performs two main functions. First it defines the displacement map to drive the geometrical displacement of the actual waves, ripples and water motion. In order for this to affect the actual geometry of the object you must have the Enable Bump check-mark activated as mentioned previously. The second function of this node map is to define the look of the water surface itself.
Setting up the Texture Nodes to Create the Wave Displacement Map
The displacement node map is composed of four main components, three for the general water motion and an additional Ripples Node that I added later to add ripples at the point where the product breaks through the water’s surface in this particular project. This Ripples Node is not needed for plain wavy water. This was added so that there would be distinct ripples radiating out from the point in the water where the products rise up and break the surface, as well as when they sink back below the surface. If you are only creating wavy water and don’t need localized ripples you can skip this Ripples Node.
I started with a Turbulence Node to create the large flat swells. I fed that into another Turbulence Node to add the main waves to it. I then fed that into a Crumple Node to add smaller details to the waves. An easy way to combine all these texture nodes together is to simply feed the color output of one into the background color of the next in a chain fashion. I used an additive Blending mode with various opacity levels for each texture node. I then fed the result into the displacement input of the Surface Node. I later added a Scalar Layer Distance to Object Gradient Node to scale back the waves as they approached the horizon to create the appearance of greater distance to the horizon.
Water: Ripples Node:
Optional: To create localized ripples around objects.
- Blending: Normal (This is the first in the chain so it’s not being blended to anything else).
- Opacity: [E]nveloped (Tied to Ripple-Motion-Null.Position.Y with a channel follower)
- Wave Sources: 1
- Wavelength: 0.0625
- Wave Speed 0.0125
- Bump Amplitude: 100% (This is not actually used because we’ll be using the color output to drive the displacement rather than the bump.)
- Reference Object: Ripple Location Null
- Scale X, Y, Z: 1 m
- Falloff X: 75%, Y: 0%, Z: 75% (This is used to have the ripples fade out as they move away from the ripple source.)
Water: Swell Turbulence Node:
This node creates the larger swells in the water.
- Blending: Normal (This was originally the first in the chain, before I added the ripples before it, you could use additive if adding to other nodes).
- Opacity: 75%
- Small Scale: 0.5 (for medium small detail strength)
- Contrast: 50% (for medium contrast)
- Frequencies: 3 (for a simple texture)
- Bump Amplitude: 100% (This is not actually used because we’ll be using the color output to drive the displacement rather than the bump.)
- Reference Object: Wave Swells – Null
- Scale X, Y, Z: 1 m (for relatively large swells)
Water: Main Waves Turbulence Node:
This node creates the more defined waves on top of the swells in the water.
- Blending: Additive (to add to the swell node).
- Opacity: 50%
- Small Scale: 0.5 (for medium small detail strength)
- Contrast: 50% (for medium contrast)
- Frequencies: 4 (for a slightly more detailed texture)
- Bump Amplitude: 100% (This is not actually used because we’ll be using the color output to drive the displacement rather than the bump.)
- Reference Object: Wave Main – Null
- Scale X, Y, Z: 500 mm (for relatively medium waves)
Water: Main Crumple Node:
This node adds finer details to the waves for a more windswept choppy appearance.
- Blending: Additive (to add to the swell node).
- Opacity: 25% (for a more subtle texture for these smaller details.)
- Small Scale: 0.75 (for a higher level of small detail strength)
- Frequencies: 3 (for a simple texture)
- Bump Amplitude: 100% (This is not actually used because we’ll be using the color output to drive the displacement rather than the bump.)
- Reference Object: Wave Crumple – Null
- Scale X, Y, Z: 600 mm (for relatively medium wave details)
I then used a Scalar Texture node to apply a Distance to Object gradient so that I could reduce the amplitude of the waves as they moved away from the center and out toward the horizon. I used a 2.5 m radius sphere for the sky dome and a 2.5 m disc for the surface of the water.
Texture Editor – Scalar Texture – Scalar Layer:
- Layer Type: Gradient
- Blending Mode: Normal
- Layer Opacity: 100%
- Input Parameter: Distance to Object
- Object: The water surface object itself so that it uses distance from the object’s pivot point.
- Start: 0 m, Value: White
- End 2.5 m, Value: Black
I used the output of this Distance to Object gradient Scalar Layer node to reduce the waves’ amplitude as they approach the horizon edge of the disc (2.5 m in this scene) by feeding this and the output of the Crumple Node into a Multiply node and then feeding the result into the Surface Node’s Displacement input.
Setting up the Water Surface Appearance Nodes
I used a few key nodes to define the look of the water waves using the legacy Kappa II shader to give it some subsurface scattering (SSS). I sometimes use the older legacy shader nodes like Kappa and Kappa II for a couple of reasons. First it is not pre-processed so it works with VPR so that I don’t have to keep doing test renders and can use VPR while refining the surfaces appearance. Second it gives me full access to all the other independent inputs on the Surface Node which often gives me more flexibility to build up my surfaces one component at a time rather than the more limited and locked-down Material Nodes which override pretty much everything and tie various components together making fine tuning much more difficult.
The water surface’s appearance is defined with four nodes. A color Gradient node feeding into a Kappa II Node to control the Diffuse Shanding and a couple of Gradient Nodes to control the Reflection and Transparency of the Surface Node. A few other items on the main Surface Editor are tweaked to suit if needed or additional nodes may be added to the node map.
NOTE: There’s a minor bug when using the Node Editor on the Mac with VPR. When VPR is on the node thumbnails often fail to completely update. The Update button even fails. If this happens to you, a workaround is to turn off VPR temporarily while working in the node editor and all the thumbnails will update. Then turn VPR back on when you want to see the viewport update.
Gradient Node:
In addition to the Displacement input, I also fed the output of the Crumple node into the input of a Gradient node to control the wave color. By setting the gradient from a dark blue/green at 0.0 to a yellow/green at 1.0 it will color the waves to be brighter at the peaks and darker at the troughs as a fast and simple way to simulate the absorption of the light where the water is deeper.
Kappa II Node:
This node gives the waves a little Subsurface Scattering (SSS)
- I fed the output of the color gradient into both the Forward and Backward color for the Kappa II node.
- Range 100mm
- Forward & Backward Amount: 100%
- Samples 8
The output of the Kappa II Node is then fed into the Diffuse Shading input on the Surface Node.
Reflection Incidence Gradient Node:
I used an incidence gradient node to control the Reflection level of the water surface.
I used a grayscale ramp from a value of 228 (about 90%) at the start of 0 to a value of 25 (about 10%) at the end of 1.0 to adjust the reflectivity to be strongest at glancing angles and lowest at head-on angles.
Transparency Gradient Node:
I used another gradient node to fade the transparency of the water as it approached the horizon so that it wouldn’t cause render glitches along the horizon. I set the Input to Z-Coordinate. I then set the Alpha to 80% from the start of 0.0 to 2.0 and then dropped it to 0% at 3. I then used the alpha output to drive the transparency input on the Surface Node. I’ll often use the Alpha output rather than the Color output on the gradient node because it’s easier to set simple 0-100% values.
In this particular scene I have a ground basin under the water surface so that there’s something behind the semi-transparent water surface when rendered. It just has a simple color gradient surface from a light green to a dark green based on slope.
Animating the Wave Displacments with Nulls
Once the water surface nodes were finished I then animated the reference nulls to set up the wave animation using the scene editor and the graph editor. I was animating at 24 fps so I created keyframes for the nulls at frame 24 to set the motion over 1 second.
I opened the null position channels in the Graph Editor and animated each to move slightly in all three axes at differing speeds. I set the Pre and Post behaviors to Linear so that the motion would continue throughout the entire animation. I then rendered a quick preview and adjusted the motions of each null until I had the effect I was looking for.
Once I had the overall water motion I then positioned the Ripple Location Null at the point where the products would rise through the water surface and sink back below the surface. And after the products were animated I animated the Ripple-Motion-Null’s Y Position. I could have just animated the envelope of the water surface’s Ripple Opacity directly, but I often find it easier to tie animated items to nulls that can be animated more easily.
I animated the Ripple-Motion-Null’s Y position to coincide with the products rising up through the water surface and then sinking back below the surface.
I attached a Channel Follower to the water surface’s Ripple Node’s Opacity envelope and set it to follow the Ripple-Motion-Null.Position.Y
Final Results of How to Use Displacements in LightWave 3D to Animate Rippling Water Waves
The same displacement map techniques were used to animate the rippling water waves in two shots in the final 3D Consumer Product Animation. This same technique was used in a second shot with an assembly line of bottles moving through the water. In that shot I used 10 ripple nodes with one tied to each bottle as it moved through the water. I also used the hypervoxel dripping liquid technique from a previous blog post in that extracts shot.
Leave a Reply