缩小脏矩形

问题描述

尝试优化落沙模拟,我正在实施 noita 开发人员在其 GDC talk 中谈到的优化。在 10:45 左右,他们讨论了他们如何使用脏矩形。我已经开始尝试实施类似的系统。

目前,我能够创建一个覆盖需要更新的粒子的脏矩形。每次在块内设置有效粒子(粒子不是空气或固体,如墙)时,我都会这样做,我调用一个函数来更新脏矩形,将放置的粒子位置作为参数。从那里,我可以轻松地从这个位置计算矩形的新最小值/最大值。

这是该工作的 gif。

Dirty rect expanding as particles update

这里是更新矩形的代码

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);
}

从 gif 图中可以看出,问题在于我目前无法缩小脏矩形。我可以做一些事情,例如检测粒子何时在脏矩形的边界边缘被擦除/替换为空气/固体粒子,但我不确定从那里开始做什么。

解决方法

这是一种可能适合您的方法。

  1. 保持脏矩形由前一帧更新。

  2. 计算仅更新一帧的脏矩形。

  3. 将这两个矩形合并为一个包含它们的单个矩形。

  4. 使用第 3 步中的矩形更新屏幕。

  5. 用您在第 2 步计算的矩形替换前一帧矩形。不是您在第 3 步计算的组合矩形,这样做会导致您描述的相同问题。