python - 如何在 MacOS 上使用 QGLFormat 更改 OpenGL 版本?

标签 python macos opengl pyqt4 qglwidget

我在 Mac 上使用 PyOpenGL。默认情况下,使用 OpenGL 2.1。但是,根据我的研究和 OpenGL Extension Viewer,我应该能够使用 OpenGL 4.1。 我正在尝试将 QGLFormat 传递给我的 QGLWidget,正如我在此处的许多线程上看到的那样,但上下文版本不会更改。如果我尝试强制它,它会告诉我上下文无效。 我已经进行了很多实验 - 这是一个非常简单的示例,显示了我的问题:

from PyQt4 import QtGui, QtCore, QtOpenGL
import sys

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)

    glFormat = QtOpenGL.QGLFormat()
    glFormat.setVersion(4,1)
    glFormat.setProfile(QtOpenGL.QGLFormat.CoreProfile)
    glFormat.setSampleBuffers(True)
    glFormat.setDefaultFormat(glFormat)
    print("Format version: " + str(glFormat.majorVersion()))
    myW = QtOpenGL.QGLWidget(glFormat)
    print ("Widget context valid: " + str(myW.context().isValid()))
    print ("Widget format version: " + str(myW.format().majorVersion()))
    print ("Widget context format version: " + str(myW.context().format().majorVersion()))
    myW.context().setFormat(glFormat)
    print ("Forced format valid: " + str(myW.context().isValid()))
    print ("Forced format version: " + str(myW.format().majorVersion()))
    myW.show()
    sys.exit(app.exec_())

这是输出:

Format version: 4
Widget context valid: True
Widget format version: 1
Widget context format version: 1
Forced format valid: False
Forced format version: 4

知道我的问题出在哪里吗?难道我做错了什么? 我使用的是 macOS Sierra 版本 10.12.6。 我使用 Qt 版本 4.8.7、sip 版本 4.19.3 和 pyqt 版本 4.12(如果相关的话)。 这是what OpenGL Extension Viewer tells me .

任何帮助将不胜感激!

编辑:

我在这里发现了与 C++ 类似的问题。我不确定如何将解决方案转换为 PyQt,但我会研究一下: Changing the OpenGL Context Version for QGLWidgets in Qt 4.8.6 on OS X .

编辑3:

在尝试@ekhumoro 提供的补丁(第二个版本)时,我得到以下输出:

patching file qpy/QtOpenGL/core_profile_attributes.mm
patching file qpy/QtOpenGL/qpyopengl.pro
patching file sip/QtOpenGL/qgl.sip
patch unexpectedly ends in middle of line
Hunk #3 FAILED at 493.
1 out of 3 hunks FAILED -- saving rejects to file sip/QtOpenGL/qgl.sip.rej

qpyopengl.pro 现在已正确修补,但 qgl.sip 仍然失败。

更新:

以下是 qgl.sip 的拒绝文件的内容:

***************
*** 478,481 ****

  %ModuleHeaderCode
  #include <qpyopengl_api.h>

--- 493,498 ----

  %ModuleHeaderCode
  #include <qpyopengl_api.h>
+ typedef struct GDevice** GDHandle;
+ void* select_3_2_mac_visual();

出于好奇,我运行了configure-ng.py并尝试编译。我收到以下错误:

[...]/PyQt4_gpl_mac-4.12.1/sip/QtOpenGL/qgl.sip:269:5: error: 'virtual' can only appear on non-static member functions
    virtual void* chooseMacVisual(GDHandle handle)
    ^
[...]/PyQt4_gpl_mac-4.12.1/sip/QtOpenGL/qgl.sip:271:16: error: use of undeclared identifier 'select_3_2_mac_visual'
        return select_3_2_mac_visual();
               ^
[...]/PyQt4_gpl_mac-4.12.1/sip/QtOpenGL/qgl.sip:269:44: warning: unused parameter 'handle' [-Wunused-parameter]
    virtual void* chooseMacVisual(GDHandle handle)

最佳答案

无论如何,在我的 Windows 10 笔记本电脑上运行代码会得到以下输出:

Format version: 4
Widget context valid: True
Widget format version: 4
Widget context format version: 4
Forced format valid: False
Forced format version: 4

因此,我怀疑您的问题实际上可能不是特定于平台的问题,而是与您的 myW.context().setFormat(glFormat) 调用有关。有趣的是,我看了一下PyQt documentation for QGLWidget而且 setFormat() 似乎缺少它,这非常没有帮助!

查看相应的C++文档,看起来setFormat()实际上可以从QGLWidget itself任一调用。 ,或者它 child QGLContext目的。由于您是从 QGLContext 调用它,因此上下文被重置,从而使其无效。解决方案是在设置格式后调用myW.context().create(),从而使用新参数创建一个有效的格式对象!该修改如下所示:

from PyQt4 import QtGui, QtCore, QtOpenGL
import sys

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)

    glFormat = QtOpenGL.QGLFormat()
    glFormat.setVersion(4,1)
    glFormat.setProfile(QtOpenGL.QGLFormat.CoreProfile)
    glFormat.setSampleBuffers(True)
    glFormat.setDefaultFormat(glFormat)
    print("Format version: " + str(glFormat.majorVersion()))
    myW = QtOpenGL.QGLWidget(glFormat)
    print ("Widget context valid: " + str(myW.context().isValid()))
    print ("Widget format version: " + str(myW.format().majorVersion()))
    print ("Widget context format version: " + str(myW.context().format().majorVersion()))
    myW.context().setFormat(glFormat)
    myW.context().create()
    print ("Forced format valid: " + str(myW.context().isValid()))
    print ("Forced format version: " + str(myW.format().majorVersion()))
    myW.show()
    sys.exit(app.exec_())

另一种选择是在 QGLWidget 级别调用 setFormat(),这会自动创建一个新上下文,结果如下:

from PyQt4 import QtGui, QtCore, QtOpenGL
import sys

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)

    glFormat = QtOpenGL.QGLFormat()
    glFormat.setVersion(4,1)
    glFormat.setProfile(QtOpenGL.QGLFormat.CoreProfile)
    glFormat.setSampleBuffers(True)
    glFormat.setDefaultFormat(glFormat)
    print("Format version: " + str(glFormat.majorVersion()))
    myW = QtOpenGL.QGLWidget(glFormat)
    print ("Widget context valid: " + str(myW.context().isValid()))
    print ("Widget format version: " + str(myW.format().majorVersion()))
    print ("Widget context format version: " + str(myW.context().format().majorVersion()))
    myW.setFormat(glFormat)
    print ("Forced format valid: " + str(myW.context().isValid()))
    print ("Forced format version: " + str(myW.format().majorVersion()))
    myW.show()
    sys.exit(app.exec_())

话虽这么说,所有这些都是推测,因为我没有可以测试此代码的 Mac。请告诉我这是否可以解决您的问题,并希望它有所帮助!

关于python - 如何在 MacOS 上使用 QGLFormat 更改 OpenGL 版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46834905/

相关文章:

Java LWJGL OpenGL将3d点转换为2d点

image-processing - glGetTexImage 返回全黑纹理

python - 对列表的 numpy 数组进行排序

python - 为什么我的电脑上已经有camelot却找不到camelot?

macos - 在哪里可以找到有关如何在Mac上安装Vala的说明?

openGL像素坐标

python - ModelForm 的表单类可以更改属性吗?

Python相互依赖类(循环依赖)

c++ - 无法在 Maya 插件中编译顶点着色器

macos - WebStorm - 注释行快捷方式不起作用