1
\$\begingroup\$

So, for the past couple of weeks, I've been working on a falling sand simulation inspired by games such as The Powder Toy, Noita, and Sandspiel. I've been making it in Love2D and I'm please with what I got so far. The simulation can handle 59k particles at 60FPS however pretty much anything over that amount will cause the FPS to plummet so I've been thinking of other ways to optimize it.

The way my simulation works is that I have a large table that contains numbers. These numbers refer to an index inside a table which contains particle data. The particle data is structured as:

Name, Color(table containing 4 values, r,g,b,a), Update logic function, Color variation modifier (0 = no color variation between particles)

I've got the options for optimization narrowed down to a pretty small list:

  • Spatialhashing/Quadtree - splitting the screen into a grid and only updating cells with particles in it
  • GPU simulation - Moving simulation logic to the GPU
  • Multithreading - Moving simulation logic to separate CPU threads

The downsides of all of these are as follow:

  • Spatialhashing/Quadtree - There are no unique identifiers for the particles themselves as they're only stored in the table as the index for their data so it's hard to have a reference that can be added/removed when needed

  • GPU simulation - I'm not good with shader code and there are no good ways to do GPU code in Love2D that's purely computational.

  • Multithreading - Similar to GPU simulation, I'm not knowledgable when it comes to multithreading nor do I have any idea of how to parallelize my simulation code.

Some information about how to multithread a falling sand physics simulation comes from the devs of Noita, where they split the world into chunks and updated each on a different thread in a checkerboard pattern (to make ensure that pixels weren't being updated by multiple threads at the same time). They also had 'dirty rects' which showed which particles needed updating which is similar to spatial hashing.

However, the talk the noita dev did just showed what they did, rather than how they did it. Since I lack a lot of knowledge in these fields, I don't really have much to go on for implementing them.

My code is open source and viewable on github. You'll need the latest version of Love2D to run it:

https://github.com/BradBath/Sand (either drag the Sand-master folder on the love2D executable or open the folder in VSCode and use the Love2D plugin to run it via LALT+L)

If anyone has any ideas I could implement some of these optimizations, or has any other ideas for optimization, I'd love to hear them. Thanks!

Here's a gif of my simulation at its current point

\$\endgroup\$
  • \$\begingroup\$ One of the engineers for Notia did a pretty in-depth tech talk about optimizations he made youtube.com/watch?v=prXuyMCgbTc. The summary is, don't simulate if you can ignore it. Many things outside of the player's screen or rigid bodies are not single points, but large chunks. \$\endgroup\$ – mobo Jun 10 at 2:22
  • \$\begingroup\$ As mentioned in the OP, I already know about the Noita dev talk and as also mentioned my problem was that it just shows what he did, not how it was implemented. \$\endgroup\$ – Ducktor Jun 10 at 4:19
  • \$\begingroup\$ How did you try to implement this, and where specifically did you get stuck? A narrower focus like that might help you get more actionable answers. \$\endgroup\$ – DMGregory Jun 10 at 16:21
  • \$\begingroup\$ I have no idea how to even start. \$\endgroup\$ – Ducktor Jun 10 at 18:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.