Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Pyside6 does not render QOpenGLWidget window when using keypress and updating array using glBufferSubData
QtWS25 Last Chance

Pyside6 does not render QOpenGLWidget window when using keypress and updating array using glBufferSubData

Scheduled Pinned Locked Moved Unsolved Qt for Python
qt for python
3 Posts 2 Posters 544 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    Tribble
    wrote on last edited by Tribble
    #1

    I have been studying on how to draw OpenGL context, but I came across problem while updating the screen. Keypress invokes a rotation, but for some reason the window won't update the current render after using glBufferSubData. It should do this after invoking update() . Am I using keypressevent incorrectly or is the problem somewhere else. Python version 3.10

    Main.py

    from GLWidget import GLWidget
    from PySide6.QtWidgets import QApplication, QMainWindow
    
    class Window(QMainWindow):
        def __init__(self):
            super().__init__()
            # set the title
            self.setWindowTitle("OpenGL Interface")
            # setting  the geometry of window
            self.setGeometry(0, 0, 1024, 768)
            self.qlw = GLWidget()
            self.setCentralWidget(self.qlw)
    
    if __name__ == '__main__':
        app = QApplication([])
        window = Window()
        window.show()
        app.exec()
    

    GLWidget.py

    import Shader
    from Math_3d import Vector3f
    from OpenGL.GL import *
    from PySide6.QtOpenGLWidgets import QOpenGLWidget
    from PySide6.QtCore import Qt
    
    
    class GLWidget(QOpenGLWidget):
        def __init__(self):
            super().__init__()
            # Vertex Buffer Object
            # Create point vertex data
            self.v3f = Vector3f([[0.5, 0.5, 0.0],
                                [-0.5, -0.5, 0.0],
                                [0.5, -0.5, 0.0],
                                [-0.5, 0.5, 0.0]])
            self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
    
        def initializeGL(self):
    
            program = glCreateProgram()
            buffer = glGenBuffers(1)
            # Request program and shader slots from the GPU
            vertex = glCreateShader(GL_VERTEX_SHADER)
            fragment = glCreateShader(GL_FRAGMENT_SHADER)
    
            # Set shader sources
            glShaderSource(vertex, Shader.vertex_code)
            glShaderSource(fragment, Shader.fragment_code)
            # Compile shaders and check that they have compiled
            glCompileShader(vertex)
            glCompileShader(fragment)
            if not glGetShaderiv(vertex, GL_COMPILE_STATUS):
                report_shader = glGetShaderInfoLog(vertex)
                print(report_shader)
                raise RuntimeError("Vertex shader compilation error")
    
            if not glGetShaderiv(fragment, GL_COMPILE_STATUS):
                report_frag = glGetShaderInfoLog(fragment)
                print(report_frag)
                raise RuntimeError("Fragment shader compilation error")
    
            # Link shaders to program
            glAttachShader(program, vertex)
            glAttachShader(program, fragment)
            glLinkProgram(program)
    
            if not glGetProgramiv(program, GL_LINK_STATUS):
                print(glGetProgramInfoLog(program))
                raise RuntimeError('Linking error')
            # Get rid of shaders
            glDetachShader(program, vertex)
            glDetachShader(program, fragment)
            # Make default program to run
            glUseProgram(program)
    
            # Make this buffer the default one
            glBindBuffer(GL_ARRAY_BUFFER, buffer)
            # Vertex Array Buffer
            vao = glGenVertexArrays(1)
            glBindVertexArray(vao)
            strides = int(self.v3f.buffdata.nbytes/self.v3f.buffdata.itemsize)
            loc = glGetAttribLocation(program, 'position')
            glEnableVertexAttribArray(loc)
            glVertexAttribPointer(loc, 3, GL_FLOAT, False, strides, None)
            glBufferData(GL_ARRAY_BUFFER, self.v3f.buffdata.nbytes, self.v3f.buffdata, GL_DYNAMIC_DRAW)
    
        def paintGL(self):
            print(glGetError())
            glClear(GL_COLOR_BUFFER_BIT)
            glPointSize(20)
            glDrawArrays(GL_POINTS, 0, self.v3f.buffdata.itemsize)
    
        def keyPressEvent(self, e):
            if e.key() == Qt.Key.Key_Left:
                self.v3f.Rotate(-0.1)
            elif e.key() == Qt.Key.Key_Right:
                self.v3f.Rotate(0.1)
            elif e.key() == Qt.Key.Key_Escape or Qt.Key.Key_Q:
                exit()
            self.update()
    

    Shader.py

    vertex_code = """
        attribute vec3 position;
        void main()
        {
            gl_Position = vec4(position, 1.0);
        }   
        """
    
    fragment_code = """
        void main() 
        { 
            gl_FragColor = vec4(0.5, 0.5, 0.5, 1.0); 
        }
        """
    

    Math_3d.py

    from OpenGL.GL import *
    import numpy as np
    np.set_printoptions(precision=3, suppress=True)
    
    
    class Vector3f:
        def __init__(self, ndarray):
            self.data = np.array([ndarray], dtype=np.float32)
            # Convert n-dimension arrays to one long array
            self.buffdata = self.data.ravel()
            self.orig = self.data
            self.__rval = 0.0
            self.__sval = 0.0
    
        def Rotate(self, val):  # Rotation Matrix
            self.__rval += val  # Create a memory value and add to that value
            m1 = np.asmatrix(self.data)  # Convert n-dimension array to matrix
            rot2 = np.matrix([[np.cos(self.__rval), np.sin(-self.__rval), 0.0],  # Create rotation matrix
                             [np.sin(self.__rval), np.cos(self.__rval), 0.0],
                             [0.0, 0.0, 0.0]], dtype=np.float32)
            rotator = m1 * rot2  # Matrix multiplication
            self.buffdata = rotator.ravel()  # Convert result to array to be used on GPU buffer
            glBufferSubData(GL_ARRAY_BUFFER, 0, self.buffdata.data.nbytes, self.buffdata.data)
            print(glGetError())
    
    
    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      If memory serves well, you should ensure that the context is current when calling OpenGL methods outside the various xxxGL methods of QOpenGLWidget.

      One possible alternative is to use a dirty flag and you call glBufferSubData the next time paintGL is called.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      T 1 Reply Last reply
      0
      • SGaistS SGaist

        Hi and welcome to devnet,

        If memory serves well, you should ensure that the context is current when calling OpenGL methods outside the various xxxGL methods of QOpenGLWidget.

        One possible alternative is to use a dirty flag and you call glBufferSubData the next time paintGL is called.

        T Offline
        T Offline
        Tribble
        wrote on last edited by
        #3

        @SGaist Thank you. You are actually quite correct on this one. It seems to be missing the context initialisation and swapbuffer command should work after that.

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved