(Originally posted on Mastodon)

I’m working on the generation of the mesh to render the simulated water. It’s a bit weird with this debug material, but very useful during development. Also, I can now run the simulation in the Godot editor which is very handy.

Screen capture of the 3D green mountainous terrain under a blue sky. This time it runs in the Godot editor. We can see a small stream of "water" running down the slope, excepted it's a debug material, an opaque checkerboard of gray and white squares. The flow increases and a larger amount of water flows down the slope, seen from multiple camera angles.

Each square is a voxel of liquid (1 meter per 1 meter).

Next step is the water material. I do not plan to achieve anything photo-realistic, but at least something translucent, with animated ripples, following the flow speed.

I’ve implemented a system that generates a flow map, storing the water velocity in each vertex of the mesh. Then I took this shader, and made some modifications to add the flowing movement and support non-horizontal surfaces. It’s not final yet, lot of things to improve, and I’d like to add foam, but it’s already really improving the result!

Yet another screen capture video of the same 3D green mountainous terrain under a blue sky, running in the Godot editor. We can see a small stream of water running down the slope, successively filling two small ponds, overflowing and continuing as a small stream in the distance. The water shader has animated ripples which follow the correct flow direction (even though there are glitches), and reflects the environment and the sun.

Each horizontal slice of water runs a micro-fluid-simulation to compute the local flow map, using the “virtual pipes” method, which is nicely explained here. The result gives a map of velocities, and as long as the shape of the slice does not change, this is not re-computed. So while the shader gives an illusion of movement, the flow map is static and only upated when needed.

The simulation is split in chunks, and a mesh is generated for each chunk only when its shape is modified. So this doesn’t use much computation power, since in most cases only a few chunks are modified each frame, most of the simulation is in a stable state. Still, there are cases where more chunks are impacted, so to avoid degrading performances when it happens, I have implemented the liquid mesher in a separate thread.

I’ve also made some improvements and fixed bugs. And I’m spending way too much time looking at the results, especially when I’m tired 😅 I guess it’s a bit mesmerizing.

Video of a 3D landscape seen from the top. We can see a river flowing in from the left of the screen, filling a pool, then overflowing to form another pool a bit farther, and so on, until the river can weave away in the distance.