在没有屏幕撕裂的情况下实现较低的帧速率

Achieving lower frame rates without screen tearing

我想在游戏中达到 24fps。我可以使用以下代码执行此操作:

IsFixedTimeStep = info.fixedTimeStep;
TargetElapsedTime = TimeSpan.FromSeconds(1f / 24f);

然而,这会产生卡顿帧率或屏幕撕裂,具体取决于是否启用垂直同步。我预计会出现这种情况,因为显示器的 24fps 和 60fps 不匹配。

我决定改为尝试达到 30fps:

IsFixedTimeStep = info.fixedTimeStep;
TargetElapsedTime = TimeSpan.FromSeconds(1f / 30f);

然而,此 会产生图像卡顿或屏幕撕裂。我不明白为什么当 30fps 是 60fp 显示器刷新的一半时会发生这种情况。可能是涉及到的帧率不准确?

谷歌搜索让我发现我可以通过让 Monogame 同步每隔一次屏幕刷新来获得更好的结果:

graphics = new GraphicsDeviceManager(game);
graphics.PreparingDeviceSettings += (sender, e) =>
{
    e.GraphicsDeviceInformation.PresentationParameters.PresentationInterval = PresentInterval.Two;
};

[编辑 1:我注意到这是一个坏主意,因为它假设显示器刷新率为 60,所以我更需要一个更好的方法!]

[编辑 1.1:我发现此行指定 60fps 作为基础,然后使用上述达到 30fps 的技术:

game.TargetElapsedTime = TimeSpan.FromTicks(166666);

]

这给了我大约 30fps 的速度,但结果很流畅。这对我来说是一个可以接受的结果,但我想知道是否有人知道有什么方法可以达到接近 24fps 的水平?或者如果没有 jittering/tearing 是不可能的?

非常感谢!

[编辑 2:无论是在独家全屏还是无边框 window 模式下,我得到的结果都是一样的。]

好吧,我想出了我认为最好的解决方案。这给了我 24fps 的结果,结果非常流畅(可能会达到 24fps 的流畅度)。

IsFixedTimeStep = true;

TargetElapsedTime = TimeSpan.FromTicks(208333); // 48fps (will be halved to 24fps).

// The following effectively halves the frame rate to 24fps by syncing every other refresh.
graphics.PreparingDeviceSettings += (sender, e) =>
{
    e.GraphicsDeviceInformation.PresentationParameters.PresentationInterval = PresentInterval.Two;
};

它比仅使用 TimeSpan.FromTicks(416666) 将其设置为 24fps 提供更好的结果。我不确定这是为什么。

30fps 可以通过将 FromTicks 值调整为 60fps 来实现,然后减半为 30fps。同样,它为我带来了比一开始只瞄准 30fps 更好的结果。