使用自定义QSurfaceFormat时PySide2 OpenGL错误

问题描述

我正在使用QSurfaceFormat来明确定义 OpenGL Core配置文件并设置次要/主要版本。事实是,自定义表面格式的分配给我以下错误

Traceback (most recent call last):
  File "/home/artem/PycharmProjects/polyEdit3D/polyEdit3D/Widgets/PlyViewport.py",line 22,in initializeGL
    gl.glEnable(gl.GL_COLOR_BUFFER_BIT)
  File "/home/artem/.local/lib/python3.7/site-packages/OpenGL/platform/baseplatform.py",line 415,in __call__
    return self( *args,**named )
  File "src/errorchecker.pyx",line 58,in OpenGL_accelerate.errorchecker._ErrorChecker.glCheckerror
OpenGL.error.GLError: GLError(
    err = 1280,description = b'invalid enumerant',baSEOperation = glEnable,cArguments = (GL_COLOR_BUFFER_BIT,)
)
Traceback (most recent call last):
  File "/home/artem/PycharmProjects/polyEdit3D/polyEdit3D/Widgets/PlyViewport.py",line 69,in paintGL
    gl.glDrawElements(gl.GL_TRIANGLES,6,gl.GL_UNSIGNED_INT,ctypes.c_void_p(0))
  File "src/latebind.pyx",line 39,in OpenGL_accelerate.latebind.LateBind.__call__
  File "src/wrapper.pyx",line 318,in OpenGL_accelerate.wrapper.Wrapper.__call__
  File "src/wrapper.pyx",line 311,in OpenGL_accelerate.wrapper.Wrapper.__call__
  File "/home/artem/.local/lib/python3.7/site-packages/OpenGL/platform/baseplatform.py",in OpenGL_accelerate.errorchecker._ErrorChecker.glCheckerror
OpenGL.error.GLError: GLError(
    err = 1282,description = b'invalid operation',baSEOperation = glDrawElements,pyArgs = (
        GL_TRIANGLES,GL_UNSIGNED_INT,c_void_p(None),),cArgs = (
        GL_TRIANGLES,cArguments = (
        GL_TRIANGLES,)
)

您会看到gl.glEnable(gl.GL_COLOR_BUFFER_BIT)和其他简单内容中存在错误。如果不指定QSurfaceFormat,所有内容都会像超级按钮一样。

这是我的表面格式类:

class GLSurfaceFormat(QtGui.QSurfaceFormat):
    def __init__(self):
        super(GLSurfaceFormat,self).__init__()
        self.__initSurface()

    def __initSurface(self):
        self.setRenderableType(QtGui.QSurfaceFormat.OpenGL)
        self.setMinorVersion(3)
        self.setMajorVersion(4)
        self.setProfile(QtGui.QSurfaceFormat.CoreProfile)
        self.setColorSpace(QtGui.QSurfaceFormat.sRGBColorSpace)
        self.setSwapBehavior(QtGui.QSurfaceFormat.DoubleBuffer)

这是我的分配方式:

    QApplication.setAttribute(Qt.AA_UseDesktopOpenGL)
    QSurfaceFormat.setDefaultFormat(GLSurfaceFormat())

    app = QApplication(sys.argv)
    ...

您能告诉我,QSurfaceFormat使用中是否有任何错误,或者还有其他问题?

!UPDATE! 这是一个简单的示例,您可以在其中重现相同的行为:

from pyside2 import QtCore,QtGui,QtWidgets
from OpenGL import GL as gl
from OpenGL.GL.shaders import compileProgram,compileShader
import numpy as np
import ctypes
import sys
import glm

class PlyViewportWidget(QtWidgets.qopenglwidget):
    def __init__(self):
        super(PlyViewportWidget,self).__init__(parent=None)
        self.vao = None
        self.vbo = None
        self.ebo = None
        self.shaderProg = None
        self.isWireframe = False

    def initializeGL(self):
        gl.glEnable(gl.GL_COLOR_BUFFER_BIT)
        gl.glClearColor(0.4,0.4,1)

        with open("fragment.glsl",'r') as f:
            fragment = compileShader(f.read(),gl.GL_FRAGMENT_SHADER)
        with open("vertex.glsl","r") as f:
            vertex = compileShader(f.read(),gl.GL_VERTEX_SHADER)
        self.shaderProg = compileProgram(vertex,fragment)

        vertices = np.array(
            [
                0.5,0.5,0.0,-0.5,0.0
            ],dtype=ctypes.c_float
        )
        indices = np.array(
            [
                0,1,3,2,3
            ],dtype=ctypes.c_uint
        )

        self.vbo = gl.glGenBuffers(1)
        self.ebo = gl.glGenBuffers(1)

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER,self.vbo)
        gl.glBufferData(gl.GL_ARRAY_BUFFER,vertices.nbytes,vertices,gl.GL_STATIC_DRAW)

        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER,self.ebo)
        gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER,indices.nbytes,indices,gl.GL_STATIC_DRAW)

        gl.glEnabLevertexAttribArray(0)
        gl.glVertexAttribPointer(0,gl.GL_FLOAT,gl.GL_FALSE,3 * ctypes.sizeof(ctypes.c_float),ctypes.c_void_p(0))

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER,0)
        gl.glBindVertexArray(0)

        gl.gluseProgram(self.shaderProg)

    def paintGL(self):
        gl.glClearColor(0.4,1.0)
        gl.glClear(gl.GL_COLOR_BUFFER_BIT)

        trans = self.getTransformMatrix()
        #u_transform = gl.glGetUniformlocation(self.shaderProg,"u_transform")
        #gl.gluniformMatrix4fv(u_transform,u_transform)

        gl.glBindVertexArray(self.vao)
        gl.glDrawElements(gl.GL_TRIANGLES,ctypes.c_void_p(0))

    def resizeGL(self,w:int,h:int):
        gl.glViewport(0,w,h)

    def keyPressEvent(self,event:QtGui.QKeyEvent):
        self.makeCurrent()
        if event.key() == QtCore.Qt.Key_Z and not self.isWireframe:
            gl.glpolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_LINE)
            self.isWireframe = True
            self.update()
        elif event.key() == QtCore.Qt.Key_Z and self.isWireframe:
            gl.glpolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_FILL)
            self.isWireframe = False
            self.update()

        event.accept()

    def getTransformMatrix(self):
        return glm.rotate(glm.mat4(1.0),glm.radians(90.0),glm.vec3(1.0,0.0))


