PyQt5 应用程序中的极简 PyOpenGL 示例

V.K*_*.K. 5 python pyqt pyopengl pyside

我正在学习PyOpenGL并在PyQt5应用程序中使用它。我正在尝试将一些旧的简单示例从C++/ 转换QtPython. 以下示例应在黑色背景上绘制白色三角形。至少它在相应的C++/Qt代码中。但它什么也不做,只是一个黑色的窗口。任何想法我缺少什么?请注意,我需要使用着色器的“现代”方法(但是根据我的知识 - 我可能是错的 - 以下代码应该只使用默认的普通着色器,即 2D 中的白色)而不是所有那些旧的glBegin(), glEnd().

import numpy as np
from OpenGL import GL
from PyQt5.QtWidgets import QOpenGLWidget, QApplication


class OpenGLWidget(QOpenGLWidget):

    def initializeGL(self):
        vertices = np.array([0.0, 1.0, -1.0, -1.0, 1.0, -1.0], dtype=np.float32)

        bufferId = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, bufferId)
        GL.glBufferData(GL.GL_ARRAY_BUFFER, vertices.size, vertices, GL.GL_STATIC_DRAW)

        GL.glEnableVertexAttribArray(0)
        GL.glVertexAttribPointer(0, 2, GL.GL_FLOAT, GL.GL_FALSE, 0, 0)

    def paintGL(self):
        GL.glDrawArrays(GL.GL_TRIANGLES, 0, 3)


app = QApplication([])
widget = OpenGLWidget()
widget.show()
app.exec_()
Run Code Online (Sandbox Code Playgroud)

V.K*_*.K. 8

好的,最后,我发现了我的错误:

GL.glBufferData(GL.GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL.GL_STATIC_DRAW)  # nbytes instead of size
Run Code Online (Sandbox Code Playgroud)

GL.glVertexAttribPointer(0, 2, GL.GL_FLOAT, GL.GL_FALSE, 0, None)  # i.e. None instead of 0
Run Code Online (Sandbox Code Playgroud)

完整的简约示例如下:

import numpy as np
from OpenGL import GL
from PyQt5.QtWidgets import QOpenGLWidget, QApplication


class OpenGLWidget(QOpenGLWidget):

    def initializeGL(self):
        vertices = np.array([0.0, 1.0, -1.0, -1.0, 1.0, -1.0], dtype=np.float32)

        bufferId = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, bufferId)
        GL.glBufferData(GL.GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL.GL_STATIC_DRAW)

        GL.glEnableVertexAttribArray(0)
        GL.glVertexAttribPointer(0, 2, GL.GL_FLOAT, GL.GL_FALSE, 0, None)

    def paintGL(self):
        GL.glDrawArrays(GL.GL_TRIANGLES, 0, 3)


app = QApplication([])
widget = OpenGLWidget()
widget.show()
app.exec_()
Run Code Online (Sandbox Code Playgroud)

请注意,这并不遵循“最佳实践”——您应该使用着色器和 VAO!这段代码真的是最短的......