Page 1 of 2

GPU particles

Posted: Sun Oct 23, 2016 5:56 am
by Magitek
I've been working on my game and finding particle systems a big drain on performance, that is until I found a GPU particle example by Jonbro. (viewtopic.php?t=81865).

With his permission, I'm releasing an enhanced version with the following features:

Particle collision via distance field calculation.
Control over various parameters like spawn rate and particle type.
Particle stretching with velocity.
Multiple particle systems working alongside each other.
Multiple types of particles possible within a single system.
Multiple particle textures in a single system.
Translation and scaling of the particles within world space.
Delta time instead of lockstep velocity.

It requires a video card capable of 32 bit floating point textures, although it will run on 16f - it doesn't look good past a certain resolution. Your mileage may vary on mobiles and laptops. Some people have had problems with this system in the past but I had none between 3 different machines personally - although I haven't tested this using a modern AMD video card yet. I'm sure there are multiple issues and performance enhancements that could be made to this, but I've run out of time. I wanted to have it automatically re-compile particle shaders from strings to construct each particle system based on parameters for maximum efficiency.

GPU particles aren't as flexible as CPU systems, but they are a great deal faster. 1 million particles, each with individual collision and texture are no problem. Modern games typically combine light CPU particle systems with GPU particles to make up numbers.

Image
Image

The actual textures in memory storing all the particles:
Image

The distance field:
Image
This provides the collision normals for determining particle reflections. It's a fairly heavy shader pass but it doesn't need to run every frame. I have it set to reconstruct every 50ms, with the previous distance field interpolated with camera movement, which is sufficient for my game - it's not that bad running every frame, but I'd avoid it where possible.

Ideally for performance reasons you'll want to split up your particle effects instead of using one giant shader for all of them (although one system is much more efficient if you're using a lot of one particle). Each particle effect should have it's own shader unless it can reasonable share physics without overloading your shader with comparison statements.

When or If Love develops an asynchronous PBO/getPixel implementation, GPU particles may be used for more complicated purposes, like managing hundreds of thousands of objects which the CPU cannot and similar applications like that. I think in it's current state you could do liquid, but if you want to interact with it from the CPU that makes it difficult to do in real-time.

Known issues:
Collision inaccuracy from either scaling or the 1024x1024 distance field.
RGBA16f could probably still be used for a big speed and compatibility boost, but I'm still not sure how to get it working acceptably.
It's possible for particles to get stuck, especially if the distance field isn't regenerated when scaling the view.
Distance field rendering normals could be improved. The field should actually extend to well within the collider so that particles that overstep the collision barrier can escape.
Particles under a certain velocity don't have the floating point accuracy to actually move. This is not much of a problem generally since you can scale both the system up/down and the particle itself, although 16f positional textures will make it readily apparent.

This is not a library that I will be maintaining, but I thought it might be useful to the community in its current state. Let me know if you have problems or have an interesting effect to share. Jonbro's original work is licensed under MIT and mine under public domain.

edit: updated with a higher compatibility version

Re: GPU particles

Posted: Sun Oct 23, 2016 8:24 am
by raidho36
Does it runs on a patched version? When I try to run it, it immediately throws "invalid number of arguments" error.

Re: GPU particles

Posted: Sun Oct 23, 2016 10:10 am
by Nixola
I managed to get it to work with 0.11.0 (monkeypatching setColor to make it accept 0-255 colours); it's nice, it doesn't ever drop under 60 FPS on an integrated GPU (an Intel HD 530 if I recall correctly). By the way, I don't understand this comment:

Code: Select all

gp_velocity_format = "rgba32f"--32 provides more variety, but usually isn't worth the wasted vram
If your VRAM usage is accurate, I get 40MB of used VRAM with rgba16f and 41.5 with rgba32f.

Re: GPU particles

Posted: Sun Oct 23, 2016 10:21 am
by Magitek
raidho36 wrote:Does it runs on a patched version? When I try to run it, it immediately throws "invalid number of arguments" error.
It runs on stock 0.10.1, assuming I uploaded the most recent version.

I think GLSL has some misgivings about the table I use to upload particle data, I might have to remove it and hardcode them.

Re: GPU particles

Posted: Sun Oct 23, 2016 10:27 am
by Magitek
Nixola wrote:I managed to get it to work with 0.11.0 (monkeypatching setColor to make it accept 0-255 colours); it's nice, it doesn't ever drop under 60 FPS on an integrated GPU (an Intel HD 530 if I recall correctly). By the way, I don't understand this comment:

Code: Select all

gp_velocity_format = "rgba32f"--32 provides more variety, but usually isn't worth the wasted vram
If your VRAM usage is accurate, I get 40MB of used VRAM with rgba16f and 41.5 with rgba32f.
Well that's kind of interesting - the normal example uses just as you say; but when you use a million particles, there's a much larger difference: 81.7mb -> 98.5mb.

32f is slower regardless so that's a factor too. I just didn't notice much improvement in velocities with 32f to warrant using it.

Re: GPU particles

Posted: Sun Oct 23, 2016 8:40 pm
by pgimeno
How is it supposed to be used? If I click and drag my mouse frantically I occasionally see a moving dot like the one to the right of rgb32f in this snapshot:
Image
but nothing like in your snapshots above.

Re: GPU particles

Posted: Mon Oct 24, 2016 1:50 am
by Magitek
hmm that looks quite odd. Can you take a screenshot of debug mode 1 while holding right mouse?
Also what kind of video card are you using?

Re: GPU particles

Posted: Mon Oct 24, 2016 3:35 am
by pgimeno
nVidia GeForce 210, with proprietary drivers (version 340.96). LÖVE 0.10.1 is supported. Screenshot:
Image
Output in terminal:

Code: Select all

$ love10 gpart.love 
Detected desktop resolution: 1280,1024
Render-to-texture limit: 16
Texture size limit: 8192
Texture formats supported:
   rgb10a2
   r32f
   rgba4
   r16f
   r8
   rg32f
   rgba32f
   rgba8
   rgb565
   normal
   rgba16f
   rg16f
   rgb5a1
   hdr
   rg8
   srgb
   rg11b10f
Changing resolution: 1280,720
Constructing GP particle tables and canvases using resolution: 1280 / 720
GPu: Initialized gp with collision texture.
GPu: Autocreating a mesh..
GPu: Initializing gp: table: 0xb77d2d58
GPu: Initialized gp with collision texture.
GPu: Autocreating a mesh..
GPu: Initializing gp: table: 0xb3bfbc68
GPu: Initialized gp with collision texture.
GPu: Initializing gp: table: 0xb77cb7f0
GPu: Initialized gp with collision texture.
GPu: Initializing gp: table: 0xb506db48
GPu: Initialized gp with collision texture.
GPu: Initializing gp: table: 0xb186e368
GPu: Initialized gp with collision texture.
GPu: Initializing gp: table: 0xb506dad8
GPu: Initialized gp with collision texture.
GPu: Initializing gp: table: 0xb506b6d0
GPu: Initialized gp with collision texture.
GPu: Initializing gp: table: 0xb186ec18
Window resized to 640x720.
Window resized to 640x480.
Window resized to 775x480.
Window resized to 768x480.
Before resizing I don't see anything either. I resize the window only to make the screenshots smaller.

Re: GPU particles

Posted: Mon Oct 24, 2016 5:35 am
by Magitek
Image
Yeah the data looks different somehow, almost like your textures are half size. Could take some serious debugging.

Does the original demo work properly?: viewtopic.php?t=81865

I wonder how forcing driver settings like AA and texture quality would affect this system.

Re: GPU particles

Posted: Mon Oct 24, 2016 6:04 am
by Magitek
Actually pgimeno, that looks identical to my radeon laptop. I think the problem may actually be with the rendering side.
raidho36 wrote:Does it runs on a patched version? When I try to run it, it immediately throws "invalid number of arguments" error.
Try this table-less version if you get time.