
Stylish waterfall from RiME in the game engine: make a water stream
- Transfer
This is the second (and last) part of the Unity or UE4 waterfall guide after being inspired by the RiME game. The first figured out the tools, chose the development environment and created a shader for water circles. Why did you start with this? Everything is simple: most of the methods that are now needed when creating a waterfall are used there. But there are some hints. We will not pull - let's go under the cat.

Let's start with the obvious - take the regular Panner and mesh. You might be surprised: why are there so many polygons? Like in Simon Falls, I use vertex displacement to offset the vertices of a model in 3D through a shader. And to make it look beautiful, we need additional tops. For optimization, you can create LOD meshes (Level Of Detail) with fewer polygons, and force Unity to switch to lower-resolution models.

The UV seam is located at the back. Even if the waterfall does not have visible texture seams, it’s still better to play it safe and place the UV seams in the least visible places for the player.
As with the water circle mesh, the UV scan should have the smallest number of seams on the model when using tiling textures. One side of the UV shell is tied to 0 in the direction of U, and the other to 1. Remember that the width of the UV shell must fit into an integer value of U-space (for example, tiling 1, 2 or 3). If we tile 1.2 times in the U direction, a seam will appear at the junction. And we need a seamless tiling texture.

This is how the normal map looks tiled 3 times in the U-direction. Notice how the right side of the 3D image fits perfectly in 1 in the U-direction. Setting tiling to 3 in the U direction means that the texture repeats 3 times between 0 and 1 in the U direction (the image below shows the UV space from 0 to 1).

For example, here is the same texture tiled 2.2 times - a seam appeared immediately. For many, this is obvious, but it’s important to understand why and how you should place your UV scans in certain scenarios. We work with panning of tiling textures, and besides, we do not need seams, so we must adapt the UV scan.

For a more complete picture, look at the gif where I move the UV map. For one, the width of the UV shell is exactly 1 (perfectly tiled), the other is trimmed so that the seam is visible. Since we use only tiling textures, the UV map does not have to be between 0 and 1.

At the waterfall (as with the circles on the water), I also distorted the UV map. Therefore, when using Panner, the texture moves faster or slower at certain points in the mesh. Additional polygons in this case make the transition between distorted areas less noticeable. Try turning on soft selection to warp the UVs for smoother transitions.

Pay attention to how the texture stretches more strongly on the bend of the waterfall - this effect can be regulated in different ways. Always imagine the transition from UV to 3D. The closer the vertices of UV are to each other, the faster the texture will move along these UVs in 3D space when using Panner. If you move the UV vertices farther apart, the texture will appear more often in this area of the mesh and move more slowly in 3D when using Panner. Experiment until you get the desired effect.

Note: this is new material. Create a new material and apply a new shader on it (see part 1 ).
We again use the same texture with several Panner speed / direction options, as well as UV tiling (we flip one of them, giving a negative value of U). Add them to each other to get the feeling of a more random effect. And we use their output to add many other settings: opacity, color variation and vertex displacement.

I also used the normal map scroll. Only one, because it moves so fast with two Panner for variation, that in this case there will be no difference. Multiply it by the value of blue equal to 1 (255 is indicated on the gif - this is when each channel has 256 steps, from 0 to 255), as well as by the values of red and green equal to 60 (or the value 0.23 if you use the scale from 0 to 1). As a result, a too saturated normal map has become more even and calm. To return more intense normals, keep the values of R and G the same and increase them. So you get a little more customization inside the shader itself.

We set up the mesh, UV and other components that will be needed for the waterfall to work. Let's analyze a few things on this GIF:

On it, a stream of water scrolls through a 3D mesh and breaks below. It can be seen that the type of transparent cut-out rendering is used here - the waterfall is completely opaque or completely transparent. Water changes color when it approaches the ground, and looks less smooth in white areas. The vertex displacement, which we spoke about earlier, is immediately noticeable. All these factors give the waterfall a more lively and natural look. Now in more detail - let's start with color.
I use Lerp (linear interpolation) with two colors and a scrolling black and white texture that I made at the beginning as an alpha (input signal). This texture basically serves as a mask for choosing whether to show blue or white. And Add is connected to the vertex color node (node with vertex colors).

The used vertex colors are shown below. They work like the vertex colors from the first part - that is, as a gradient. Colors are needed to make sure that the water becomes whiter towards the bottom of the waterfall. Since we add vertex colors over the existing color (the whitest point vertex color = 1), you can easily exceed the value 1. If this happens, we will get too bright and oversaturated results. Therefore, Clamp is at the end, so that the maximum values do not exceed 1 (for Clamp, minimum = 0, and maximum = 1). Using white and blue colors ensures that when the water “breaks”, it will be in the white (foamed) area of the mesh and will get a white border around the transparent areas. The lighter the vertex color, the more vertices protrude outward. Thus, the end of the waterfall, which is lighter in vertex color, moves more randomly.

Next, I made two additional meshes inside the main waterfall - so that a sense of volume appeared. The other two meshes are modified versions of the main mesh, with the same UVs. They are slightly offset and modified so that the material looks different on all three meshes. This method does not take performance, but it helps a lot.

Additionally, connect the fresnel in the emission channel to create fake light that passes through the water. Fresnel makes the pixel so lighter as the normal vector on the surface of the 3D object is deviated from the camera and as dark as the normal vector is directed to the camera (perpendicular to the camera).
If you look at an angle, the waterfall becomes “thinner" - fresnel is useful here to show more fake light in these areas. At the same time, it is impossible for the waterfall to glow - to weaken the effect, I used min node. Fresnel is often used with water shaders to change color depending on the viewing angle. Connecting 0 (black) to emission will not do anything, and connecting 1 (white) will make it an un-lit shader that will look completely lit from all sides (even if it is in the shade).

For smoothness, I flipped vertex color using one minus node. If you scroll a little higher, you will see that the vertex color is light below and dark above. Turning them over (to make it light above and dark below), you can make the lower part of the waterfall less smooth compared to the upper. Darker values are equal to a less smooth surface, and lighter values are smoother.

Vertex displacement or vertex offset is an important thing necessary to realize this effect. Moving the peaks, the waterfall looks less static and therefore more lively.
This is a waterfall without vertex displacement:

But with vertex displacement:

Moving the peaks based on our scrolling black and white texture, the waterfall becomes smoother. If you direct the value 0.5 to the vertex offset output of the main node, then nothing will happen. Try to keep gray with a value of 0.5 as the standard vertex value. Everything below 0.5 will move in the negative direction, and everything above 0.5 in the positive direction.
So how do we know in which direction the peaks will move? What is up and down?
In our case, we want to move the vertices away from the surface of the mesh. A negative direction will mean that the vertex moves “inward” relative to the direction of the vertex normal on the surface, and a positive direction will move “outward”. For just such a vertex movement, we can use vertex normals. Each vertex, even if it is just one “point” in 3D space, has a direction assigned to it - vertex normal. It is used to calculate how the surface of the mesh should be shaded. In this example, I made a ball and set Maya to display vertex normals (display> polygons> vertex normals). Each vertex has a direction that, by default, indicates the distance from the surface. You can also edit any vertex normal and change its direction, but now the current one suits us.

Vertex normal node outputs RGB values that are based on the normal direction of the mesh vertices. In shaders and with normals in general, RGB values are used to express a 3D XYZ coordinate object in 2D space. So that our black and white Panner in the shader can move along the surface of a 3D object, we can use RGB vertex normal values. I added vertex color to the tops to make the bottom of the mesh more convex. And also a few nodes to control the offset value (this is normal if your values are below 0 or above 1).

To demonstrate, I will give a sphere with a vertex normal node applied directly to the albedo (color) output of the main node.

The RGB (XYZ) output of the vertex normal node is based on the vertex normals of the mesh, which gives us this result.
Here is the complete structure of the nodes. It shows where and how everything connects.

I hope you have learned something new for yourself. My goal was to provide enough knowledge and starting points for the independent creation of such a waterfall. To do such things, it is not necessary to know everything - enough basic things. Of course, I not only just opened Amplify and created this effect in one fell swoop - there were other attempts that didn't work.
Some more useful links on the topic:

