DirectX:游戏循环顺序,先绘制还是先处理输入?

6
我刚刚阅读了DirectX文档,并在IDirect3DDevice9::BeginScene页面中发现了一些有趣的内容:
为了实现CPU和图形加速器之间的最大并行性,尽可能在调用present之前调用IDirect3DDevice9::EndScene是有利的。
我习惯先处理输入等操作,然后再进行绘制。这样做是否有误?也许游戏循环应该更像这样:(半伪代码,显然)
while(running) {
    d3ddev->Clear(...);
    d3ddev->BeginScene();
    // draw things
    d3ddev->EndScene();

    // handle input
    // do any other processing
    // play sounds, etc.

    d3ddev->Present(NULL, NULL, NULL, NULL);
}

根据文档中的这句话,该循环将“实现最大并行性”。
这是常见的做法吗?按照这种方式排序游戏循环是否有任何缺点?在第一次迭代之后,我并没有看到什么真正的问题...我知道了解像这样的实际速度增加的最好方法是对其进行基准测试,但是否已经有其他人尝试过这个,并且您可以证明任何实际的速度增加?

1
我没有DirectX经验(XNA开发),但我知道这可能会导致游戏出现轻微的“卡顿”感,因为在您的游戏向前步进并更新新提供的输入之前,事物就已经被绘制了。 - RCIX
3个回答

2

我一直觉得先画图再模拟有点“尴尬”,所以我倾向于将绘图推迟到更新之后,但也要在“当前”调用之后。例如:

while True:
   Simulate()
   FlipBuffers()
   Render()

在第一帧上,您没有翻转任何内容(您需要设置事物,以便第一次翻转确实会翻转到已知状态),尽管操作顺序一旦开始就相同,但这总让我感觉更好,比先放置Render()要好一些。


2
简短的回答是,是的,这是常见的做法。请看以下关于PS3上《战神III》游戏循环的演示:http://www.tilander.org/aurora/comp/gdc2009_Tilander_Filippov_SPU.pdf。如果您在以30fps运行双缓冲游戏,则输入延迟将为1/30≈0.033秒,这对人类来说太小了,无法被察觉(作为比较,在100米赛跑中,任何低于0.1秒的反应时间都被认为是虚假起步)。

1
3毫秒绝对不是人类能够察觉的时间间隔,当演奏MIDI钢琴时,4-5毫秒以上的延迟是可以察觉到的,而10毫秒以上的延迟则非常令人讨厌,甚至可能无法正常演奏。不过,在演奏乐器和玩视频游戏之间可能存在差异。 - Viktor Sehr

2
值得注意的是,在几乎所有PC硬件上,BeginScene和EndScene都没有实际作用。事实上,驱动程序会缓存所有绘图命令,当您调用present时,它甚至可能不开始绘制。通常,它们会缓存多个帧的绘图命令以平滑帧率。通常,驱动程序是基于present调用来进行操作的。
这可能会导致在帧率不高时出现输入延迟。
我敢打赌,如果您在present之前立即进行渲染,您将注意不到与上面给出的循环有任何区别。当然,在一些奇怪的硬件上可能会导致问题,因此一般而言,按照您上面的建议进行循环是最好的做法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接