簡體   English   中英

當我編譯着色器時,PyOpengGL 引發錯誤

[英]PyOpengGL raises error when I compile shaders

我正在瀏覽大量 OpenGL 着色器教程以及混合和匹配內容,試圖實現自定義着色器。 我有以下 Python 代碼和回溯:

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QOpenGLWidget
from PyQt5.QtCore import Qt
from OpenGL.GL import (
                       glLoadIdentity, glTranslatef, glRotatef,
                       glClear, glBegin, glEnd,
                       glColor3fv, glVertex3fv,
                       GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT,
                       GL_QUADS, GL_LINES,
                       shaders, GL_VERTEX_SHADER, GL_FRAGMENT_SHADER
                      )
from OpenGL.GLU import gluPerspective

class mainWindow(QMainWindow):    #Main class.
    def keyPressEvent(self, event):    #This is the keypress detector.
        try:
            key = event.key()
        except:
            key = -1    
        #print(key)
        if key == 16777216:
            exit()

    vertices = [
                (-1, 1, 0),
                (1, 1, 0),
                (1, -1, 0),
                (-1, -1, 0)
               ]
    wires = [
             (0, 1),
             (1, 2),
             (2, 3),
             (0, 3)
            ]
    facets = [
             (0, 1, 2, 3)
            ]
    zoomLevel = -5
    rotateDegreeH = 0
    rotateDegreeV = -45

    vertShaderCode = """#version 120    
void main() {
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}"""
    fragShaderCode = """#version 120
void main() {
    gl_FragColor = vec4( 0, 1, 0, 1 );
}"""

    def __init__(self):
        super(mainWindow, self).__init__()
        self.sizeX = 700    #Variables used for the setting of the size of everything
        self.sizeY = 600
        self.setGeometry(0, 0, self.sizeX + 50, self.sizeY)    #Set the window size

        #make shaders
        VERTEX_SHADER = shaders.compileShader(self.vertShaderCode, GL_VERTEX_SHADER)

        FRAGMENT_SHADER = shaders.compileShader(self.fragShaderCode, GL_FRAGMENT_SHADER)

        self.shader = shaders.compileProgram(VERTEX_SHADER,FRAGMENT_SHADER)

        self.openGLWidget = QOpenGLWidget(self)    #Create the GLWidget
        self.openGLWidget.setGeometry(0, 0, self.sizeX, self.sizeY)
        self.openGLWidget.initializeGL()
        self.openGLWidget.resizeGL(self.sizeX, self.sizeY)    #Resize GL's knowledge of the window to match the physical size?
        self.openGLWidget.paintGL = self.paintGL    #override the default function with my own?

    def nav(self, hVal = 0, vVal = 0, zVal = 0):
        self.zoomLevel += zVal
        self.rotateDegreeH += hVal
        self.rotateDegreeV += vVal
        self.openGLWidget.update()

    def paintGL(self):
        #This function uses shape objects, such as cube() or mesh(). Shape objects require the following:
        #a list named 'vertices' - This list is a list of points, from which edges and faces are drawn.
        #a list named 'wires'    - This list is a list of tuples which refer to vertices, dictating where to draw wires.
        #a list named 'facets'   - This list is a list of tuples which refer to vertices, ditating where to draw facets.
        #a bool named 'render'   - This bool is used to dictate whether or not to draw the shape.
        #a bool named 'drawWires' - This bool is used to dictate whether wires should be drawn.
        #a bool named 'drawFaces' - This bool is used to dictate whether facets should be drawn.

        shaders.glUseProgram(self.shader)
        glLoadIdentity()
        gluPerspective(45, self.sizeX / self.sizeY, 0.1, 110.0)    #set perspective?
        glTranslatef(0, 0, self.zoomLevel)    #I used -10 instead of -2 in the PyGame version.
        glRotatef(self.rotateDegreeV, 1, 0, 0)    #I used 2 instead of 1 in the PyGame version.
        glRotatef(self.rotateDegreeH, 0, 0, 1)
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

        glBegin(GL_LINES)

        for w in self.wires:
            for v in w:
                glVertex3fv(self.vertices[v])
        glEnd()

        glBegin(GL_QUADS)

        for f in self.facets:
            for v in f:
                glVertex3fv(self.vertices[v])
        glEnd()

app = QApplication([])
window = mainWindow()
window.show()
sys.exit(app.exec_())
C:\Users\ccronk22\Documents\Python\glShaders>pygl002.py
Traceback (most recent call last):
  File "C:\Users\ccronk22\AppData\Local\Programs\Python\Python38\lib\site-packages\OpenGL\latebind.py", line 43, in __call__
    return self._finalCall( *args, **named )
