At first, I tried recreating the Navier-Stokes equation directly inside Substance Designer and succeeded (sort of), but the node was just too cumbersome since there’s many calculations that need to be done on several components of the simulation’s equation in order for it to look correct. Each calculation of the equation is just one time step, and you’ll need several hundred steps to get a result that’s acceptable. This approach ended up being completely impractical, however it wasn’t a total failure because I came away with the knowledge to achieve what I needed to in a much simpler way.
Before i get into that, i want to spend a moment to talk about what makes a good fluid simulation. This is a long walk, so bear with me. The key is having a non-divergent vector field to advect your texture with. Divergence, in this context, is the measure of how much fluid enters or leaves a given area in a single time step. If more fluid enters than leaves, it has positive divergence, which will eventually lead to pinching. If more fluid leaves than enters, it has a negative divergence, which leads to nasty stretching. A field that has no divergence has the same amount of fluid entering and leaving any given area which leads to a beautiful warping effect with no pinching or stretching. Unfortunately, as I explored the solutions offered to me in Jamie Wong’s post, I realized that creating a divergent free field is easier said than done. Doing so requires calculating pressure from divergence and then using like, 40 - 80 Poisson blurs to generate a nice enough pressure gradient that is then used to create ANOTHER vector field which is subtracted by the previous time step’s velocity field after it has been advected by itself, etc. It gets pretty complicated, but the end goal is to create a non-divergent vector field so that we get those pretty swirly shapes.
In order to cut down on complexity, we can take a step back and think about what’s necessary for us to achieve our end goal. Lets assume that we don’t care about several fluid properties like viscosity or diffusion rate or density for the time being. We also don’t care about variable force, because at the end of the day, we’re not running a simulation, we’re creating a single node that gives us results SIMILAR to a simulation. With that being said, we can just make the assumption that we’ll be using a constant vector field which does not change over time to drive our warping effect. With that assumption, we can just precompute a single vector field, and as long as that vector field is as non-divergent, we’ll get acceptable results.
But… how can I generate a divergent free vector field in Substance Designer? The answer is simpler than you’d think. We use a grayscale height field and calculate it’s curl to create a “Curl Field”. We do this because a Curl Field has the property of being divergent free! Unfortunately, there are no prepackaged tools that creates a Curl Field from a Height Field, but making one is incredibly easy to do, especially if you’re working with a two dimensional vector field.
The set up is easy. Grab a smooth grayscale noise like Perlin noise or Gaussian noise. Convert that into a normal map using Height-To-Normal World Units. (this gives a normal map with a nice range). Then use the Normal Vector Rotation node to rotate your normals by -90 or 90 degrees. That’s it. This creates a vector field where, instead of the vectors moving along the slope, it curls AROUND the slope, hence the name “Curl”.