Hi everyone!
I have been working on a way to dynamically create flow maps for water based on the distance field data. Here is the result:
IMPORTANT: The following material is made in the Unreal Engine 4.9 master branch from GitHub. This will not work in 4.8!
This material can’t yet be used with translucent screen space reflections because it will take up to many texture samples.
DOWNLOAD:
roelbartstra.com/resources/downloads/distancefieldflowmap.zip
Let’s start of by talking about flow maps and what they do exactly. A flow map is usually covering the entire water surface to give per pixel information about the direction the water is moving towards. This an example flow map from the game Left 4 Dead 2.
There is clearly a lot of saturated red and green and no blue. This is because we are providing a 2 dimensional direction in which the water should move. Red being the x direction and green being the y direction. We can pan the texture in this direction to fake water flow, making it feel much livelier.
I won’t go in too much detail on the actual flow map math. If you would like to know more about it, I would suggest reading Valve’s Siggraph talk about flow maps: http://www.valvesoftware.com/publications/2010/siggraph2010_vlachos_waterflow.pdf
In the past these flow textures were always pre-painted. This can be done with a variety of different tools. But the problem is, if something moves dynamically through the water, it will not influence the flow map. It can also end up being a pain in the *** if you have to make a ton of them for different levels.
In Unreal Engine 4.9 there will be a couple of new material nodes related to distance field data. The ones I used the flow mapping are called “DistanceToNearestSurface” and “DistanceFieldGradient”. At first sight the DistanceFieldGradient node seems to be what we want since we can normalize it and then it will return the direction. Here you can see masking the red and green channel from the Distance Field Gradient looks already very similar to a flow map.
Although it gives a results which looks like it could resemble a flow map, the flow will look strange when the directions changes too abrupt. To make a more “blurred” directional map I made my own direction to nearest surface based on the distance to nearest surface:
This way we can tweak the “smoothness” value easily. The smoother the value, the less accurate the direction will be.
Since this particular material is made for a river we first need to have an initial flow direction. Preferably something the artist can easily control. My current solution is to use the uv coordinates. You can see in the image below the uv coordinates are laid out straight even though the river mesh (purple thingy on the right) is curved.
We can transform the y (green) coordinates from tangent space into world space to get the directional flow based on the uv’s. We do this in world space since the distance field data we receive is also in world space. We can take the average between these 2 directions to quickly calculate the flow. This will mean if the directions are both the same, the river will move in the direction provided by the artist. If the distance field direction is going the other way, the flow will, in most cases, go to the side. Evading the object.
We can now use a dot product to compare this uv direction with the distance field flow, giving the following results.
If the distance field flow is perpendicular to the uv flow it will return 1 if it is in the opposite direction it will be zero. Anything in-between will be an interpolated value.
I have used this data to push the water upwards when it’s heading towards an obstacle, and downwards when the flow is moving away from an obstacle. It’s also used as a mask for the foam.
That’s all for now, I might go into more detail later on. In the mean time, enjoy!