Python 如何在MacOS上使用QGLFormat更改OpenGL版本?
我正在Mac上使用PyOpenGL。默认情况下,使用OpenGL 2.1。然而,根据我的研究和OpenGL Extension Viewer,我应该能够使用OpenGL 4.1。 我正在尝试将QGLFormat传递给我的QGLWidget,正如我在这里的许多线程上看到的那样,但是上下文版本没有改变。如果我试图强迫它,它告诉我上下文是无效的。 我已经做了很多实验——下面是一个非常简单的例子,说明了我的问题:Python 如何在MacOS上使用QGLFormat更改OpenGL版本?,python,macos,opengl,pyqt4,qglwidget,Python,Macos,Opengl,Pyqt4,Qglwidget,我正在Mac上使用PyOpenGL。默认情况下,使用OpenGL 2.1。然而,根据我的研究和OpenGL Extension Viewer,我应该能够使用OpenGL 4.1。 我正在尝试将QGLFormat传递给我的QGLWidget,正如我在这里的许多线程上看到的那样,但是上下文版本没有改变。如果我试图强迫它,它告诉我上下文是无效的。 我已经做了很多实验——下面是一个非常简单的例子,说明了我的问题: from PyQt4 import QtGui, QtCore, QtOpenGL imp
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。
这是
任何帮助都将不胜感激
编辑:
我发现这里的C++看起来类似问题。我不确定如何将解决方案转换为PyQt,但我将研究以下内容:
编辑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();
值得一提的是,在我的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)
调用有关。有趣的是,我查看了,setFormat()似乎缺少了它,这是非常没有帮助的
相反,查看相应的C++文档,它看起来像是setFormat()
实际上可以从调用,或者从它的子对象调用。由于您是从QGLContext
调用它,结果表明该上下文是reset,使其无效。解决方案是在设置格式后调用myW.context().create()
,从而使用新参数创建一个有效的format对象!该修改如下所示:
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。请告诉我这是否解决了您的问题,并希望它能帮助您 回答有关将特定于Mac的解决方案转换为Python的特定问题:这不可能直接完成,因为PyQt绑定没有包装虚拟方法。没有这一点,就无法重新实现它,因为Qt无法看到PyQt没有预定义为虚拟的任何Python方法 因此,让它工作的唯一方法是修补PyQt4并重新编译它。幸运的是,已经有人这样做了,并在这里提供了代码:
macgl.diff
,然后运行以下命令:
patch -Np1 -i macgl.diff
然后,您可以使用以下说明编译修补的PyQt4:
diff -Naur c/qpy/QtOpenGL/core_profile_attributes.mm d/qpy/QtOpenGL/core_profile_attributes.mm
--- c/qpy/QtOpenGL/core_profile_attributes.mm 1970-01-01 01:00:00.000000000 +0100
+++ d/qpy/QtOpenGL/core_profile_attributes.mm 2017-10-22 20:11:53.000000000 +0100
@@ -0,0 +1,22 @@
+#include <QGLContext>
+
+
+void* select_3_2_mac_visual()
+{
+ static const int Max = 40;
+ NSOpenGLPixelFormatAttribute attribs[Max];
+ int cnt = 0;
+
+ attribs[cnt++] = NSOpenGLPFAOpenGLProfile;
+ attribs[cnt++] = NSOpenGLProfileVersion3_2Core;
+
+ attribs[cnt++] = NSOpenGLPFADoubleBuffer;
+
+ attribs[cnt++] = NSOpenGLPFADepthSize;
+ attribs[cnt++] = (NSOpenGLPixelFormatAttribute)16;
+
+ attribs[cnt] = 0;
+ Q_ASSERT(cnt < Max);
+
+ return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
+}
diff -Naur c/qpy/QtOpenGL/qpyopengl.pro d/qpy/QtOpenGL/qpyopengl.pro
--- c/qpy/QtOpenGL/qpyopengl.pro 2017-06-30 09:47:26.000000000 +0100
+++ d/qpy/QtOpenGL/qpyopengl.pro 2017-10-31 17:07:37.694805459 +0000
@@ -24,6 +24,11 @@
TARGET = qpyopengl
TEMPLATE = lib
+mac {
+ OBJECTIVE_SOURCES += core_profile_attributes.mm
+ LIBS += -framework Foundation -framework Cocoa
+ }
+
SOURCES = \
qpyopengl_attribute_array.cpp \
qpyopengl_uniform_value_array.cpp
diff -Naur c/sip/QtOpenGL/qgl.sip d/sip/QtOpenGL/qgl.sip
--- c/sip/QtOpenGL/qgl.sip 2017-06-30 09:47:26.000000000 +0100
+++ d/sip/QtOpenGL/qgl.sip 2017-10-31 17:30:26.025295693 +0000
@@ -20,6 +20,14 @@
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+%ModuleCode
+#include <qgl.h>
+
+typedef struct GDevice** GDHandle;
+void* select_3_2_mac_visual();
+
+%End
+
namespace QGL
{
%TypeHeaderCode
@@ -257,6 +265,13 @@
%End
%End
+%TypeCode
+ virtual void* chooseMacVisual(GDHandle handle)
+ {
+ return select_3_2_mac_visual();
+ }
+%End
+
public:
void deleteTexture(GLuint tx_id);
static void setTextureCacheLimit(int size);
@@ -478,4 +493,6 @@
%ModuleHeaderCode
#include <qpyopengl_api.h>
+typedef struct GDevice** GDHandle;
+void* select_3_2_mac_visual();
%End
diff-Naur c/qpy/QtOpenGL/core_profile_attributes.mm d/qpy/QtOpenGL/core_profile_attributes.mm
---c/qpy/QtOpenGL/core_profile_attributes.mm 1970-01-01 01:00:00.000000000+0100
+++d/qpy/QtOpenGL/core_profile_attributes.mm 2017-10-22 20:11:53.000000000+0100
@@ -0,0 +1,22 @@
+#包括
+
+
+void*选择_3_2_mac_visual()
+{
+静态常数int Max=40;
+NSOpenGLPixelFormatAttribute属性属性[Max];
+int-cnt=0;
+
+attribs[cnt++]=NSOpenGLPFAOpenGLProfile;
+属性[cnt++]=NSOpenGLProfileVersion3_2核心;
+
+attribs[cnt++]=NSOpenGLPFADoubleBuffer;
+
+attribs[cnt++]=NSOpenGLPFADepthSize;
+属性[cnt++]=(NSOpenGLPixelFormatAttribute)16;
+
+attribs[cnt]=0;
+Q_断言(cnt
谢谢!至少我知道
diff -Naur c/qpy/QtOpenGL/core_profile_attributes.mm d/qpy/QtOpenGL/core_profile_attributes.mm
--- c/qpy/QtOpenGL/core_profile_attributes.mm 1970-01-01 01:00:00.000000000 +0100
+++ d/qpy/QtOpenGL/core_profile_attributes.mm 2017-10-22 20:11:53.000000000 +0100
@@ -0,0 +1,22 @@
+#include <QGLContext>
+
+
+void* select_3_2_mac_visual()
+{
+ static const int Max = 40;
+ NSOpenGLPixelFormatAttribute attribs[Max];
+ int cnt = 0;
+
+ attribs[cnt++] = NSOpenGLPFAOpenGLProfile;
+ attribs[cnt++] = NSOpenGLProfileVersion3_2Core;
+
+ attribs[cnt++] = NSOpenGLPFADoubleBuffer;
+
+ attribs[cnt++] = NSOpenGLPFADepthSize;
+ attribs[cnt++] = (NSOpenGLPixelFormatAttribute)16;
+
+ attribs[cnt] = 0;
+ Q_ASSERT(cnt < Max);
+
+ return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
+}
diff -Naur c/qpy/QtOpenGL/qpyopengl.pro d/qpy/QtOpenGL/qpyopengl.pro
--- c/qpy/QtOpenGL/qpyopengl.pro 2017-06-30 09:47:26.000000000 +0100
+++ d/qpy/QtOpenGL/qpyopengl.pro 2017-10-31 17:07:37.694805459 +0000
@@ -24,6 +24,11 @@
TARGET = qpyopengl
TEMPLATE = lib
+mac {
+ OBJECTIVE_SOURCES += core_profile_attributes.mm
+ LIBS += -framework Foundation -framework Cocoa
+ }
+
SOURCES = \
qpyopengl_attribute_array.cpp \
qpyopengl_uniform_value_array.cpp
diff -Naur c/sip/QtOpenGL/qgl.sip d/sip/QtOpenGL/qgl.sip
--- c/sip/QtOpenGL/qgl.sip 2017-06-30 09:47:26.000000000 +0100
+++ d/sip/QtOpenGL/qgl.sip 2017-10-31 17:30:26.025295693 +0000
@@ -20,6 +20,14 @@
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+%ModuleCode
+#include <qgl.h>
+
+typedef struct GDevice** GDHandle;
+void* select_3_2_mac_visual();
+
+%End
+
namespace QGL
{
%TypeHeaderCode
@@ -257,6 +265,13 @@
%End
%End
+%TypeCode
+ virtual void* chooseMacVisual(GDHandle handle)
+ {
+ return select_3_2_mac_visual();
+ }
+%End
+
public:
void deleteTexture(GLuint tx_id);
static void setTextureCacheLimit(int size);
@@ -478,4 +493,6 @@
%ModuleHeaderCode
#include <qpyopengl_api.h>
+typedef struct GDevice** GDHandle;
+void* select_3_2_mac_visual();
%End