From Still to Alive: 2 Shader Tricks Every VFX Artist Should Know [Tutorial]

In this tutorial, we’ll explore two essential techniques for creating animated procedural materials: building stylized water in Blender and panning textures in Unreal Engine 5. By combining procedural patterns, UV manipulation, distortion, color, and animation, you’ll learn how simple shader concepts can produce dynamic, expressive visual effects suitable for games and VFX.

MATERIAL SETUP

I will be using the Node Wrangler add-on

Open the Shader Editor, create a new material, and give it a descriptive name such as Stylized Water

We’re going to construct the shader from several procedural layers, so it helps to keep the node tree organized as we go

Our first task is to create the basic wave pattern


WAVE PATTERN

Use SHIFT + A to add a Voronoi Texture node

Change its Dimensions to 4D and its Feature Output to Distance to Edge

This is important because, unlike the standard Voronoi pattern, Distance to Edge gives us lines around the cells

These lines are going to become the foundation of our stylized waves

At this point, though, the pattern looks far too perfect

The edges are straight and regular, which doesn’t look much like water

So before using the Voronoi pattern, we need to distort it


DISTORTION

Select the Voronoi Texture and use CTRL + T to add a Texture Coordinate node and Mapping node

Add a Mix Color node after the Mapping node and change the Blending Mode to Linear Light

Now add a Noise Texture

Take the Color output from the Noise Texture and connect it to the second input of the Mix Color node

The important idea here is that the Noise Texture is bending and disturbing the coordinates before they reach the Voronoi pattern

The once-perfect Voronoi cells should now appear irregular and fluid

Try reducing the Mapping Scale and keep the Linear Light factor subtle

A Value around 0.1 is a good starting point

If the water looks excessively warped, don’t worry. You can control the amount of distortion in two main ways:

  • Adjust the scale of the Noise Texture
  • Reduce or modify the Linear Light settings

The trick is to create enough irregularity to make the water feel organic without destroying the underlying wave structure


SHARP MASK

Now we need to turn the soft Distance to Edge information into a clean graphic pattern

Add a Math node after the Voronoi Texture and set its operation to Greater Than

Lower the threshold until you get a pattern of sharp black lines against white

This is useful because we’re no longer dealing with a gradual falloff

Instead, we have a clean mask that can be used to define exactly where our stylized waves appear


COLOR

Add a Mix Color node after the Math node and connect the Math node to the Factor of the Mix Color node

The two color inputs of the Mix Color node now become our water colors