TypeError: 'NoneType' object is not callable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\ccronk22\Documents\Python\glShaders\pyGL002.py", line 109, in <module>
    window = mainWindow()
  File "C:\Users\ccronk22\Documents\Python\glShaders\pyGL002.py", line 59, in __init__
    VERTEX_SHADER = shaders.compileShader(self.vertShaderCode, GL_VERTEX_SHADER)
  File "C:\Users\ccronk22\AppData\Local\Programs\Python\Python38\lib\site-packages\OpenGL\GL\shaders.py", line 228, in compileShader
    shader = glCreateShader(shaderType)
  File "C:\Users\ccronk22\AppData\Local\Programs\Python\Python38\lib\site-packages\OpenGL\latebind.py", line 46, in __call__
    self._finalCall = self.finalise()
  File "C:\Users\ccronk22\AppData\Local\Programs\Python\Python38\lib\site-packages\OpenGL\extensions.py", line 242, in finalise
    raise error.NullFunctionError(
OpenGL.error.NullFunctionError: Attempt to call an undefined alternate function (glCreateShader, glCreateShaderObjectARB), check for bool(glCreateShader) before calling

C:\Users\ccronk22\Documents\Python\glShaders>

如果您將 compileShader、compileProgram 和 useProgram 行注釋掉,則上述代碼運行良好。 從上面的角度看,它會產生一個白色方塊:

    def __init__(self):
        super(mainWindow, self).__init__()
        self.sizeX = 700    #Variables used for the setting of the size of everything
        self.sizeY = 600
        self.setGeometry(0, 0, self.sizeX + 50, self.sizeY)    #Set the window size

        #make shaders
        #VERTEX_SHADER = shaders.compileShader(self.vertShaderCode, GL_VERTEX_SHADER)

        #FRAGMENT_SHADER = shaders.compileShader(self.fragShaderCode, GL_FRAGMENT_SHADER)

        #self.shader = shaders.compileProgram(VERTEX_SHADER,FRAGMENT_SHADER)
[…]
    def paintGL(self):
        #This function uses shape objects, such as cube() or mesh(). Shape objects require the following:
        #a list named 'vertices' - This list is a list of points, from which edges and faces are drawn.
        #a list named 'wires'    - This list is a list of tuples which refer to vertices, dictating where to draw wires.
        #a list named 'facets'   - This list is a list of tuples which refer to vertices, ditating where to draw facets.
        #a bool named 'render'   - This bool is used to dictate whether or not to draw the shape.
        #a bool named 'drawWires' - This bool is used to dictate whether wires should be drawn.
        #a bool named 'drawFaces' - This bool is used to dictate whether facets should be drawn.

        #shaders.glUseProgram(self.shader)

一些附加信息:

我試圖讓http://pyopengl.sourceforge.net/context/tutorials/shader_1.html 中的代碼在 PyQt5 上下文中工作,只有 OpenGL 和 PyQt5 API。 本教程是用 Python2 編寫的。 我正在使用 Python3。

那么,我的着色器編譯有什么問題? 它是在 Python 還是 GLSL 中?

要編譯和鏈接着色器,您需要一個有效的當前OpenGL 上下文 請注意,當調用任何 OpenGL 指令時,OpenGL 上下文必須是最新的。 QOpenGLWidget提供虛擬方法

def initializeGL () def paintGL () def resizeGL (w, h)

OpenGL 上下文處於活動狀態的位置。 此方法是回調並由 Qts 事件處理調用。 不要在你的代碼中調用它們。

initializeGL回調中創建着色器:

class mainWindow(QMainWindow):

    def __init__(self):
        super(mainWindow, self).__init__()
        self.sizeX = 700    #Variables used for the setting of the size of everything
        self.sizeY = 600
        self.setGeometry(0, 0, self.sizeX + 50, self.sizeY)    #Set the window size

        self.openGLWidget = QOpenGLWidget(self)    #Create the GLWidget
        self.openGLWidget.setGeometry(0, 0, self.sizeX, self.sizeY)
        self.openGLWidget.resizeGL(self.sizeX, self.sizeY)    #Resize GL's knowledge of the window to match the physical size?
        self.openGLWidget.initializeGL = self.initializeGL 
        self.openGLWidget.paintGL = self.paintGL    #override the default function with my own?
        self.shader = None

    def nav(self, hVal = 0, vVal = 0, zVal = 0):
        self.zoomLevel += zVal
        self.rotateDegreeH += hVal
        self.rotateDegreeV += vVal
        self.openGLWidget.update()

    def initializeGL(self):
        #make shaders
        VERTEX_SHADER = shaders.compileShader(self.vertShaderCode, GL_VERTEX_SHADER)
        FRAGMENT_SHADER = shaders.compileShader(self.fragShaderCode, GL_FRAGMENT_SHADER)
        self.shader = shaders.compileProgram(VERTEX_SHADER,FRAGMENT_SHADER)

    def paintGL(self):

        glUseProgram(self.shader)
        # [...]

(您的代碼中缺少glUseProgram的導入)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM