GPU particles

Showcase your libraries, tools and other projects that help your fellow love users.
Magitek
Prole
Posts: 48
Joined: Sun Dec 13, 2009 2:23 am

GPU particles

Post 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
Attachments
gpart_notables.love
higher compatibility version with hardcoded particle data in the shader
(35.36 KiB) Downloaded 177 times
gpart.love
(35.24 KiB) Downloaded 222 times
Last edited by Magitek on Mon Oct 24, 2016 6:06 am, edited 1 time in total.
User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: GPU particles

Post by raidho36 »

Does it runs on a patched version? When I try to run it, it immediately throws "invalid number of arguments" error.
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: GPU particles

Post 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.
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
lt = love.thread
li = love.image
lg = love.graphics
Magitek
Prole
Posts: 48
Joined: Sun Dec 13, 2009 2:23 am

Re: GPU particles

Post 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.
Magitek
Prole
Posts: 48
Joined: Sun Dec 13, 2009 2:23 am

Re: GPU particles

Post 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.
User avatar
pgimeno
Party member
Posts: 3550
Joined: Sun Oct 18, 2015 2:58 pm

Re: GPU particles

Post 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.
Magitek
Prole
Posts: 48
Joined: Sun Dec 13, 2009 2:23 am

Re: GPU particles

Post 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?
User avatar
pgimeno
Party member
Posts: 3550
Joined: Sun Oct 18, 2015 2:58 pm

Re: GPU particles

Post 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.
Magitek
Prole
Posts: 48
Joined: Sun Dec 13, 2009 2:23 am

Re: GPU particles

Post 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.
Magitek
Prole
Posts: 48
Joined: Sun Dec 13, 2009 2:23 am

Re: GPU particles

Post 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.
Attachments
gpart_notables.love
(35.36 KiB) Downloaded 145 times
Post Reply

Who is online

Users browsing this forum: No registered users and 223 guests