I'm using QSurfaceFormat
to explicitly define OpenGL Core profile and set minor/major versions. The thing is, assignment of a custom surface format gives me the following error:
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", 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 = 1282,
description = b'invalid operation',
baseOperation = glDrawElements,
pyArgs = (
GL_TRIANGLES,
6,
GL_UNSIGNED_INT,
c_void_p(None),
),
cArgs = (
GL_TRIANGLES,
6,
GL_UNSIGNED_INT,
c_void_p(None),
),
cArguments = (
GL_TRIANGLES,
6,
GL_UNSIGNED_INT,
c_void_p(None),
)
)
As you can see there's an error in gl.glEnable(gl.GL_COLOR_BUFFER_BIT)
and other simple things. Without specifying QSurfaceFormat
everything works like a charm.
Here's my surface format class:
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)
Here's how I assign it:
QApplication.setAttribute(Qt.AA_UseDesktopOpenGL)
QSurfaceFormat.setDefaultFormat(GLSurfaceFormat())
app = QApplication(sys.argv)
...
Could you tell me, is there any mistake in QSurfaceFormat
usage or maybe there's something else?
!UPDATE! Here's a quick example where you can reproduce the same behavior:
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, 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.5, 0.0,
-0.5, -0.5, 0.0,
-0.5, 0.5, 0.0
], dtype=ctypes.c_float
)
indices = np.array(
[
0, 1, 3,
1, 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, 3, 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, 0.4, 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, 1, gl.GL_FALSE, u_transform)
gl.glBindVertexArray(self.vao)
gl.glDrawElements(gl.GL_TRIANGLES, 6, gl.GL_UNSIGNED_INT, ctypes.c_void_p(0))
def resizeGL(self, w:int, h:int):
gl.glViewport(0, 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, 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);
}
GL_COLOR_BUFFER_BIT
is not a valid enumeration constant for glEnable
, but it is a proper argument for glClear
.
Invoke glClear
, after the clear color is set by glClearColor
:
class PlyViewportWidget(QtWidgets.QOpenGLWidget):
# [...]
def initializeGL(self):
#gl.glEnable(gl.GL_COLOR_BUFFER_BIT) <---- DELETE
gl.glClearColor(0.4, 0.4, 0.4, 1)
gl.glClear(gl.GL_COLOR_BUFFER_BIT) # <---- ADD
You missed to create the named Vertex Array Object:
class PlyViewportWidget(QtWidgets.QOpenGLWidget):
# [...]
def initializeGL(self):
# [...]
self.vao = gl.glGenVertexArrays(1) # <---
gl.glBindVertexArray(self.vao) # <---
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, 3, 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)