我试图通过QPainter绘制QGLWidget,如各种教程中所述。在我的paintGL()函数中,我有两个案例。实际上,如果在OpenGL中没有任何东西可以绘制,那么我只使用QPainter绘制2条线(这部分确实有用)。但是,当有一些东西可以用OpenGL绘制时,我首先使用一个OpenGL函数,比如drawElements()然后我用我的画家来重写小部件,但在这种情况下我只能显示我的OpenGL“对象”,这两行看不见。
这是我的paintGL方法的代码:
def paintGL(self):
glClearColor(0, 0, 0, 1)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
if np.array(self.objects).size:
print('there are %i objects'%(len(self.objects)))
#
# active shader program
glUseProgram(self.shaderProgram)
for i, obj in enumerate(self.objects):
loc_pos = glGetAttribLocation(self.shaderProgram, "position")
glEnableVertexAttribArray(loc_pos)
glBindBuffer(GL_ARRAY_BUFFER, obj.VBO[0])
glVertexAttribPointer(loc_pos, 2, GL_FLOAT, False, 0, ctypes.c_void_p(0))
loc_col = glGetAttribLocation(self.shaderProgram, "color")
glEnableVertexAttribArray(loc_col)
glBindBuffer(GL_ARRAY_BUFFER, obj.VBO[1])
glVertexAttribPointer(loc_col, 4, GL_FLOAT, False, 0, ctypes.c_void_p(0))
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, obj.VBO[2])
glDrawElements(GL_TRIANGLES, obj.indices.size, GL_UNSIGNED_INT, ctypes.c_void_p(0))
glUseProgram(0)
painter = QtGui.QPainter()
painter.begin(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
print(painter.isActive())
pen = QtGui.QPen(QtGui.QColor(255,0,0), 10)
x = 100
y= 100
# clean previous drawings
painter.fillRect(self.rect(),QtGui.QBrush(QtGui.QColor(0,0,0)) )
painter.setPen(pen)
currentFont = painter.font()
currentFont.setPointSize(currentFont.pointSize()*4)
painter.setFont(currentFont)
painter.drawLine(x, 0, x, self.height())
painter.drawLine(0, y, self.width(), y)
painter.end()
else:
print('No data in objects ==> no drawing')
painter = QtGui.QPainter()
painter.begin(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
print(painter.isActive())
pen = QtGui.QPen(QtGui.QColor(255,0,0), 10)
x = 100
y= 100
# clean previous drawings
painter.fillRect(self.rect(),QtGui.QBrush(QtGui.QColor(0,0,0)) )
painter.setPen(pen)
currentFont = painter.font()
currentFont.setPointSize(currentFont.pointSize()*4)
painter.setFont(currentFont)
painter.drawLine(x, 0, x, self.height())
painter.drawLine(0, y, self.width(), y)
painter.end()
更新
更确切地说,当我启动我的应用程序时,一切都很好。当我更新我的相机矩阵(通过鼠标事件)时,它的行为符合预期,因为我仍然可以看到QPainter绘图。但是,当我点击我的应用程序中的一个按钮(这样一个按钮触发一个方法,包括通过glBindBuffer()和glBufferData填充缓冲区),而我的paintGL()方法被调用时,不会出现QPainter的绘图,只有OpenGL数据。
更新第2期:
另外,我提供了一些代码:
我的GLWidget类:
import ctypes
import numpy
import numpy as np
from OpenGL.GL import *
from OpenGL.GL import shaders
import FN_functions as fn
from PyQt4 import QtGui, QtCore, QtOpenGL
VERTEX_SHADER = """
#version 440 core
uniform float scale;
uniform mat4 Model;
uniform mat4 View;
uniform mat4 Projection;
in vec2 position;
in vec4 color;
out vec4 v_color;
void main()
{
gl_Position = Projection*View*Model*vec4(scale*position, 0.0, 1.0);
v_color = color;
}
"""
FRAGMENT_SHADER = """
#version 440 core
in vec4 v_color;
void main()
{
gl_FragColor = v_color;
} """
class MyWidget(QtOpenGL.QGLWidget):
def __init__(self):
super(MyWidget, self).__init__()
self.objects = []
self.camTarget = np.array([0,0,0])
self.camEye = np.array([0,0,10])
self.camUp = np.array([0, 1, 0])
# by default, GLwidget does not accept any focus as there is no text input
self.setFocusPolicy(QtCore.Qt.StrongFocus)
# avoid blinking when repainting
self.setAutoFillBackground(False)
self.setAttribute(QtCore.Qt.WA_OpaquePaintEvent)
self.setAttribute(QtCore.Qt.WA_NoSystemBackground)
self.setMouseTracking(True)
def initializeGL(self):
#glViewport(0, 0, self.width(), self.height())
print('initializeGL')
# compile shaders and program
vertexShader = shaders.compileShader(VERTEX_SHADER, GL_VERTEX_SHADER)
fragmentShader = shaders.compileShader(FRAGMENT_SHADER, GL_FRAGMENT_SHADER)
self.shaderProgram = shaders.compileProgram(vertexShader, fragmentShader)
print(self.shaderProgram)
# Init uniforms
glUseProgram(self.shaderProgram)
# Scale
loc = glGetUniformLocation(self.shaderProgram, 'scale')
glUniform1f(loc, 1)
# Model matrix
matModel = fn.translate((2*np.random.rand(1), 2*np.random.rand(1), 2*np.random.rand(1)))
loc = glGetUniformLocation(self.shaderProgram, 'Model')
glUniformMatrix4fv(loc, 1, True, np.asfortranarray(matModel))
# View matrix
matView = fn.lookat(np.array([0,0,0]), np.array([0,0,10]), np.array([0,1,0]))
loc = glGetUniformLocation(self.shaderProgram, 'View')
glUniformMatrix4fv(loc, 1, True, np.asfortranarray(matView))
# Projection matrix
matProj = fn.perspective(fovy=45, aspect=1.0, n=1.0, f=100000.0)
loc = glGetUniformLocation(self.shaderProgram, 'Projection')
glUniformMatrix4fv(loc, 1, True, np.asfortranarray(matProj))
glUseProgram(0)
def wheelEvent(self, e):
zStep = -e.delta()/10
self.camEye[2] += zStep
self.updateCamera()
def keyPressEvent(self, e):
xStep, yStep = (1, 1)
if e.key() == QtCore.Qt.Key_Z:
self.camEye[1] += yStep
self.camTarget[1] += yStep
elif e.key() == QtCore.Qt.Key_S:
self.camEye[1] -= yStep
self.camTarget[1] -= yStep
elif e.key() == QtCore.Qt.Key_Q:
self.camEye[0] += xStep
self.camTarget[0] += xStep
elif e.key() == QtCore.Qt.Key_D:
self.camEye[0] -= xStep
self.camTarget[0] -= xStep
self.updateCamera()
def updateCamera(self):
matView = fn.lookat(self.camEye, self.camTarget, self.camUp)
glUseProgram(self.shaderProgram)
loc = glGetUniformLocation(self.shaderProgram, 'View')
glUniformMatrix4fv(loc, 1, True, np.asfortranarray(matView))
self.updateGL()
# def mouseMoveEvent(self, e):
#
# print(self.context())
#
# self.makeCurrent()
# self.swapBuffers()
# print('mouseMoveEvent')
# print(e.pos())
# x, y = e.pos().x(), e.pos().y()
#
# pen = QtGui.QPen(QtGui.QColor(255,0,0), 10)
#
#
# self.painter.begin(self)
#
#
# # clean previous drawings
# self.painter.fillRect(self.rect(),QtGui.QBrush(QtGui.QColor(0,0,0)) )
# self.painter.setPen(pen)
#
# currentFont = self.painter.font()
# currentFont.setPointSize(currentFont.pointSize()*4)
# self.painter.setFont(currentFont)
# #painter.fillRect(e.rect(), QtGui.QBrush(QtGui.QColor(64,32,64)))
# self.painter.drawLine(x, 0, x, self.height())
# self.painter.drawLine(0, y, self.width(), y)
#
# self.painter.end()
# def paintEvent(self, e):
# print('paintEvent')
#
#
# print(self.context())
#
# self.makeCurrent()
# self.swapBuffers()
# print(e.pos())
# x, y = e.pos().x(), e.pos().y()
#
# pen = QtGui.QPen(QtGui.QColor(255,0,0), 10)
#
#
# self.painter.begin(self)
#
#
# # clean previous drawings
# self.painter.fillRect(self.rect(),QtGui.QBrush(QtGui.QColor(0,0,0)) )
# self.painter.setPen(pen)
#
# currentFont = self.painter.font()
# currentFont.setPointSize(currentFont.pointSize()*4)
# self.painter.setFont(currentFont)
# #painter.fillRect(e.rect(), QtGui.QBrush(QtGui.QColor(64,32,64)))
# self.painter.drawLine(x, 0, x, self.height())
# self.painter.drawLine(0, y, self.width(), y)
#
# self.painter.end()
def paintGL(self):
print('paintGL CALL')
glClearColor(0, 0, 0, 1)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_COLOR_ARRAY)
if np.array(self.objects).size:
print('there are %i objects'%(len(self.objects)))
#
# active shader program
glUseProgram(self.shaderProgram)
for i, obj in enumerate(self.objects):
print(i)
loc_pos = glGetAttribLocation(self.shaderProgram, "position")
glEnableVertexAttribArray(loc_pos)
glBindBuffer(GL_ARRAY_BUFFER, obj.VBO[0])
glVertexAttribPointer(loc_pos, 2, GL_FLOAT, False, 0, ctypes.c_void_p(0))
loc_col = glGetAttribLocation(self.shaderProgram, "color")
glEnableVertexAttribArray(loc_col)
glBindBuffer(GL_ARRAY_BUFFER, obj.VBO[1])
glVertexAttribPointer(loc_col, 4, GL_FLOAT, False, 0, ctypes.c_void_p(0))
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, obj.VBO[2])
glDrawElements(GL_TRIANGLES, obj.indices.size, GL_UNSIGNED_INT, ctypes.c_void_p(0))
glUseProgram(0)
painter = QtGui.QPainter()
painter.begin(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
print(painter.isActive())
pen = QtGui.QPen(QtGui.QColor(255,0,0), 10)
x = 100
y= 100
# clean previous drawings
painter.fillRect(self.rect(),QtGui.QBrush(QtGui.QColor(0,0,0)) )
painter.setPen(pen)
currentFont = painter.font()
currentFont.setPointSize(currentFont.pointSize()*4)
painter.setFont(currentFont)
painter.drawLine(x, 0, x, self.height())
painter.drawLine(0, y, self.width(), y)
painter.end()
else:
print('No data in objects ==> no drawing')
painter = QtGui.QPainter()
painter.begin(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
print(painter.isActive())
pen = QtGui.QPen(QtGui.QColor(255,0,0), 10)
x = 100
y= 100
# clean previous drawings
painter.fillRect(self.rect(),QtGui.QBrush(QtGui.QColor(0,0,0)) )
painter.setPen(pen)
currentFont = painter.font()
currentFont.setPointSize(currentFont.pointSize()*4)
painter.setFont(currentFont)
painter.drawLine(x, 0, x, self.height())
painter.drawLine(0, y, self.width(), y)
painter.end()
然后,每次按下GUI上的按钮,它都会触发此功能:
def addAnObject(self):
obj = geometricShape.GeometricShape()
obj.sendToBuffer()
self.widgetGL.objects.append(obj)
self.widgetGL.updateGL()
GeometricShape类是:
import numpy as np
from OpenGL.GL import *
from scipy.spatial import Delaunay
class GeometricShape():
def __init__(self):
#self.vertices = np.random.rand(4,2)
self.vertices = np.array([[1,1], [-1,1], [1,-1], [-1,-1]])
tmp = np.random.rand(self.vertices.shape[0],3)
tmp2 = np.ones(shape=(self.vertices.shape[0],1))
tmp = np.hstack((tmp, tmp2 ))
self.colors = tmp
self.indices = Delaunay(self.vertices).simplices
def sendToBuffer(self):
# create VBO
print('sendBuffer')
glUseProgram(3)
self.VBO = glGenBuffers(3)
# fill it
glBindBuffer(GL_ARRAY_BUFFER, self.VBO[0])
glBufferData(GL_ARRAY_BUFFER, self.vertices.nbytes, np.ascontiguousarray(self.vertices.flatten(), dtype=np.float32), GL_STATIC_DRAW)
#
glBindBuffer(GL_ARRAY_BUFFER, self.VBO[1])
glBufferData(GL_ARRAY_BUFFER, self.colors.nbytes, np.ascontiguousarray( self.colors.flatten(), dtype=np.float32), GL_STATIC_DRAW)
#
# # # INDEX ARRAY
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.VBO[2])
glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.indices.nbytes, np.ascontiguousarray(self.indices.flatten(), dtype=np.uint32), GL_STATIC_DRAW)
glUseProgram(0)
答案 0 :(得分:1)
解决!我不得不补充道:
glBindBuffer(GL_ARRAY_BUFFER, 0)
在使用QPainter执行绘图之前解压缩paintGL()函数中的缓冲区。
我也摆脱了:
painter.fillRect(...)
不要隐藏我的GL渲染。
因此可以注意到,没有必要绘制QImage(尽管它有效)。