我目前在 144 HZ 显示器上使用 shady,我正试图将 shady world 刷新率限制为 90 Hz。据我了解,降低 FPS 的唯一方法是使用“SetSwapInterval”,它将帧速率降低一半或三分之一。有没有其他方法可以通过调用 shady 而不使用 time.sleep() 或其他基于 python 的时间来实现这种效果?
1 回答
首先,重要的是要理解:如果您更新屏幕内容的时间间隔不是显示器物理刷新周期的整数倍,那么您一定会得到一种或另一种类型的时间伪影。如果避免时间伪影很重要,唯一好的解决方案是不要以 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 )