PyQt5的Raspberry Pi的OpenGL ES 2.0纹理映射不起作用

时间:2018-03-08 20:42:43

标签: python pyqt raspberry-pi opengl-es-2.0 pyqt5

我想使用PyQT5和OpenGL来创建一个应该在Raspberry Pi Zero上运行Raspbian的交互式应用程序。

第一步是在屏幕上显示图像纹理,但这已经失败,并在Pi上显示错误消息。 (见下文)

然而,在我的Ubuntu开发机器上使用OpenGL 2.0配置文件执行它时运行正常。

#!/usr/bin/env python
import sys

from PIL import Image
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtGui import (QColor, QSurfaceFormat, QOpenGLVersionProfile)
from PyQt5.QtWidgets import QApplication, QGridLayout, QOpenGLWidget, QWidget


class GLWidget(QOpenGLWidget):

    def __init__(self, path, width, height, parent=None):
        super(GLWidget, self).__init__(parent)

        self.path = path
        self.width = width
        self.height = height
        self.texture_array = []
        self.current_texture_index = 0
        self.fps = 0

        self.elapsed = 0
        self.clearColor = QColor(Qt.black)

    def sizeHint(self):
        return QSize(self.width, self.height)

    def initializeGL(self):
        version = QOpenGLVersionProfile()
        version.setVersion(2, 0)

        self.gl = self.context().versionFunctions(version)
        self.gl.initializeOpenGLFunctions()

        self.gl.glEnable(self.gl.GL_DEPTH_TEST)
        self.gl.glEnable(self.gl.GL_TEXTURE_2D)

        self.gl.glClearColor(self.clearColor.redF(), self.clearColor.greenF(),
                             self.clearColor.blueF(), self.clearColor.alphaF())

        img = Image.open(self.path)
        img_data = img.convert("RGBA").tobytes("raw", "RGBA")
        self.texture_array.append(self.frameToTex(img_data, self.width, self.height))

    def frameToTex(self, data, width, height):
        texture_id = self.gl.glGenTextures(1)

        self.gl.glBindTexture(self.gl.GL_TEXTURE_2D, texture_id)

        self.gl.glTexParameterf(self.gl.GL_TEXTURE_2D, self.gl.GL_TEXTURE_MIN_FILTER, self.gl.GL_LINEAR_MIPMAP_LINEAR)
        self.gl.glTexParameterf(self.gl.GL_TEXTURE_2D, self.gl.GL_TEXTURE_MAG_FILTER, self.gl.GL_LINEAR)

        self.gl.glTexParameteri(self.gl.GL_TEXTURE_2D, self.gl.GL_GENERATE_MIPMAP, self.gl.GL_TRUE)
        self.gl.glTexImage2D(self.gl.GL_TEXTURE_2D, 0, self.gl.GL_RGBA, width,
                             height, 0, self.gl.GL_RGBA, self.gl.GL_UNSIGNED_BYTE,
                             data)

        return texture_id

    def paintGL(self):
        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT)
        self.gl.glMatrixMode(self.gl.GL_MODELVIEW)
        self.gl.glLoadIdentity()
        self.gl.glBindTexture(self.gl.GL_TEXTURE_2D, self.texture_array[self.current_texture_index])

        self.gl.glRotatef(-90, 0.0, 0.0, 1.0)

        self.gl.glBegin(self.gl.GL_QUADS)
        self.gl.glTexCoord2f(0.0, 0.0)
        self.gl.glVertex2f(-1.0, -1.0)
        self.gl.glTexCoord2f(0.0, 1.0)
        self.gl.glVertex2f(1.0, -1.0)
        self.gl.glTexCoord2f(1.0, 1.0)
        self.gl.glVertex2f(1.0, 1.0)
        self.gl.glTexCoord2f(1.0, 0.0)
        self.gl.glVertex2f(-1.0, 1.0)
        self.gl.glEnd()

    def resizeGL(self, width, height):
        side = min(width, height)
        self.gl.glViewport((width - side) // 2, (height - side) // 2, side,
                           side)


class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        main_layout = QGridLayout()

        main_layout.setContentsMargins(0, 0, 0, 0)
        widget = GLWidget('images/bg.jpg', 800, 480)
        main_layout.addWidget(widget)

        self.setLayout(main_layout)
        self.currentGlWidget = widget
        self.setWindowTitle("Texture Test")

    def setCurrentGlWidget(self):
        self.currentGlWidget = self.sender()


if __name__ == '__main__':
    app = QApplication(sys.argv)

    format = QSurfaceFormat()
    format.setDepthBufferSize(24)
    QSurfaceFormat.setDefaultFormat(format)

    window = Window()
    window.show()
    sys.exit(app.exec_())

在RPI上执行此代码时不起作用。显示以下错误:

$ python3 GLWidget.py 
MESA-LOADER: failed to retrieve device information
MESA-LOADER: failed to retrieve device information
MESA-LOADER: failed to retrieve device information
Traceback (most recent call last):
  File "GLWidget.py", line 43, in initializeGL
    self.texture_array.append(self.frameToTex(img_data, self.width, self.height))
  File "GLWidget.py", line 46, in frameToTex
    texture_id = self.gl.glGenTextures(1)
TypeError: QOpenGLFunctions_ES2.glGenTextures(): not enough arguments
Abort

我查看了两个绑定的签名:

QOpenGLFunctions_2_0

void glGenTextures(GLsizei n, SIP_PYOBJECT *textures /TypeHint="Union[int, Tuple[int, ...]]"/);

QOpenGLFunctions_ES2

void glGenTextures(GLsizei n, SIP_PYOBJECT textures /TypeHint="Union[int, Tuple[int, ...]]"/);

由于不熟悉python-sip,我尝试使用int-array并将其传递给glGenTexturesleads但没有成功。该数组仍为空。

如何使用PyQT5的RPI OpenGL支持,特别是显示简单的图像纹理?

0 个答案:

没有答案