The final product looks like this
What is flow-map shader?
A flow-map shader animates the UV mapping by using a specially crafted texture encoded with velocity information. It looks like this:
This texture is encoded with positive/negative velocity information. 0.5 red means 0 x-axis velocity and 0.5 green means 0 y-axis velocity. (Because of this most of the texture looks like puke yellow, meaning its velocity is 0, nothing is moving)
We use this texture, map the value from [0,1] back to [-1,1] and simply add it to our UV coordinate to distort the texture.
Adding the flow-map to the UV.
(except the flow-map needs to be mapped)
To understand flow-map shader, one must first understand the relationship between UV mapping and the texture.
Pure red means x is 1, pure black means x is 0.
RED + GREEN = YELLOW so the top-right corner is yellow.
This is the UV map, however, a UV map is not actually a texture. We just like to visualize this way, by using the color RED for X-axis and GREEN for Y-axis. The brighter the colors the higher the axis value is.
In the surface or vertex shader, we get access to a UV coordinate as input from the graphics engine. We usually use this information to figure out what color that pixel on the mesh is by directly using the UV coordinate to find a color from a texture.
The flowmap simply adds a number to the UV coordinate so it’s accessing other pixels. Notice how there are multiple parts of the UV that look fully green, aka maxed out Y value, that means both of those points are accessing the same color pixel, stretching that part of the texture across.
Here’s what it looks like in code, the shader function gets the UV coordinate.
vert function stands for vertex function
the graphics engine passes in the UV of the vertex as the “appdata” struct.
Same goes for the surface shader.
To animate the flow-map we take the flow-map and multiply it by an increasing number, making everything move more and more.
In this video I’m modifying the number that multiplies the flowmap, notice the higher the value the more the texture distorts.
We can now animate it, but not endlessly and seamlessly.
To endlessly animate, we use the time with a “fract” function, so we get a number that goes from 0 to 1 every second. (fract means fraction, so fract(1.23)=0.23) We use this number to multiply the flow-map, making it go from no distortion to maximum distortion every second.
To seamlessly animate, we make two copies of the endless flow-map but we offset one of them to be 0.5 seconds behind the other one. Then we fade them in and out on top of each other so you’ll never see the loop end because it’ll be overlapped by another loop starting. We call the two copies of flow-map phase0 and phase1.
Fun and great for starting to write cool shaders, no advanced math, just addition, and multiplication for a heck of an effect! I can try to answer any questions in the comments or on Twitter @LouisGameDev. Thanks for reading.