【问题标题】:PyQt4 OpenGL: Enabling OpenGL Core ProfilePyQt4 OpenGL:启用 OpenGL 核心配置文件
【发布时间】:2023-04-10 04:57:01
【问题描述】:

我使用的是 Mac OS X Mavericks,iMac 和 NVIDIA GeForce GTX 660M,所以它应该支持 OpenGL 4.1 版和 GLSL 4.1.0 版。但是当我使用这个时:

print("OpenGL: " + str(glGetString(GL_VERSION)))
print("GLSL: " + str(glGetString(GL_SHADING_LANGUAGE_VERSION)))

我明白了:

OpenGL: b'2.1 NVIDIA-8.26.26 310.40.45f01'
GLSL: b'1.20'

我发现我应该启用核心配置文件

class TestWindow(QtGui.QMainWindow):
    def __init__(self, parent = None):
        super(TestWindow, self).__init__(parent)

        # generate random data points
        self.data = np.array([
            [ -0.90, -0.90 ], [ 0.85, -0.90 ], [ -0.90, 0.85 ],
            [  0.90, -0.85 ], [ 0.90,  0.90 ], [ -0.85, 0.90 ]
        ], dtype = np.float32)

        # core profile
        glformat = QtOpenGL.QGLFormat()
        glformat.setVersion(4, 1)
        glformat.setProfile(QtOpenGL.QGLFormat.CoreProfile)
        glformat.setSampleBuffers( True )

        # initialize the GL widget
        self.widget = GLPlotWidget(glformat)
        self.widget.set_data(self.data)

        # put the window at the screen position (100, 100)
        self.setGeometry(100, 100, self.widget.width, self.widget.height)
        self.setCentralWidget(self.widget)
        self.show()

但这并没有解决问题。现在我发现this这个问题在哪里解决了c++的问题:

// Add this in initializeGL before m_shader.setAttributeBuffer:

uint vao;

typedef void (APIENTRY *_glGenVertexArrays) (GLsizei, GLuint*);
typedef void (APIENTRY *_glBindVertexArray) (GLuint);

_glGenVertexArrays glGenVertexArrays;
_glBindVertexArray glBindVertexArray;

glGenVertexArrays = (_glGenVertexArrays) QGLWidget::context()->getProcAddress("glGenVertexArrays");
glBindVertexArray = (_glBindVertexArray) QGLWidget::context()->getProcAddress("glBindVertexArray");

glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

但是我怎样才能在 python3 中做同样的事情呢?

这是我的完整源代码:

# PyQT4 imports
from PyQt4 import QtGui, QtCore, QtOpenGL
from PyQt4.QtOpenGL import QGLWidget
# PyOpenGL imports
from OpenGL.GL import *
from OpenGL.GL.shaders import *

class GLPlotWidget(QGLWidget):
    # default window size
    width, height = 600, 600

    def __init__(self, format = None):
        super(GLPlotWidget, self).__init__(format, None)

    def set_data(self, data):
        self.data = data
        self.count = data.shape[0]
        self.numVAOs = 2
        self.VAOs = [0] * self.numVAOs
        self.numVBOs = 2
        self.VBOs = [0] * self.numVBOs
        self.shader = None
        self.vPositionLocation = 0

    def initializeGL(self):
        glGenVertexArrays(self.numVAOs, self.VAOs)
        glBindVertexArray(self.VAOs[0])

        glGenBuffers(self.numVBOs, self.VBOs)
        glBindBuffer(GL_ARRAY_BUFFER, self.VBOs[0])
        glBufferData(GL_ARRAY_BUFFER, self.count, self.data, GL_STATIC_DRAW)

        VERTEX_SHADER = compileShader("""
            #version 410 core
            layout(location = 0) in vec4 vPosition;
            void main() {
                gl_Position = vPosition;
            }
        """, GL_VERTEX_SHADER)

        FRAGMENT_SHADER = compileShader("""
            #version 410 core
            out vec4 fColor;
            void main() {
                fColor = vec4(0.0, 0.0, 1.0, 1.0);
            }
        """, GL_FRAGMENT_SHADER)

        self.shader = compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)
        glUseProgram(self.shader)

        glVertexAttribPointer(self.vPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0)
        glEnableVertexAttribArray(self.vPositionLocation)

    def paintGL(self):
        glClear(GL_COLOR_BUFFER_BIT)

        glBindVertexArray(self.VAOs[0])
        glDrawArrays(GL_TRIANGLES, 0, self.count)

        glFlush()

    def resizeGL(self, width, height):
        # update the window size
        self.width, self.height = width, height

        # paint within the whole window
        glViewport(0, 0, width, height)

        # set orthographic projection (2D only)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()

        # the window corner OpenGL coordinates are (-+1, -+1)
        glOrtho(-1, 1, -1, 1, -1, 1)

if __name__ == '__main__':
    # import numpy for generating random data points
    import sys
    import numpy as np
    import numpy.random as rnd

    # define a QT window with an OpenGL widget inside it
    class TestWindow(QtGui.QMainWindow):
        def __init__(self, parent = None):
            super(TestWindow, self).__init__(parent)

            # generate random data points
            self.data = np.array([
                [ -0.90, -0.90 ], [ 0.85, -0.90 ], [ -0.90, 0.85 ],
                [  0.90, -0.85 ], [ 0.90,  0.90 ], [ -0.85, 0.90 ]
            ], dtype = np.float32)

            # core profile
            glformat = QtOpenGL.QGLFormat()
            glformat.setVersion(4, 1)
            glformat.setProfile(QtOpenGL.QGLFormat.CoreProfile)
            glformat.setSampleBuffers( True )

            # initialize the GL widget
            self.widget = GLPlotWidget(glformat)
            self.widget.set_data(self.data)

            # put the window at the screen position (100, 100)
            self.setGeometry(100, 100, self.widget.width, self.widget.height)
            self.setCentralWidget(self.widget)
            self.show()

    # create the QT App and window
    app = QtGui.QApplication(sys.argv)
    window = TestWindow()
    window.show()
    app.exec_()

【问题讨论】:

    标签: c++ qt opengl pyqt4


    【解决方案1】:

    如果其他人遇到类似问题,原始代码中的一个严重错误是对glVertexAttribPointer 的调用。

    确保最后一个参数使用ctypes中的c_void_p(0),否则调用无效,VAO不会绘制任何东西。

    【讨论】:

      【解决方案2】:

      从 PyQt4 迁移到 PyQt5 解决了问题

      完整源代码:

      # PyQT5 imports
      from PyQt5 import QtGui, QtCore, QtOpenGL, QtWidgets
      from PyQt5.QtOpenGL import QGLWidget
      from ctypes import *
      # PyOpenGL imports
      from OpenGL.GL import *
      from OpenGL.GL.shaders import *
      from OpenGL.GLUT import *
      
      class GLPlotWidget(QGLWidget):
          # default window size
          width, height = 600, 600
      
          def __init__(self, format = None):
              super(GLPlotWidget, self).__init__(format, None)
      
          def set_data(self, data):
              self.data = data
              self.count = self.data.nbytes
              self.numVAOs = 2
              self.VAOs = [0] * self.numVAOs
              self.numVBOs = 2
              self.VBOs = [0] * self.numVBOs
              self.shader = None
              self.vPositionLocation = 0
      
          def initializeGL(self):
      
              glClearColor(0.0, 0.0, 0.0, 1.0)
      
              self.VAOs = glGenVertexArrays(self.numVAOs)
              glBindVertexArray(self.VAOs[0])
      
              self.VBOs = glGenBuffers(self.numVBOs)
              glBindBuffer(GL_ARRAY_BUFFER, self.VBOs[0])
              glBufferData(GL_ARRAY_BUFFER, self.count, self.data, GL_STATIC_DRAW)
      
              VERTEX_SHADER = compileShader("""
                  #version 410 core
                  layout(location = 0) in vec4 vPosition;
                  void main() {
                      gl_Position = vPosition;
                  }
              """, GL_VERTEX_SHADER)
      
              FRAGMENT_SHADER = compileShader("""
                  #version 410 core
                  out vec4 fColor;
                  void main() {
                      fColor = vec4(1.0, 1.0, 0.0, 1.0);
                  }
              """, GL_FRAGMENT_SHADER)
      
              self.shader = compileProgram(VERTEX_SHADER, FRAGMENT_SHADER)
              glUseProgram(self.shader)
      
              glVertexAttribPointer(self.vPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, c_void_p(0))
              glEnableVertexAttribArray(self.vPositionLocation)
      
          def paintGL(self):
              glClear(GL_COLOR_BUFFER_BIT)
      
              glBindVertexArray(self.VAOs[0])
              glDrawArrays(GL_TRIANGLES, 0, self.count)
      
              glFlush()
      
      if __name__ == '__main__':
          # import numpy for generating random data points
          import sys
          import numpy as np
          import numpy.random as rnd
      
          # define a QT window with an OpenGL widget inside it
          class TestWindow(QtWidgets.QMainWindow):
              def __init__(self, parent = None):
                  super(TestWindow, self).__init__(parent)
                  self.data = np.array([
                      [ -0.90, -0.90 ],
                      [  0.85, -0.90 ],
                      [ -0.90,  0.85 ],
                      [  0.90, -0.85 ],
                      [  0.90,  0.90 ],
                      [ -0.85,  0.90 ]
                  ], dtype = np.float32)
                  # initialize the GL widget
                  glformat = QtOpenGL.QGLFormat()
                  glformat.setVersion(4, 1)
                  glformat.setProfile(QtOpenGL.QGLFormat.CoreProfile)
                  glformat.setSampleBuffers( True )
                  self.widget = GLPlotWidget(glformat)
                  self.widget.set_data(self.data)
                  # put the window at the screen position (100, 100)
                  self.setGeometry(100, 100, self.widget.width, self.widget.height)
                  self.setCentralWidget(self.widget)
                  self.show()
      
          # create the QT App and window
          app = QtWidgets.QApplication(sys.argv)
          window = TestWindow()
          window.show()
          app.exec_()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-06-09
        • 2011-12-13
        • 1970-01-01
        • 1970-01-01
        • 2015-01-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多