Note: this is an old tutorial migrated from a previous version of the website.

Implementing a believable wind animation for vegetation and foliage is no easy task. In this tutorial we’re first going to take a look at how Crytek approached the problem in Crysis, and we’ll then re-implement their solution in a highly customizable material inside UDK.

Overview

The shader we’re going to create has several advantages over the one found in the UDK Foliage Demo:

  • It allows for a more realistic and believable wind animation.
  • It’s more customizable thanks to the usage of material parameters and material instances.
  • It’s more performant: depending on the settings this shader uses 71 to 95 instructions, opposed to the 130 instructions used by the demo shader.

Right now the shader does not support interactive foliage, but adding support for it is relatively easy if you follow the InteractiveFoliageActor documentation on UDN.

Analysis of Wind Animation in Crysis

The original implementation is described in detail in this paper from NVidia GPU Gems 3. Lets start by understanding how the wind itself is generated.

A wind vector is computed per-instance, in world space, by summing up the wind forces affecting the instance. A wind area can be a directional or an omnidirectional wind source. […] Designers can place wind sources at specific locations.

As you can see, Crysis and UDK implementations are very similar when they come to generate wind direction and strength. As such, to generate wind data we’ll just use the WindDirectionalSource and WindPointSource actors the way we’re used to, nothing new here. What is really interesting in the Crysis animation system, though, is how wind animation is applied to the meshes:

In our approach, we divide animation into two parts: (1) the main bending, which animates the entire vegetation along the wind direction; and (2) the detail bending, which animates the leaves. […] We generate the main bending by using the xy components of the wind vector, which gives us the wind direction and its strength, using the vegetation mesh height as a scale to apply a directional vertex deformation. Note that care must be taken to limit the amount of deformation; otherwise, the results will not look believable.

For leaves’ detail bending, we approach things in a similar fashion, but in this case only wind strength is taken into account. Artists paint one RGB color per-vertex, using a common 3D modeling software. This color gives us extra information about the detail bending. The red channel is used for the stiffness of leaves’ edges, the green channel for per-leaf phase variation, and the blue channel for the overall stiffness of the leaves.

Dividing the animation into two parts provides great animation flexibility and realism while keeping the asset creation pipeline simple as vertex colors are easy to paint on meshes (their use was also required by Epic’s shader).

Implementing Wind Animation in UDK

Implementing the wind shader in UDK is a simple process as all we have to do is translating how the Crysis shader works to UDK material instructions. All the functionality will be implemented in a Material Function so that we can plug the wind animation in our materials more easily. Material Functions were added in the August 2011 UDK Beta, so you’ll need an up to date version of UDK to use them. Alternatively, the shader can also be implemented directly inside a standard material, but you’ll need to duplicate all the instructions each time you’ll want to use the wind animation in a different material, which in the long run can make maintaining the shader a cumbersome work. To better follow the tutorial please make sure to download the example UDK Package which contains the full material setup.

Main bending

Main bending is responsible of animating the entire vegetation mesh (trunk, branches and leaves) along the wind direction. Vegetation mesh height is used as a scale to apply the directional vertex deformation.

Main bending implementation
Main bending implementation.

We’re using the Wind Material Function to save us some work and obtain separated outputs for the wind variables. The Normalized Wind Vector (which represents wind direction) is multiplied by Wind Speed and scaled using a parameter. The result is used as the source for a Sine function which is then clamped to 0-1 range to avoid unnatural animation along the mesh. Wind Strength is then multiplied by the Sine function and then by a (1, 1, 0) vector to kill all movement along the Z axis.

Now we need to make wind deformation more evident as we move up the mesh from the ground. This is done by taking the object pivot point location (which is supposed to be at the bottom of the plant trunk) returned by the ObjectPivotPoint Material Function and calculating its distance from the current vertex World Position. Distance is then divided by a number (in our case 256) to reduce the amount of overall deformation along the trunk. We can now multiply the result by the wind sine function to obtain the final main bending animation. To have better control over the animation we multiply it by another scalar parameter so we can tweak the strength of the main bending later in our materials.

Detail bending: edge deformation

Detail bending: edge deformation implementation
Detail bending: edge deformation implementation.

Lets now take a look at detail bending, starting with edge deformation. This type of detail bending is done by deforming leaf edges along the vertex normal direction, using the vertex color red channel for controlling edge stiffness.

We start by calculating the size of the Sine wave dividing the vertex World Position by a scalar parameter and adding the result to the Wind Speed multiplied by a scale parameter. This is then multiplied by the Normalized Wind Vector (which represents wind direction) to make sure that wind animation is played only in the direction of the wind. We then add the result to the detail bending variation (more on this in a second) and use the returned value as the input for the Sine function.

Now that we have a wave, we make sure to clamp it to the 0-1 range to avoid unnatural animation and then we multiply it by Wind Strength and then by a (1, 1, 0) vector to kill all movement along the Z axis. We must now take in consideration vertex colors and vertex normal to obtain the final animation: this is done by simply multiplying our result by the vertex World Normal and by the red Vertex Color channel. The remaining instructions should be self explicative as they consists only of scale and on/off parameters.

Detail bending: per-leaf bending

Per-leaf bending is produced simply by deforming the leaves up and down along the Z axis, using the blue channel to control leaf stiffness.

Detail bending: per-leaf bending implementation
Detail bending: per-leaf bending implementation.

As you can see the per-leaf bending implementation is very similar to the edge deformation one explained above, so I’ll only point out a couple of things: (1) we now keep the movement along the Z axis and kill all movement on the XY axes instead, and (2) to be as consistent as possible with the Crysis implementation, blue vertex color is painted on the vertices of the mesh that do not need to move, so we have to use the 1-x instruction to mask out the blue vertices.

Detail bending: per-leaf variation

We’ve come to the last detail bending type, which uses vertex color’s green channel to control a per-leaf variation, which we use to give each individual leaf its own phase so that every leaf moves differently.

Detail bending: per-leaf variation implementation
Detail bending: per-leaf variation implementation.

Putting it all together

Now that all the animation types have been implemented we only need to add them together and connect the end result to the Material Function Output node.

A switch controls whether to use detail bending or not
A switch controls whether to use detail bending or not.

Before adding detail bending to main bending, though, we add a last switch parameter controlling whether to use detail bending or not to have better control in our materials over every single part of the animation. We’re now ready to plug our material function inside our materials! I usually create just two main base materials for all my vegetation meshes, one for leaves that needs to be masked and have both main and detail bending applied to them, and one for trunks that are opaque and only needs main bending animation. I then create material instances based on the two base materials and control all the wind parameters through them; this way I only need to work on the base materials or on the material function to maintain my shaders.

Wind Animation Material Function inside a standard material
Wind Animation Material Function inside a standard material.

Modeling Tips

Since wind animation is done through vertex deformation you must pay attention while modeling your meshes to obtain a clean topology. If your model has topology problems it’s very likely that you will have problems with the wind shader and won’t end up with a nice and seamless animation. Another aspect to keep in mind is normals orientation. Since edge deformation is done along the vertex normal direction, having flipped normals on some leaves or very different normals on nearby vertices can seriously harm the wind animation. Make sure to double check your mesh normals before exporting to UDK.

Adding vertex colors

Vertex coloring process
Vertex coloring process.

Each RGB channel controls a single type of detail bending: Red for edge deformation, Green for per-leaf variation, Blue for per-leaf bending. In 3D Studio Max, for example, a nice way to paint vertex colors on your meshes is to have three Vertex Color modifiers on the stack set to the Add blend mode and use each of them for a single color. You can find a very good explanation of this workflow in the Bending Setup chapter of the Crysis Asset Creation Guide. Keep in mind that even though the guide tells you to collapse the stack when exporting to Crysis, you don’t need to when exporting to UDK.

Level of detail

If you plan to LOD your meshes you can consider the option of having the wind animation not playing on the last LOD(s): if the model is far enough you won’t notice the difference and you’ll save some frame time. The best way of doing this is to have a material instance with wind animation disabled inside UDK and to completely remove vertex colors from the last mesh LOD.

Conclusion

In this tutorial we have implemented an efficient and realistic wind animation system in UDK based on the Crysis procedural animation system. I hope you found the tutorial useful! Feel free to get in touch if you find errors or have suggestions or comments.

Downloads & References