我正在用Python(pysdl2,PyOpenGL)编写一个使用SDL2和OpenGL的实时交互式图形应用程序。该应用程序连续生成帧,这些帧可能会根据键盘/鼠标输入或基于时间而变化。
我的主要事件循环是从网络上一些我再也找不到的晦涩来源复制的,看起来(简化)如下:
event = sdl2.SDL_Event()
running = True
while running:
# process events
while sdl2.SDL_PollEvent(ctypes.byref(event)) != 0:
if event.type == sdl2.SDL_QUIT:
running = False
# render frame
<some OpenGL commands>
sdl2.SDL_GL_SwapWindow(window)
sdl2.SDL_Delay(10)
据我了解,10 毫秒的延迟旨在给 CPU 一些喘息的空间,事实上,当我删除它时,CPU 使用率翻了一番。
我不明白的是为什么有必要。图形显示采用双缓冲,缓冲交换与垂直回溯同步(60 Hz = 16 ms)。天真地认为,如果<some OpenGL commands>
花费的时间少于 16 毫秒,那么SDL_GL_SwapWindow
无论如何都会引入延迟,因此SDL_Delay
是不必要的。如果他们使用更多,那么程序正在努力跟上显示帧速率,并且引入延迟会受到伤害。
现在从我在回答另一个问题时被告知的,缓冲区交换和因此回溯同步在执行SDL_GL_SwapWindow
时不会发生,但这只会将"同步和交换"指令放入 OpenGL 队列中,并且该指令在之前的所有内容完成后执行。这同样适用于<some OpenGL commands>
.但是这个指令队列是有限的,因此在某些时候,我的程序不会等待回溯,而是等待指令队列中有空间。最终效果应该是相同的:如果事件循环的一次执行平均需要少于 16 毫秒,那么程序的平均延迟时间足以使每次循环执行 16 毫秒。那么,为什么明确的延迟是必要的?
作为第二个问题:考虑到延迟可能会损害帧率,有没有更好的方法让 CPU 休息?
你不需要使用sdl2.SDL_Delay(10)
因为如果你使用event-loop,那么SDL_Delay是SDL2框架的计时器,那么它不需要SDL_Delay。
我的Python 3.10代码通过鼠标单击按键并关闭窗口的示例
event = sdl2.SDL_Event()
running = True
while running:
while sdl2.SDL_PollEvent(ctypes.byref(event)) != 0:
if event.type == sdl2.SDL_QUIT:
running = False
if event.type == sdl2.SDL_KEYDOWN:
if event.key.keysym.sym == sdl2.SDLK_ESCAPE:
running = False
... GL Functions ...
sdl2.SDL_GL_SwapWindow(window)
请记住,事件循环应该像 C/C++ 中的其他循环一样。Java,C#或其他编程语言。
无事件循环手段 您应该使用SDL_Delay()
然后游戏窗口将自动关闭。
我希望你理解 - 我发现了 Python 示例,但它们看起来很奇怪和错误 - 它们写得像"拉丁语"。
我想提高谁像其他编程语言一样理解得更好。 PS:我会用清晰的例子努力工作我的 github:)