Let's start with the obvious - take the regular Panner and mesh. You might be surprised: why are there so many polygons? Like in Simon Falls, I use vertex displacement to offset the vertices of a model in 3D through a shader. And to make it look beautiful, we need additional tops. For optimization, you can create LOD meshes (Level Of Detail) with fewer polygons, and force Unity to switch to lower-resolution models.

The UV seam is located at the back. Even if the waterfall does not have visible texture seams, it’s still better to play it safe and place the UV seams in the least visible places for the player.
As with the water circle mesh, the UV scan should have the smallest number of seams on the model when using tiling textures. One side of the UV shell is tied to 0 in the direction of U, and the other to 1. Remember that the width of the UV shell must fit into an integer value of U-space (for example, tiling 1, 2 or 3). If we tile 1.2 times in the U direction, a seam will appear at the junction. And we need a seamless tiling texture.

This is how the normal map looks tiled 3 times in the U-direction. Notice how the right side of the 3D image fits perfectly in 1 in the U-direction. Setting tiling to 3 in the U direction means that the texture repeats 3 times between 0 and 1 in the U direction (the image below shows the UV space from 0 to 1).

For example, here is the same texture tiled 2.2 times - a seam appeared immediately. For many, this is obvious, but it’s important to understand why and how you should place your UV scans in certain scenarios. We work with panning of tiling textures, and besides, we do not need seams, so we must adapt the UV scan.

For a more complete picture, look at the gif where I move the UV map. For one, the width of the UV shell is exactly 1 (perfectly tiled), the other is trimmed so that the seam is visible. Since we use only tiling textures, the UV map does not have to be between 0 and 1.

At the waterfall (as with the circles on the water), I also distorted the UV map. Therefore, when using Panner, the texture moves faster or slower at certain points in the mesh. Additional polygons in this case make the transition between distorted areas less noticeable. Try turning on soft selection to warp the UVs for smoother transitions.

Pay attention to how the texture stretches more strongly on the bend of the waterfall - this effect can be regulated in different ways. Always imagine the transition from UV to 3D. The closer the vertices of UV are to each other, the faster the texture will move along these UVs in 3D space when using Panner. If you move the UV vertices farther apart, the texture will appear more often in this area of the mesh and move more slowly in 3D when using Panner. Experiment until you get the desired effect.

Note: this is new material. Create a new material and apply a new shader on it (see part 1 ).
We again use the same texture with several Panner speed / direction options, as well as UV tiling (we flip one of them, giving a negative value of U). Add them to each other to get the feeling of a more random effect. And we use their output to add many other settings: opacity, color variation and vertex displacement.

I also used the normal map scroll. Only one, because it moves so fast with two Panner for variation, that in this case there will be no difference. Multiply it by the value of blue equal to 1 (255 is indicated on the gif - this is when each channel has 256 steps, from 0 to 255), as well as by the values of red and green equal to 60 (or the value 0.23 if you use the scale from 0 to 1). As a result, a too saturated normal map has become more even and calm. To return more intense normals, keep the values of R and G the same and increase them. So you get a little more customization inside the shader itself.

We set up the mesh, UV and other components that will be needed for the waterfall to work. Let's analyze a few things on this GIF:

On it, a stream of water scrolls through a 3D mesh and breaks below. It can be seen that the type of transparent cut-out rendering is used here - the waterfall is completely opaque or completely transparent. Water changes color when it approaches the ground, and looks less smooth in white areas. The vertex displacement, which we spoke about earlier, is immediately noticeable. All these factors give the waterfall a more lively and natural look. Now in more detail - let's start with color.
I use Lerp (linear interpolation) with two colors and a scrolling black and white texture that I made at the beginning as an alpha (input signal). This texture basically serves as a mask for choosing whether to show blue or white. And Add is connected to the vertex color node (node with vertex colors).

The used vertex colors are shown below. They work like the vertex colors from the first part - that is, as a gradient. Colors are needed to make sure that the water becomes whiter towards the bottom of the waterfall. Since we add vertex colors over the existing color (the whitest point vertex color = 1), you can easily exceed the value 1. If this happens, we will get too bright and oversaturated results. Therefore, Clamp is at the end, so that the maximum values do not exceed 1 (for Clamp, minimum = 0, and maximum = 1). Using white and blue colors ensures that when the water “breaks”, it will be in the white (foamed) area of the mesh and will get a white border around the transparent areas. The lighter the vertex color, the more vertices protrude outward. Thus, the end of the waterfall, which is lighter in vertex color, moves more randomly.

