Shader Tutorial: Flow-Map
(5/7/2024)
Hi, I’m Louis Hong.
I’ve rewritten this tutorial for clarity and added additional information.
This new version is posted on my personal blog:
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.
Explained: Distortion
To understand the flow-map shader, one must first understand the relationship between UV mapping and texture.
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.
Explained: Animation/Motion
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.
That’s it!
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.