首页 > 解决方案 > 如何在黑幕引擎上设置自定义 FPS 限制

问题描述

我目前在 144 HZ 显示器上使用 shady,我正试图将 shady world 刷新率限制为 90 Hz。据我了解,降低 FPS 的唯一方法是使用“SetSwapInterval”,它将帧速率降低一半或三分之一。有没有其他方法可以通过调用 shady 而不使用 time.sleep() 或其他基于 python 的时间来实现这种效果?

标签: pythonshady

解决方案


首先,重要的是要理解:如果您更新屏幕内容的时间间隔不是显示器物理刷新周期的整数倍,那么您一定会得到一种或另一种类型的时间伪影。如果避免时间伪影很重要,唯一好的解决方案是不要以 144Hz 驱动显示器——相反,进入“显示器”控制面板并告诉操作系统实际以 90Hz 驱动它。如果您的硬件/驱动程序不支持这一点,那么这将是“选择你的毒药”的情况。

毒药 A 是让帧更新代码每 1/90 秒即时运行一次,无论屏幕是否物理准备好。在这种情况下,您将花费额外的时间来执行渲染(绘制更多/更大的刺激),但是,无论您是否需要额外的时间,由于屏幕与屏幕不同步,您将不可避免地获得视觉“撕裂”伪影显存。

毒药 B 是抖动帧的调度,因此更新有时相隔一个物理帧(1/144 秒),有时是两个物理帧(2/144 秒),平均到 1/90。在这种情况下,您不会被撕裂,但动画可能会生涩且看起来不规则。此外,在较短持续时间的帧中,您没有获得任何额外的渲染时间,这可能会破坏目的。

在几乎所有设想 Shady 的用例中,这两者都是不可取的,因此 Shady 没有为此提供任何预打包的解决方案。下面是完成任一解决方案的清单,具体取决于您是否运行它--allowTearing。我将默认设置为--fps=40,一个小于 60 的任意目标,以便我可以在我的 60Hz 设置上对其进行测试;显然你会想用--fps=90.

这两种解决方案都涉及sleep()Python 中的 a(在较低级别中破解更精确的东西是没有意义的:睡眠是所有这些问题中最不可怕的)。它们之间的区别只是w.SetSwapInterval(0),其效果是使渲染代码尽可能快地运行,而完全不关心物理屏幕时序(注意:在某些图形驱动程序上,此设置实际上可能会被忽略,在这种情况下你重新陷入毒药B)。

import Shady, time

cmdline = Shady.WorldConstructorCommandLine()

allowTearing = cmdline.Option( 'allowTearing', False, type=bool )
fps = cmdline.Option( 'fps', 40, type=float )

cmdline.Help().Finalize()

w = Shady.World( **cmdline.opts )
Shady.TearingTest(w).z = 0
Shady.FrameIntervalGauge(w)

if allowTearing:
    w.SetSwapInterval( 0 )
else:
    w.SetSwapInterval( 1 )

w.awkwardFrameRate = fps  # change w.awkwardFrameRate on-the-fly if you want

@w.AnimationCallback
def Blah( self, t ):
    try:
        t0, n0, framesPerSecond = self._awkward
    except AttributeError:
        framesPerSecond = None
    if framesPerSecond != self.awkwardFrameRate:
        t0, n0, framesPerSecond = self._awkward = [ Shady.Timing.Seconds(), self.framesCompleted, self.awkwardFrameRate ]
        print( self._awkward )
    deadline = t0 + ( self.framesCompleted - n0 ) / framesPerSecond

    while Shady.Timing.Seconds() < deadline:
        time.sleep(0.001)

Shady.AutoFinish( w )

推荐阅读