opengl 为什么PyQt6在通过glBufferSubData添加更新的数组后不能正确更新paintGL?

holgip5t  于 2022-12-23  发布在  其他
关注(0)|答案(1)|浏览(150)

当我按下左或右键旋转4点围绕原点,屏幕将无法正确更新,导致破碎的渲染。顶点数组是正确引入缓冲区,但我还没有找到有关为什么这不会正确渲染的相关信息。

以下是相关代码:

import Shader
from Math_3d import Vector3f
from OpenGL.GL import *
from PyQt6.QtOpenGLWidgets import QOpenGLWidget
from PyQt6.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):
        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)
            print("Left")
        elif e.key() == Qt.Key.Key_Right:
            self.v3f.Rotate(0.1)
            print("Right")
        elif e.key() == Qt.Key.Key_Escape or Qt.Key.Key_Q:
            exit()
        self.update()

其他模块:

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)
eiee3dmh

eiee3dmh1#

对于任何OpenGL指令,都需要当前有效的OpenGL ContextQOpenGLWidget创建OpenGL上下文,但上下文仅在initializeGLpaintGLresizeGL回调之前变为当前。
因此,您不能使用这些函数范围之外的OpenGL指令,这就是通过keyPressEvent调用glBufferSubData时调用失败的原因。

相关问题