QopenGLwidget not displaying content but Qglwidget does
-
I'm trying to get a QT GUI going with a OpenGL widget. Using the "old" Qglwidget the code below works as intended. However, using the UI tool it creates QopenGLwidgets and the window does not even open in the GUI (the code below however opens an empty window). Is there a way to fix this so that I can use QopenGLwidget instead?
import sys from PyQt5.QtWidgets import QOpenGLWidget, QApplication import moderngl import numpy as np import moderngl from PyQt5 import QtOpenGL, QtCore, QtGui from PyQt5.QtCore import Qt, pyqtSignal import numpy as np from pyrr import matrix44 cube_verts4 = np.array([ -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, ], dtype=np.float32) cube_ibo_idxs = np.array([ 0, 1, 2, 0, 2, 3, 3, 2, 6, 3, 6, 7, 7, 6, 5, 7, 5, 4, 7, 4, 0, 7, 0, 3, 4, 5, 1, 4, 1, 0, 1, 5, 6, 1, 6, 2 ], dtype=np.int32) class PyQtOpenGL(QtOpenGL.QGLWidget): #class PyQtOpenGL(QOpenGLWidget): vsync = True remove_event = pyqtSignal(str) def __init__(self, **kwargs): super().__init__(**kwargs) self.gl_version = (4, 3) fmt = QtOpenGL.QGLFormat() # need compute shader stuff fmt.setVersion(self.gl_version[0], self.gl_version[1]) fmt.setProfile(QtOpenGL.QGLFormat.CoreProfile) fmt.setDepthBufferSize(24) fmt.setDoubleBuffer(True) fmt.setSwapInterval(1 if self.vsync else 0) self.ctx = None self.timer = QtCore.QTimer(self) self.timer.timeout.connect(self.update) self.timer.start(16) self.last_mouse_pos = None self.rotation_x = 0 self.rotation_y = 0 def mousePressEvent(self, event: QtGui.QMouseEvent) -> None: self.last_mouse_pos = event.pos() def mouseMoveEvent(self, event: QtGui.QMouseEvent) -> None: dx = event.x() - self.last_mouse_pos.x() dy = event.y() - self.last_mouse_pos.y() if event.buttons() & Qt.LeftButton: self.rotation_x += dx * 0.01 self.rotation_y += dy * 0.01 self.last_mouse_pos = event.pos() @property def gl_version_code(self) -> int: return self.gl_version[0] * 100 + self.gl_version[1] * 10 @property def aspect_ratio(self): return self.width() / self.height() def initializeGL(self) -> None: self.ctx = moderngl.create_context( require=self.gl_version_code) self.prog = self.ctx.program( vertex_shader=''' #version 330 in vec4 vertex; in float power; out vec4 v_clip_pos; uniform mat4 mvp_matrix; void main() { v_clip_pos = mvp_matrix * vertex; gl_Position = v_clip_pos; } ''', fragment_shader=''' #version 330 in vec4 v_clip_pos; out vec4 color; void main() { vec3 ndc_pos = v_clip_pos.xyz / v_clip_pos.w; vec3 dx = dFdx( ndc_pos ); vec3 dy = dFdy( ndc_pos ); vec3 N = normalize(cross(dx, dy)); N *= sign(N.z); vec3 L = vec3(0.0, 0.0, 1.0); float NdotL = dot(N, L); vec3 diffuse_color = vec3(0.5) * NdotL; color = vec4( diffuse_color.rgb, 1.0 ); } ''', ) self.mvp_matrix = self.prog["mvp_matrix"] self.vbo = self.ctx.buffer( cube_verts4.astype('f4').tobytes()) self.ibo = self.ctx.buffer( cube_ibo_idxs.astype('i4').tobytes()) vao_content = [ # 4 floats are assigned to the 'in' variable named 'vertex' in the shader code (self.vbo, '4f', 'vertex'), ] self.vao = self.ctx.vertex_array(self.prog, vao_content, self.ibo) def paintGL(self): target_width = 4 target_height = 4 r_aspect_ratio = target_width / target_height if self.aspect_ratio > r_aspect_ratio: v_a = self.aspect_ratio / r_aspect_ratio projection = matrix44.create_orthogonal_projection_matrix( v_a * -target_width / 2.0, v_a * target_width / 2.0, -target_height / 2.0, target_height / 2.0, 0, 100, dtype=np.float32) else: a_v = r_aspect_ratio / self.aspect_ratio projection = matrix44.create_orthogonal_projection_matrix( -target_width / 2.0, target_width / 2.0, -a_v * target_height / 2.0, a_v * target_height / 2.0, 0, 100, dtype=np.float32) rotate = matrix44.create_from_y_rotation(-self.rotation_x) @ \ matrix44.create_from_x_rotation(-self.rotation_y) @ \ matrix44.create_from_translation(np.array([0, 0, -3], dtype=np.float32)) self.mvp_matrix.write((rotate @ projection).astype('f4').tobytes()) self.ctx.viewport = (0, 0, self.width(), self.height()) self.ctx.clear(0.0, 1.0, 1.0) self.ctx.enable(moderngl.DEPTH_TEST) self.vao.render() self.ctx.finish() def render(self): self.ctx.clear(0,0,0,0) self.vao.render() if __name__ == '__main__': app = QApplication(sys.argv) wnd = PyQtOpenGL() wnd.show() sys.exit(app.exec_())
-
Hi and welcome to devnet,
You should add:
- which version of PyQt5 you are using
- which OS you are running your script on
- how you installed PyQt
Can you test if you have the same issue with PySide2/6 ?