DirectCompute Particles on a Path

My Rel Por

For the past week I’ve been working on flows for the god game I’m working on. In the game there will be orbs, as seen in the picture above. Orbs come in different types, with a varying number of inputs and outputs.  You can see the definition of each orb type below. When an orb has a nearby neighbor it can possibly receive an output flow that that orb to the neighbor. These orbs are therefore connection points, and the flow moves from orb to orb. In the game these will grow fish populations, or possibly be hazardous and must be redirected.

  • Source orb – 3 outputs

  • Source sink orb – 2 outputs, 1 input

  • Sink orb – 3 inputs

  • Pass through orb – 1 output, 1 input

  • Combination orb – 1 output, 2 input

I started out prototyping a very simple version using LineRenderer in Unity, but I wasn’t very pleased with the results. As our project was already set to DirectX11, I decided to give Compute Shaders a try and see what they can offer. Compute shaders allow for massive parallelism and can be used to run particle simulations on the GPU. Unity has the ability to render directly from compute buffers stored on the device memory using Graphics.DrawProcedural. With the power of compute shaders I am able to get many thousands of moving particles rendered at a somewhat reasonable cost after optimizations.

I didn’t want completely simple particles moving in a straight line from orb to orb, I wanted a bit of variation to the path. To achieve this, I calculate a path on the CPU in C# code, and then initialize a new instance of the particle animation class, creating a compute buffer from this path.  My particle struct looks something like this

struct Particle
{
	float3 pos;
	int nextControlPoint;
	float3 dir;
	float4 color;
};

struct ControlPoint
{
	float3 pos;
	float4 color;
};

By keeping a nextControlPoint counter in the particle struct I’m able to iterate through the control points, when a particle reaches the final point it is sent back to the start. Using some randomization could I randomly fetch points around the actual control point and use that as a target. This spreads the particles out a bit which I think gives a better flow. To get the actual position for the particle in the compute shader, I use Coloumb particle interaction for oppositely charged particles. This gives a force that can be applied to the current position of the particle and results in a smooth path.

To get these on screen takes a little time. I decided to render all of the particle buffer points as MeshTopology.Points, and use a geometry shader to to generate quads from each vertex sent to the vertex buffer. If you’re interested how to do this look up Z-facing billboards. To me this seems like fancy shaders, perhaps it’s not, but it is my first time working with geometry shaders and I must say they are incredibly powerful.

Things I haven’t added yet but want is trails and possibly some better randomization of the points. My partner has been working on some perlin noise shaders that generate RenderTextures which could be used by the compute shader to offset the next location to target. I’ll probably be posting some more code once I have things a bit more cleaned up.