Shrinking a dirty rect

397 Views Asked by At

Trying to optimize a falling sand simulation and I'm implementing optimizations that the noita devs talked about in their GDC talk. At around 10:45 they talk about how they use dirty rects. I've started trying to implement a similar system.

Currently, I am able to create a dirty rect that covers the particles that need updating. I do this by every time a valid particle(particle is not air or solid like a wall) is set inside a chunk, I call a function to update the dirty rect giving the placed particles position as an argument. From there, I can easily calculate the new min/max of the rectangle from this position.

Here's a gif of that working. Dirty rect expanding as particles update

and here's the code for updating the rect:

public void UpdateDirtyRect(int2 newPos)
{
    minX = Math.Min(minX, newPos.x);
    minY = Math.Min(minY, newPos.y);
    maxX = Math.Max(maxX, newPos.x);
    maxY = Math.Max(maxY, newPos.y);

    dirtyrect = .(.(minX, minY), .(maxX, maxY));
    //Inflate by two pixels. Not doing this will cause the rect to not change size as particles update
    dirtyrect=dirtyrect.Inflate(2);
}

The problem, as can be seen in the gif, is that I currently have no way to shrink the dirty rect. I can do a few things, such as detecting when a particle is erased/replaced with air/solid particle on the boundary edge of the dirty rect, but I'm unsure on what to do from there.

1

There are 1 best solutions below

2
On

Here’s one approach that might work for you.

  1. Keep the dirty rectangle updated by the previous frame.

  2. Compute the dirty rectangle updated by one frame only.

  3. Combine these two rectangles into a single one that contains both of them.

  4. Use the rectangle from step 3 to update the screen.

  5. Replace the previous frame rectangle with the one you have computed on step 2. Not the combined one you computed on step 3, doing so would cause the same problem you’re describing.