PySide6, OpenGL, Context Info Example but separate classes for objects
-
I am currently undertaking a project to learn OpenGL and have encountered some challenges. My objective is to create a window utilizing PySide6 as the window manager, within which I aim to render various graphical objects. To facilitate this, I am developing a class for spheres, enabling me to instantiate multiple sphere objects.
At present, I am working on a class for triangles to establish a foundational framework, with the intention of later extending it to spheres. However, I have encountered a segmentation fault and am uncertain of the source of the error or how to resolve it.
I would greatly appreciate any guidance or assistance you could provide regarding this matter.Here is my current code, which has been modified from the "Context Info Example":
import sys import numpy as np from PySide6.support import VoidPtr from PySide6.QtCore import QObject, QTimer, Qt, QRect from PySide6.QtWidgets import QApplication, QHBoxLayout, QWidget from PySide6.QtGui import QMatrix4x4, QOpenGLContext, QSurfaceFormat, QWindow from PySide6.QtOpenGL import QOpenGLBuffer, QOpenGLShader, QOpenGLShaderProgram, QOpenGLVertexArrayObject from OpenGL import GL class Triangle(QObject): vertices = np.array([0, 0.707, -0.5, -0.5, 0.5, -0.5], dtype=np.float32) colors = np.array([1, 0, 0, 0, 1, 0, 0, 0, 1], dtype=np.float32) def __init__(self): super().__init__() self.angle = 0 self.shader_program = QOpenGLShaderProgram(self) if not self.shader_program.addShaderFromSourceFile( QOpenGLShader.ShaderTypeBit.Vertex, "shaders/vertex.shader" ): raise Exception(f"Vertex shader could not be added: {self.shader_program.log()}") if not self.shader_program.addShaderFromSourceFile( QOpenGLShader.ShaderTypeBit.Fragment, "shaders/fragment.shader" ): raise Exception(f"Fragment shader could not be added: {self.shader_program.log()}") if not self.shader_program.link(): log = self.shader_program.log() raise Exception(f"Could not link shaders: {log}") self._pos_attr = self.shader_program.attributeLocation("posAttr") self._col_attr = self.shader_program.attributeLocation("colAttr") self._matrix_uniform = self.shader_program.uniformLocation("matrix") self.vbo = QOpenGLBuffer() self.vbo.create() self.vbo.bind() self._vertices_data = self.vertices.tobytes() self._colors_data = self.colors.tobytes() vertices_size = 4 * self.vertices.size colors_size = 4 * self.colors.size self.vbo.allocate(VoidPtr(self._vertices_data), vertices_size + colors_size) self.vbo.write(vertices_size, VoidPtr(self._colors_data), colors_size) self.vbo.release() def setup_vertex_attribs(self): self.vbo.bind() self.shader_program.setAttributeBuffer(self._pos_attr, GL.GL_FLOAT, 0, 2) self.shader_program.setAttributeBuffer( self._col_attr, GL.GL_FLOAT, 4 * self.vertices.size, 3 ) self.shader_program.enableAttributeArray(self._pos_attr) self.shader_program.enableAttributeArray(self._col_attr) self.vbo.release() def render(self, context_functions): self.shader_program.bind() matrix = QMatrix4x4() matrix.perspective(60, 4 / 3, 0.1, 100) matrix.translate(0, 0, -2) matrix.rotate(self.angle, 0, 1, 0) self.shader_program.setUniformValue(self._matrix_uniform, matrix) context_functions.glDrawArrays(GL.GL_TRIANGLES, 0, 3) class RenderWindow(QWindow): def __init__(self, fmt): super().__init__() self.setSurfaceType(QWindow.SurfaceType.OpenGLSurface) self.setFormat(fmt) self.context = QOpenGLContext(self) self.context.setFormat(self.requestedFormat()) if not self.context.create(): raise Exception("Unable to create GL context") self.timer = QTimer(self) self.timer.timeout.connect(self.render) self.context_functions = self.context.functions() self.vao = QOpenGLVertexArrayObject() def init_gl(self): if not self.context.makeCurrent(self): raise Exception("makeCurrent() failed") self.context_functions.glEnable(GL.GL_DEPTH_TEST) self.context_functions.glClearColor(0, 0, 0, 1) self.triangle = Triangle() with QOpenGLVertexArrayObject.Binder(self.vao): if self.vao.isCreated(): self.triangle.setup_vertex_attribs() def render(self): if not self.context.makeCurrent(self): raise Exception("context.makeCurrent() failed!") context_functions = self.context.functions() retina_scale = self.devicePixelRatio() context_functions.glViewport( 0, 0, self.width() * retina_scale, self.height() * retina_scale ) context_functions.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) if self.vao.isCreated(): self.vao.bind() else: self.triangle.setup_vertex_attribs() self.triangle.render(self.context_functions) self.vao.release() self.context.swapBuffers(self) self.context.doneCurrent() def exposeEvent(self, event): if self.isExposed(): self.init_gl() if not self.timer.isActive(): self.timer.start(10) else: if self.timer.isActive(): self.timer.stop() class MainWindow(QWidget): def __init__( self, area: QRect | None = None, title: str = "", parent: QWidget | None = None, flags: Qt.WindowType = Qt.WindowType.Window, ): super().__init__(parent, flags) h_box_layout = QHBoxLayout(self) h_box_layout.setContentsMargins(0, 0, 0, 0) self._render_window = RenderWindow(QSurfaceFormat()) container = QWidget.createWindowContainer(self._render_window) h_box_layout.addWidget(container) self.setWindowTitle(title) self.setGeometry(area) if __name__ == "__main__": application = QApplication(sys.argv) main_window = MainWindow(QRect(0, 0, 1920, 1080), title="test") main_window.showFullScreen() sys.exit(application.exec())
The vertex.shader file:
#version 330 core in vec4 posAttr; in vec4 colAttr; out vec4 col; uniform mat4 matrix; void main() { col = colAttr; gl_Position = matrix * posAttr; };
The fragment.shader file:
#version 330 core in vec4 col; out vec4 pix_color; void main() { pix_color = col; };
Thank you for your attention.
Best regards -
@kamran78nasirizad said in PySide6, OpenGL, Context Info Example but separate classes for objects:
am uncertain of the source of the error
Please run your app in debugger to see where that happens
-
Please run your app in debugger to see where that happens
Dear @jsulm,
Thank you for your suggestion. I did execute the application using the debugger; however, it encountered an issue at the first line of the init_gl function, displaying a message indicating "disconnected unexpectedly." Unfortunately, no further information was provided.