Unity Fluid

updated:

Position Based Dynamics

This fluid sim runs entirely on the GPU using Unity Compute Shaders, implementing the method from this research paper. The current implementation uses a Bitonic sort for spatial hashing, though other parallel sorting algorithms could potentially offer better performance.

GPU Handles Collisions

Since the fluid system runs on the GPU, we have to represent physical objects as a set of particles on the GPU. I then just made a script that checks if an object is moving, if it is, we update the fluid collision particle positions.

Collision example

We have to take our “boundary particles” compute buffer (commonly refferred to as our fluid domain) and add our collision particles. Here is a simple script that does that.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// in FluidCollider.cs...

private void CreateParticles(ParticleSource source, Matrix4x4 RTS)
{
    Vector4[] positions = new Vector4[NumParticles];

    float inf = float.PositiveInfinity;
    Vector3 min = new Vector3(inf, inf, inf);
    Vector3 max = new Vector3(-inf, -inf, -inf);

    for (int i = 0; i < NumParticles; i++)
    {
        Vector4 pos = RTS * source.Positions[i];
        positions[i] = pos;

        min = Vector3.Min(min, new Vector3(pos.x, pos.y, pos.z));
        max = Vector3.Max(max, new Vector3(pos.x, pos.y, pos.z));
    }

    min -= new Vector3(ParticleRadius, ParticleRadius, ParticleRadius);
    max += new Vector3(ParticleRadius, ParticleRadius, ParticleRadius);

    Bounds = new Bounds();
    Bounds.SetMinMax(min, max);

    PositionsBuffer = new ComputeBuffer(NumParticles, 4 * sizeof(float));
    PositionsBuffer.SetData(positions);
}

The NumParticles property determines the existing boundary particle count:
public int NumParticles { get; private set; }. We need to keep track of this value to ensure we aren’t increasing or decreasing the buffer more than we need to.

Currently there isn’t any voxelization of colliders, it simply computes the collider size by the bounding box of the GameObject.

Planned features

I want to eventually add voxelization to this, as well as improve the performance. I have some ideas involving chunking our fluid domain so we could potentially run a lot of particles (>100k).