如何在PyOpengl中启用垂直同步?

4
正如标题所说,我想在PyOpenGL中开启垂直同步,但是我该怎么做呢?进行了相当详尽的网络搜索,没有找到任何结果,但也许有人有聪明的解决方案?我使用的是OS X系统,不介意使用哪个包来创建窗口和应用程序循环。然而,出于下面讨论的原因,我宁愿避免开发一个完整的Cocoa应用程序。

我研究了使用pyglet而不是PyOpenGL,但是运行在64位操作系统上的唯一版本是一个将近一年前的alpha版本,所以我不想使用它,因为我担心它可能已经被放弃了。这很遗憾,因为它看起来比PyOpenGL好得多。

this page上,我找到了以下代码。页面说它是为pygame编写的,但它看起来也适用于Glut。然而,当我运行它(在创建上下文之后)时,它只会导致分段错误。如果有人能够解释一下为什么会发生这种情况,那就太好了,因为我正在寻找类似这样的东西。

import sys

def enable_vsync():
    if sys.platform != 'darwin':
        return
    try:
        import ctypes
        import ctypes.util
        ogl = ctypes.cdll.LoadLibrary(ctypes.util.find_library("OpenGL"))
        # set v to 1 to enable vsync, 0 to disable vsync
        v = ctypes.c_int(1)
        ogl.CGLSetParameter(ogl.CGLGetCurrentContext(), ctypes.c_int(222), ctypes.pointer(v))
    except:
        print "Unable to set vsync mode, using driver defaults"

我可以尝试使用pygame,看看这段代码是否可以与其配合使用,但我在网上找到了几份报告,称这段代码也会导致pygame崩溃,所以我猜想它曾经有效,但现在不再有效。
最后,我知道一个可行的解决方案是使用PyObjC构建Cocoa应用程序。然而,那里有一个相当大的学习曲线,并且我最终得到的东西与跨平台完全不相似。这段代码仅供我个人使用,但如果我在几年后在另一台机器上回来,我非常关心最大化再次使其工作的可能性。出于这些原因,我真的不认为构建Cocoa应用程序是我想要涉足的领域。

似乎通过ctypes使用CGL的任何方法,除了CGLGetCurrentContext之外,都会导致分段错误。 - N. Virgo
4个回答

4

我已经成功修复了你的分段错误。这里是在Mac上启用垂直同步的可行代码:

import sys

def enable_vsync():
    if sys.platform != 'darwin':
        return
    try:
        import ctypes
        import ctypes.util
        ogl = ctypes.cdll.LoadLibrary(ctypes.util.find_library("OpenGL"))
        v = ctypes.c_int(1)

        ogl.CGLGetCurrentContext.argtypes = []
        ogl.CGLGetCurrentContext.restype = ctypes.c_void_p

        ogl.CGLSetParameter.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
        ogl.CGLSetParameter.restype = ctypes.c_int

        context = ogl.CGLGetCurrentContext()

        ogl.CGLSetParameter(context, 222, ctypes.pointer(v))
    except Exception as e:
        print("Unable to set vsync mode, using driver defaults: {}".format(e))

在创建并设置上下文后,只需调用enable_vsync()函数即可。


这太棒了。复制粘贴后就像魔法一样运行。 - juliusmh

2
在pygame的2.0.0版本中,添加了一个名为vsync的新选项,可以在pygame.display.set_mode(...)中使用。
它的用法应该类似于:-

pygame.display.set_mode(screen_size,DOUBLEBUF|OPENGL,vsync=1)

如果您不想使用垂直同步,则写入vsync=0。
但是,对我来说它还没有起作用,在官方pygame网站上写道,它是实验性的,并且将来可能会更改。如果它对我有用,我会编辑这个答案。
如果您找不到它,您可以从这里查看该网站:-

https://www.pygame.org/docs/ref/display.html#pygame.display.set_mode


0

尝试使用WinDLL来加载OpenGL DLL,并将CGL替换为GL或gl(哪个有效)作为函数名称。 例如: ogl = ctypes.windll.LoadLibrary(ctypes.util.find_library("OpenGL")) 然后您的函数: [GL,gl(推荐)]GetCurrentContext()


0
我目前使用pyglet解决了这个问题。虽然很长时间没有检查代码,但似乎仍有一个活跃的社区,其中主要开发人员参与其中。它是跨平台的,非常容易上手。我只是使用pyglet来管理窗口,并使用PyOpenGL进行OpenGL相关操作。如果需要,稍后我可以使用pyglet更快但较低级别的OpenGL绑定,并利用pyglet提供的各种额外功能。
然而,情况感觉有点不稳定,因为没有官方发布适用于OS X Mountain Lion的版本(我从最新源代码安装),我担心我的代码在未来一两个OS X升级后可能会停止工作。因此,如果有人有不使用pyglet的解决方案,我仍然非常感激。

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