当我按下左或右键旋转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)
1条答案
按热度按时间eiee3dmh1#
对于任何OpenGL指令,都需要当前有效的OpenGL Context。
QOpenGLWidget
创建OpenGL上下文,但上下文仅在initializeGL
、paintGL
或resizeGL
回调之前变为当前。因此,您不能使用这些函数范围之外的OpenGL指令,这就是通过
keyPressEvent
调用glBufferSubData
时调用失败的原因。