Pyglet/OpenGL 图像在鼠标移动时闪烁

Pyglet/OpenGL image flickering on mouse movement

我在 YouTube 上关注 "Pyglet Python and OpenGL - part 01 - Hello Triangle" tutorial by Attila Toth 以使用 Pyglet 绘制三角形,因为我以前从未使用过 Pyglet。据我所知,代码与视频中的相同,但是当我移动鼠标时,图像会闪烁,但没有错误消息。

作为参考,我的电脑有 4 GB 内存、i3 7020U 和集成显卡,DirectX 版本 12。我使用的是 Windows 10 build 18632。

代码:

import pyglet
from pyglet.gl import *
class Window(pyglet.window.Window):
    def __init__(self, *args,**kwargs):
        super().__init__(*args, **kwargs)
        self.set_minimum_size(400, 300)

        self.triangle = Triangle()

    def ondraw(self):
        self.triangle.vertices.draw(GL_TRIANGLES)

class Triangle():
    def __init__(self):
        self.vertices = pyglet.graphics.vertex_list(3, ('v3f', [-0.5,-0.5,0.0, 0.5,-0.5,0.0, 0.0,0.5,0.0]),
            ('c3B', [100,200,220, 200,110,100, 100,250,100]))

if __name__ == "__main__":
    window = Window(800, 600, "The Game", resizable=True)
    window.ondraw()
    pyglet.app.run()

我无法重现问题,我的机器上没有闪烁。 (GTX 1070,6 年前的 i7 和 16GB 内存,windows 10 等)

但是,您的代码存在一些小问题。
首先,它是 on_draw 而不是 ondraw,这在以后会变得很重要,因为它是 pyglet.window.Window.on_draw 函数的挂钩覆盖,在某些事件中被调用。

这里还有一个重要的功能就是设置glViewport否则屏幕上什么也不会显示。所以你需要的最少代码是这样的:

import pyglet
from pyglet.gl import *
class Window(pyglet.window.Window):
    def __init__(self, *args,**kwargs):
        super().__init__(*args, **kwargs)
        self.set_minimum_size(400, 300)

        self.triangle = Triangle()

    def on_draw(self):
        self.clear()
        self.triangle.vertices.draw(GL_TRIANGLES)

    def on_resize(self, width, height):
        glViewport(0, 0, width, height)

class Triangle():
    def __init__(self):
        self.vertices = pyglet.graphics.vertex_list(3, ('v3f', [-0.5,-0.5,0.0, 0.5,-0.5,0.0, 0.0,0.5,0.0]),
            ('c3B', [100,200,220, 200,110,100, 100,250,100]))

if __name__ == "__main__":
    window = Window(800, 600, "The Game", resizable=True)
    pyglet.app.run()

了解 on_*** 事件是由 Pyglet 的内部机制触发的,而不是您应该手动调用的东西(就像您在 if __name__ ... 中所做的 window.ondraw() ), 这不是个好主意。

相反,如果您想强制执行一个 draw 事件,只需通过触发 Pyglet 事件来触发它,一些示例是:

  • 鼠标移动
  • 键盘输入(尝试点击 spacebar)
  • 正在设置 clock/timer 以安排更新

闪烁可能来自您的显卡(或缺少适当的驱动程序),它根本无法处理您要求的刷新率。尝试快速点击 space bar 几次,这可能也会导致闪烁。在这种情况下,您可能无法从您期望的机器中获得性能。

解决方法可能是:batched rendering 这会显着缩短渲染时间,不过,对于一个简单的三角形,您应该不会遇到问题。