From my previous posts, it must now be clear that free-surface fluid dynamics is hard. This is mainly caused by the free surface. Without that, it is possible to write a fluid-in-a-box in a little over 100 lines of C code, as Jos Stam did in his paper Real-Time Fluid Dynamics for Games. However, I could not go down that road. I needed the free surface. I wanted my game to have waves, droplets, splashes, sprays, fountains! How these would make a game, I would figure out after I got the simulation to work.
Work on this project has been standing still for some time while I was working on another project. But this week I picked up work where I left off: making the fluid simulation even faster. Since the SOR solver I was using lends itself well to parallelization, and video cards are good at running parallel programs, I tried to run the solver on the video card (GPU).
The fluid simulation was beginning to approach results of decent quality. However, it was still far too slow. Most of the screenshots I’ve shown so far were done on a 64x64 grid, which barely ran in real-time even on my fast Intel i7 machine. For a full-screen game, I’d need at least 128x128 and preferably 256x256. As I noted before, a doubling of the grid size requires about ten times as much computational power. Clearly, some optimizations were in order.
I’m a very visual type of guy. A picture really does say more than a thousand words. It should come as no surprise that my way of coding and debugging reflects this.
Last week, I wrote to my fluid dynamics professor for advice on the free surface fluid simulation. It was a positive surprise to see that I had run into exactly the same problems as he had in his research. I must have been doing something right then!
It’s been a busy week with little to show for it. As I wrote last time, I more or less gave up on the SPH particle-based method, and opted to fix my grid method instead. That turned out to be harder than I expected.
I realized that the problems I was having with the tracking of the water volume were not as easy to fix as I thought. It seemed that grid-based (Eulerian) methods are very suitable for a continuous fluid, but not so good when a sharp boundary between water and air is needed.
To find the source of the instabilities, I pulled my code apart into more independent steps, that could individually be turned on or off. This did result in a speed hit, but allowed me to quickly trace the source of the problems to the advection routine. This is the part that moves the water along at its own speed.
Since no existing code fit my requirements, I started working on my own fluid simulator a few weeks ago. The idea was to try both a grid-based and a particle-based method, and see which worked better for my situation. I started with the grid-based version.
I looked around for existing code or libraries to do the fluid simulation for me. There are some, but most are either GPL-licensed or too expensive, so they are out of the question for a small-time independent developer like me. Some publications exist on the topic, most notably Jos Stam’s famous Real-Time Fluid Dynamics for Games from 2003. Mick West describes this algorithm in detail in his article Practical Fluid Dynamics. He provides a great overview of the basics, geared towards programmers. A somewhat more mathematical, but broader overview is in Michael Gourlay’s brilliant Gamasutra article Fluid Simulation for Video Games. He gives explanations of many techniques, their respective advantages and drawbacks. Many other interesting (academic) links are on the CFDtoy blog.