Over the last few decades, developers all over the world have tried to find a way to create realistic and performant real-time fluid simulations. Several approaches naturally emerged from this effort. But is there a perfect solution? What is the difference between approaches? Which approach is used in Zibra Liquids and why? To understand it all, let’s start with the basics.
In general, approaches to fluid simulation can be divided into three main groups – Lagrangian, Eulerian, and hybrid (Lagrangian-Eulerian). Each of them has its strong and weak sides. So the first thing one needs to do when simulating matter is to decide how to describe what the matter is made up of in terms that can be worked on numerically. It can be either a point cloud, a discrete grid of values, or a mesh describing an area/volume of the surface you’re modeling.
The most common approaches used for simulating fluids in game dev are Eulerian. They are grid-based, ergo the simulation space is divided into grid cells where information of different fluid properties (velocity, density, temperature etc.) is stored.
These approaches allow for simulating large-scale effects quickly and are relatively easy to implement, but they also have several weaknesses. For example, to capture finer details, with Eulerian methods, one needs to use a grid with high resolution. There are also difficulties with advection. Eulerian methods are also often computationally more demanding than particle-based simulations. They suffer from high numerical dissipation, which manifests as unphysical viscosity, making modeling low viscosity fluids difficult.
Nevertheless, they are still used in a number of applications, for example, in the popular real-time fluid simulation tool for creating fire, smoke, and explosions for real-time VFX Artists, EmberGen, etc.
The Lagrangian approaches are particle-based. They work by simulating a large number of particles to approximate fluid molecules. The most popular Lagrangian methods are position-based dynamics and smoothed particle hydrodynamics.
In position-based dynamics, particles have speed positions, and they interact with potentials that imitate fluid.
Smoothed-particle hydrodynamics is a similar but less stable approach. It’s mostly used in scientific applications. As it doesn’t have the grid, it depicts fluid more accurately, but it, unfortunately, has lower resolution and is much slower. This can be explained by the fact that to make particles interact with each other, you have to create a computationally expensive acceleration structure.
Niagara, an VFX system for Unreal Engine, gives you a general toolbox to do simulations with particles. With it you can, for example, make a fluid simulation that employs the smoothed-particle hydrodynamics method. Developers create an acceleration structure for particles, which allows them to obtain the data from neighboring particles. But the need to loop over all neighboring particles slows down the solver.
Hybrid approaches combine the Eulerian and Lagrangian methods. They use a grid to exchange data between particles and particles to move the fluid forward.
In general, hybrid methods are much faster than Lagrangian approaches and allow for the generation of more particles. Instead of simulating 60,000 particles in position-based dynamics, they can simulate several million of them.
But the downside is that they are much harder to implement and have higher computational costs than the pure Eulerian methods because it is required to maintain both particles and a grid.
Overall, the number of liquid simulation approaches is quite significant. They have different uses. For example, there are also the Lattice-Boltzmann methods. They are often used for scientific purposes and simulate various physical phenomena such as condensation, vaporization, transition between different states, etc. These methods are very realistic but very slow at the same time.
The most popular Lagrangian-Eulerian method is called Fluid-Implicit-Particle (FLIP). It is an adaptation to fluids of the implicit moment method for simulating plasmas, in which particles carry everything necessary to describe the fluid. Using the particle data, Lagrangian moment equations are solved on a grid.
The solutions are then used to advance the particle variables from timestep to timestep. It is used in various offline simulations, for example, in Blender or in a popular tool such as Houdini.
Moving Least Squares Material Point Method
Apart from FLIP, there are also other methods. Among them is the Material Point Method (MPM) technique, and its improved version, the Moving Least Squares Material Point Method (MLS-MPM), from which our tool, Zibra Liquids, was born.
The main difference between Moving Least Squares Material Point Method and FLIP is that in FLIP, only the force affecting the particles is calculated on the grid, while the velocity is simply stored in the particle.
In the material point method, which was originally based on the Particle-In-Cell (PIC) method, particles do not have their own speed, and compute it from the grid instead. The values of force and speed are stored on the grid. This has its pros and cons. The plus side is that it makes the simulation much more stable. The downside is that it loses far more energy because the velocity transfer from particles to the grid loses the high-frequency details of the velocity. As a result, the energy of the liquid decreases.
MLS-MPM is based on the Affine Particle-In-Cell (APIC) method that uses a velocity gradient matrix describing how a fluid rotates, compresses, and expands around a particle, or more technically, a first order linear approximation of the velocity around the particle. As a result, more information about the velocity is transmitted, which helps to minimize the loss of energy to some extent.
Usually, physics simulations are done on the CPU while letting the GPU do all the graphics processing. But nowadays, GPUs are far more powerful than CPUs and allow for the implementation of general-purpose algorithms (GPGPU). Due to this fact, in Zibra Liquids, we decided to utilize the far larger capabilities of graphical processors to execute simulations on a bigger scale.
The algorithm itself works this way: there are two buffers – one buffer with particles and another with grid data, and both are on the video card.
First, we implement the part of the algorithm called particle to grid. For this purpose, we use a computer shader that reads the data from all particles, then goes through the nearby cells and, using atomic operations, writes into these cells the information about the amount of momentum and mass that every particle transfers as data to the grid.
When all the necessary data is transferred to the grid, we update our grid, receive the speed value, add the acceleration, if it’s necessary, gravitational force, and make an additional dispatch.
It means that we again go through the 27 cells closest to the particle, receive the new particle speed, and approximate the velocity gradient matrix around the particle, subsequently writing everything into the particle buffer.
Our algorithm also calculates interaction with complex objects using our custom neural object representation technology. This technology allows us to pack the Signed Distance Function of an object to save memory and unpack it on the fly directly on the GPU. To calculate interaction with the object, our algorithm evaluates the neural signed distance field function to know how far the particle is from the object. If it is close enough, it adds the force in the direction of normal, which can be computed from the SDF gradient, and thus makes the particles reflect off the object.
For rendering, Zibra Liquids uses two render algorithms. We implemented the first one, utilizing a custom atomic rasterizer and a jump flood algorithm to rasterize a massive number of spheres. After that, the spheres were blurred using a bilateral filter to get the final normals to render the liquid. So, simply put, it works by drawing the centers of the spheres and then extending these centers to neighboring pixels. Spheres grow out of them, like crystals from these seeds. This method allows drawing even 50 million spheres and scales exceptionally well for large amounts of particles.
The second algorithm currently being implemented in Zibra Liquids utilizes a mesh extraction and rendering algorithm. It takes the data from the simulation grid and produces a mesh using the Dual contouring algorithm.
The mesh itself consists of triangles, the number of which can vary depending on the amount of liquid. These triangles are adjusted by using gradient descent and then a Laplacian smoothing operation to better resemble the liquid’s surface. After that, our custom shader can render this mesh.
To properly visualize effects like refraction, full internal reflection, and transparency (absorption and scattering), we use a ray marching algorithm to approximately trace rays inside the liquid. This allows for a far greater level of realism, which is usually not seen in real-time liquid simulations.
Compared to particle rendering methods, rendering the mesh has the huge benefit of using a hardware rasterizer. It allows for much better scaling of the performance with the resolution. It also helps improve performance, which is crucial when dealing with, for example, mobile devices with a limited performance budget.
All of these combined attributes make Zibra Liquids a unique solution for small to midsize liquid simulations. It can simulate up to tens of millions of particles on high-end hardware, hundreds of thousands of particles on laptops, and tens of thousands of particles on mobile devices, all in real-time.
Every aspect of Zibra Liquids’ simulation pipeline is highly optimized. We don’t use open-source code. Everything we do aims to ensure the plugin’s compatibility with all hardware platforms and different APIs, as well as maximum speed. Our API is meant for third-party engines from the get-go. Plugin design allows the scaling of particle count, even enabling the export of a high-quality liquid mesh in the future. Thanks to its core tech, Zibra Liquids can easily become a framework for other visual effects.
We update the plugin regularly to make it even better. Just this February, we released a major update of our Unity version. You can read about it here.
If you have any ideas on how to improve our plugin, feel free to share them via mail, firstname.lastname@example.org, or in our Discord community. In terms of development, we are following our roadmap, but your comments help us accurately choose the priority of our tasks.