Next, I made two additional meshes inside the main waterfall - so that a sense of volume appeared. The other two meshes are modified versions of the main mesh, with the same UVs. They are slightly offset and modified so that the material looks different on all three meshes. This method does not take performance, but it helps a lot.

Additionally, connect the fresnel in the emission channel to create fake light that passes through the water. Fresnel makes the pixel so lighter as the normal vector on the surface of the 3D object is deviated from the camera and as dark as the normal vector is directed to the camera (perpendicular to the camera).
If you look at an angle, the waterfall becomes “thinner" - fresnel is useful here to show more fake light in these areas. At the same time, it is impossible for the waterfall to glow - to weaken the effect, I used min node. Fresnel is often used with water shaders to change color depending on the viewing angle. Connecting 0 (black) to emission will not do anything, and connecting 1 (white) will make it an un-lit shader that will look completely lit from all sides (even if it is in the shade).

For smoothness, I flipped vertex color using one minus node. If you scroll a little higher, you will see that the vertex color is light below and dark above. Turning them over (to make it light above and dark below), you can make the lower part of the waterfall less smooth compared to the upper. Darker values are equal to a less smooth surface, and lighter values are smoother.

Vertex displacement or vertex offset is an important thing necessary to realize this effect. Moving the peaks, the waterfall looks less static and therefore more lively.
This is a waterfall without vertex displacement:

But with vertex displacement:

Moving the peaks based on our scrolling black and white texture, the waterfall becomes smoother. If you direct the value 0.5 to the vertex offset output of the main node, then nothing will happen. Try to keep gray with a value of 0.5 as the standard vertex value. Everything below 0.5 will move in the negative direction, and everything above 0.5 in the positive direction.
So how do we know in which direction the peaks will move? What is up and down?
In our case, we want to move the vertices away from the surface of the mesh. A negative direction will mean that the vertex moves “inward” relative to the direction of the vertex normal on the surface, and a positive direction will move “outward”. For just such a vertex movement, we can use vertex normals. Each vertex, even if it is just one “point” in 3D space, has a direction assigned to it - vertex normal. It is used to calculate how the surface of the mesh should be shaded. In this example, I made a ball and set Maya to display vertex normals (display> polygons> vertex normals). Each vertex has a direction that, by default, indicates the distance from the surface. You can also edit any vertex normal and change its direction, but now the current one suits us.

Vertex normal node outputs RGB values that are based on the normal direction of the mesh vertices. In shaders and with normals in general, RGB values are used to express a 3D XYZ coordinate object in 2D space. So that our black and white Panner in the shader can move along the surface of a 3D object, we can use RGB vertex normal values. I added vertex color to the tops to make the bottom of the mesh more convex. And also a few nodes to control the offset value (this is normal if your values are below 0 or above 1).

To demonstrate, I will give a sphere with a vertex normal node applied directly to the albedo (color) output of the main node.

The RGB (XYZ) output of the vertex normal node is based on the vertex normals of the mesh, which gives us this result.
Here is the complete structure of the nodes. It shows where and how everything connects.

I hope you have learned something new for yourself. My goal was to provide enough knowledge and starting points for the independent creation of such a waterfall. To do such things, it is not necessary to know everything - enough basic things. Of course, I not only just opened Amplify and created this effect in one fell swoop - there were other attempts that didn't work.
Some more useful links on the topic:
- Report by Julian Love , who worked on Diablo as a VFX artist. The performance is mainly about effects skills, but many of the things shown apply to other types of realtime VFX as well.
- Little Chicken Game Company Blog . It is dedicated to creating game art without textures and interesting techniques for creating a beautiful environment.
- My mastermind Simon Trumpler has many other interesting things on the site. One of my favorites is the page with the so-called Game Art Tricks .
- YouTube channel with shader videos . My favorites are those that recreate specific effects from games (in Unity).