2016-01-19 48 views
0

我想通過QPainter在QGLWidget上繪製,如各種教程中所述。在我的paintGL()函數中,我有兩種情況。事實上,如果在OpenGL中沒有任何東西可以繪製,那麼我只用QPainter繪製兩行(這部分工作)。然而,當有些東西需要用OpenGL繪製時,我首先使用OpenGL函數,比如drawElements(),然後使用我的畫家來覆蓋這個小部件,但在這種情況下,我只能顯示我的OpenGL「對象」,兩行無形。在QGLWidget上繪製失敗

這裏是我的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數據。

更新N°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() 

The Geo metricShape類是:

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) 

回答

1

解決!我不得不添加:

glBindBuffer(GL_ARRAY_BUFFER, 0) 

與QPainter的表演,我的畫的東西之前解除綁定在我paintGL()函數的緩衝區。

我也擺脫了:

painter.fillRect(...) 

不隱瞞我的GL渲染。

因此可以注意到,沒有必要繪製一個QImage(儘管它有效)。

+0

很好。我看過Qt文檔。似乎已經在Qt-4.8中添加了必要的支持。 – datenwolf