class GLSurfaceFormat(QtGui.QSurfaceFormat):
    def __init__(self):
        super(GLSurfaceFormat,self).__init__()
        self.__initSurface()

    def __initSurface(self):
        self.setRenderableType(QtGui.QSurfaceFormat.OpenGL)
        self.setMinorVersion(3)
        self.setMajorVersion(4)
        self.setProfile(QtGui.QSurfaceFormat.CoreProfile)
        self.setColorSpace(QtGui.QSurfaceFormat.sRGBColorSpace)
        self.setSwapBehavior(QtGui.QSurfaceFormat.DoubleBuffer)


if __name__ == '__main__':

    QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseDesktopOpenGL)
    # Uncomment to get this damn error!!!
    #QtGui.QSurfaceFormat.setDefaultFormat(GLSurfaceFormat())

    app = QtWidgets.QApplication(sys.argv)
    window = PlyViewportWidget()
    window.show()
    sys.exit(app.exec_())

vertex.glsl

#version 330 core

layout (location = 0) in vec3 aPos;

void main()
{
    gl_Position = vec4(aPos,1.0);
}

fragment.glsl

#version 330 core

out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0f,0.5f,0.2f,1.0f);
} 

解决方法

col_list不是glEnable的有效枚举常量,但它是glClear的适当参数。
glClearColor设置了清晰的颜色之后,调用GL_COLOR_BUFFER_BIT

glClear

您错过了创建命名为Vertex Array Object的操作:

class PlyViewportWidget(QtWidgets.QOpenGLWidget):
    # [...]

    def initializeGL(self):
        
        #gl.glEnable(gl.GL_COLOR_BUFFER_BIT) <---- DELETE
        
        gl.glClearColor(0.4,0.4,1)

        gl.glClear(gl.GL_COLOR_BUFFER_BIT) # <---- ADD