Choose a blue or cyan for the B-input [B: #6298BDFF]

You should now have the beginnings of the water material – a colored surface broken up by a procedural wave pattern

But one layer isn’t enough

To make the water more interesting, we’re going to introduce a second wave pattern


SECOND WAVE

Select the Voronoi, Math, and Mix Color nodes that form your first wave layer and duplicate them using SHIFT + D

Make sure to connect the Linear Light to the second Voronoi texture

For this layer, change the A-input color to a darker blue [#3B5B71FF]

To combine the two layers, add a Mix Color node and connect the two Mix Color node layers

When the two layers are viewed together, you’ll notice a problem – their wave patterns tend to sit directly on top of one another

Instead of looking like two independent layers of water, they look like the same pattern being painted twice

We need to randomize the second layer


SECOND PATTERN

Add another Math node and change its operation to Multiply

Connect the Value into the W input of the second Voronoi texture and use a relatively large value, such as 200, as a starting point

If you change the Factor of the last Mix Color node you will now see two variations of the Voronoi Texture

This effectively changes the fourth-dimensional coordinate used by the Voronoi texture, causing the second pattern to be different from the first

The result is two related but independently distributed wave patterns

Now we can combine them without having every wave perfectly overlap

Use the Greater Than result from the first layer as the Factor controlling the final mix between the two wave colors


EXPORTING

Under the Output Properties tab, I change the Resolution to 2K

I set up my camera and light – scaling the light to the same size as the plane and placing it in front of the camera

Render the image


MATERIAL SETUP (UE)

First, create a new material and open it in the Material Editor

In your Project Settings you will need to turn off Substrate Materials

NOTE: I would recommend making and using a tiled texture

I used the Seamless Texture Generator – it isn’t perfect but close enough for this tutorial

Change the Blend Mode to Translucent

You can also use an appropriate shading model depending on the effect you’re creating

For this example, we’ll keep the material extremely simple

Hold down the T-key and left-click to add a Texture Sample

Choose the texture you just made

Connect the Texture Sample to the Emissive Color input

At this point, you should have a basic material

Now let’s make that texture move


TEXTURE OFFSET

Before we make anything move automatically, it’s useful to understand what makes a texture move

The secret is the texture’s UV coordinates

Normally, the Texture Sample receives UV coordinates from the mesh

Those coordinates determine which part of the image is displayed at each point on the surface

If we add a value to those coordinates, we’re effectively shifting the texture

Start by holding down the U-key and left-clicking to add a Texture Coordinate node

Add an Add node by holding down the A-key and left-clicking

Connect the Texture Coordinate node to the Add node

Then connect the output of the Add node to the UVs input of your Texture Sample

Nothing should visibly change yet because we’re effectively adding zero to the UV coordinates

Now let’s create some controls


OFFSET CONTROLS

Create two scalar parameters by holding down the S-key and left-clicking

Name the first one Offset X and the second one Offset Y

For each parameter, set the minimum and maximum values to approximately -1 and 1

This gives you a convenient range for moving the texture in either direction

Now right-click and search for an Append Vector node

Connect Offset X to the A input and Offset Y to the B input

The result is a two-dimensional vector containing our horizontal and vertical offsets

Connect this Append Vector to the second input of the Add node

Apply and Save the material

Back in the Content Browser, right-click on the Material and create a Material Instance from it

Open the instance and you’ll now have controls for Offset X and Offset Y

Increase Offset X and you’ll see the texture slide horizontally

Increase Offset Y and it will slide vertically


AUTOMATIC OFFSET

Manually changing Offset X isn’t particularly useful for an animation

We could keep increasing the value ourselves, but what we really want is a number that continuously increases as the material runs

That’s exactly what the Time node provides

Go back to your material, right-click and add a Time node

Instead of using the Offset X parameter directly, connect Time to the X input of your UV offset setup

Now the texture should begin moving automatically

The reason is simple – time continuously increases while the material is being rendered

Since that changing number is being added to the UV coordinates, the sampled position changes continuously as well

We’ve just created our first animated texture


SPEED AND DIRECTION CONTROLS

The Time node gives us movement, but we still need control over it which can be done through multiplication

Hold down the M-key and left-click to add a Multiply node

Connect the Time to the A-Input and the Offset X to the B-input

Connect the Multiply node to the A-input of the Append node

Change the Offset X Parameter Name to Speed X and change the default Value to 0.1

Add a Multiply node and connect the Y Axis Parameter to the B-input

Connect the Time node to the A-input of the second Multiply node

Connect the Multiply node to the B-input of the Append node

Change the Offset Y Parameter Name to Speed Y and change the default Value to 0.1

Now you have independent controls for both directions

You can now use the Material Instance to change the speed in real time

Using negative values makes textures travel in the opposite direction


PANNER NODE

There’s just one problem

Although this setup is useful for understanding what’s happening, it contains several nodes just to achieve a very common operation

Fortunately, Unreal Engine has already packaged this functionality into a single node

Hold down the P-key and add a Panner node

Connect the Panner node to the UVs of the Texture Sample

Use CTRL + D to duplicate the Multiply, Speed X and Speed Y nodes

Connect the Speed X to the A-input of the new Multiply node

Connect the Speed Y to the B-input of the new Multiply node

Connect the Multiply node to the Speed input of the Panner

Apply and Save the material


CONCLUSION With these techniques, you now understand how procedural textures can be shaped, layered, colored, and animated to create convincing stylized effects. Blender gives you powerful tools for generating unique water patterns, while Unreal Engine makes texture animation straightforward. Together, these workflows provide a strong foundation for creating flexible, reusable materials and VFX.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.