paintGL 不在屏幕上绘制任何东西

paintGL does not draw anything on the screen

我正在尝试基于来自 OpenGL Wiki 的 example 创建 PyQt5/ PyOpenGL 代码。

paintGL() 调用不会在屏幕上呈现任何内容。我读过的具有相似标题的 Whosebug 问题描述了与我面临的问题不同的问题:

注意:由于代表限制,我目前无法 post 超过 2 个链接。我已将所有相关的 Whosebug 链接添加为对此问题的评论。

我也浏览了 Common OpenGL Mistakes 页面,但似乎没有帮助(很可能我没有很好地理解该页面)。

glGetErrors 函数在以下所有阶段报告 GL.GL_NO_ERROR

  1. 创建 VAO 绑定时
  2. 在创建 VBO 绑定时,
  3. 调用 glBindVertexArrayglEnableVertexAttribArray
  4. 之后

glGetShaderivglGetProgramivreturnGL.GL_TRUE,所以好像没有编译链接错误。

似乎已正确创建 GL 上下文。 self.context().isValid() 检查 returns True.

我正在使用 PyQt5.5,Python 3.4.0 和 PyOpenGL 3.1。此外,GPU Caps Viewer 报告说我的机器上可以使用 Open GL 4.5。

非常感谢任何有助于移动的帮助或指示。

代码如下。

from PyQt5 import QtGui, QtCore
import sys, array
from OpenGL import GL


# Create the Vertex Shader script and the Fragment Shader script here.
DeltaVertexShader = '''
#version 420 core

layout (location = 0) in vec4 vertexPositions;
layout (location = 1) in vec4 vertexColours; 

smooth out vec4 fragmentColours;

void main()
{
    gl_Position = vertexPositions;
    fragmentColours = vertexColours;
}
'''

DeltaFragmentShader = '''
#version 420 core

smooth in vec4 fragmentColours;
out vec4 finalColours;

void main()
{
    finalColours = fragmentColours;
}
'''

class PulleysWithWeights3D( QtGui.QOpenGLWindow ):


    def __init__(self):
        super().__init__()

        # These are the 4D coordinates of a triangle that needs to be drawn.
        _vertexPos = [ 0.075, 0.075, 0.075, 1.0, \
                      0.275, 0.275, 0.275, 1.0, \
                      0.550, 0.550, 0.550, 1.0 ]

        # These are the RGBA colours for each vertex.
        _vertexCols = [ 0.875, 0.525, 0.075, 0.500, \
                       0.875, 0.525, 0.075, 0.500, \
                       0.875, 0.525, 0.075, 0.500 ]

        self._deltaPositions = array.array( 'f', _vertexPos )
        self._deltaColours = array.array( 'f', _vertexCols )

        self._appSurfaceFormat = QtGui.QSurfaceFormat()

        self._appSurfaceFormat.setProfile( QtGui.QSurfaceFormat.CoreProfile )
        self._appSurfaceFormat.setMajorVersion( 4 )
        self._appSurfaceFormat.setMinorVersion( 2 )
        self._appSurfaceFormat.setRenderableType( QtGui.QSurfaceFormat.OpenGL )
        self._appSurfaceFormat.setSamples( 16 ) 
        self._appSurfaceFormat.setSwapBehavior( QtGui.QSurfaceFormat.DoubleBuffer )
        self.setSurfaceType( QtGui.QSurface.OpenGLSurface )

        self.setFormat( self._appSurfaceFormat )

        self.setIcon( QtGui.QIcon('OpenGL.png') )
        self.setTitle( 'Pulleys3D' )
        self.setMinimumSize( QtCore.QSize( 1280, 640 ) )
        self.show()


    def initializeGL(self):
        GL.glClearColor( 0.0, 0.0, 0.00, 1.0 ) # RGBA
        GL.glClearDepthf(1.0)
        GL.glClearStencil(0)
        GL.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT )

        # Initialize a VAO.
        self._vaoColouredDelta = GL.glGenVertexArrays(1) 
        GL.glBindVertexArray( self._vaoColouredDelta )

        # Initialize the VBOs.
        self._vboPositions = GL.glGenBuffers(1) # Create the position buffer.
        self._vboShades = GL.glGenBuffers(1)    # Create the colours buffer.        

        # Bind the positions VBO to the GL_ARRAY_BUFFER target.
        GL.glBindBuffer( GL.GL_ARRAY_BUFFER, self._vboPositions )

        # Initialize the positions buffer with the positions array data.
        GL.glBufferData( GL.GL_ARRAY_BUFFER, self._deltaPositions.buffer_info()[1] * self._deltaPositions.itemsize, \
                         self._deltaPositions.tobytes(), GL.GL_STATIC_DRAW )

        GL.glEnableVertexAttribArray(0)  # Enable attribute array 0, i.e., the positions array.

        GL.glVertexAttribPointer( 0, 4, GL.GL_FLOAT, GL.GL_FALSE, 0, None )

        GL.glBindBuffer( GL.GL_ARRAY_BUFFER, 0 )

        GL.glBindBuffer( GL.GL_ARRAY_BUFFER, self._vboShades )
        GL.glBufferData( GL.GL_ARRAY_BUFFER, self._deltaColours.buffer_info()[1] * self._deltaColours.itemsize, \
                         self._deltaColours.tobytes(), GL.GL_STATIC_DRAW )
        GL.glEnableVertexAttribArray(1)  # Enable attribute array 1, i.e., the colours array.
        GL.glVertexAttribPointer( 1, 4, GL.GL_FLOAT, GL.GL_FALSE, 0, None )

        GL.glBindBuffer( GL.GL_ARRAY_BUFFER, 0 )
        GL.glBindVertexArray(0) # Unbind the VAO.

        # Initialize the vertex shader and fragment shader program objects.
        _vertexShaderObj = GL.glCreateShader( GL.GL_VERTEX_SHADER )
        _fragmentShaderObj = GL.glCreateShader( GL.GL_FRAGMENT_SHADER )

        GL.glShaderSource( _vertexShaderObj, DeltaVertexShader )
        GL.glShaderSource( _fragmentShaderObj, DeltaFragmentShader )

        GL.glCompileShader( _vertexShaderObj )
        GL.glCompileShader( _fragmentShaderObj )


        if GL.glGetShaderiv( _vertexShaderObj, GL.GL_COMPILE_STATUS ) != GL.GL_TRUE:
            # There was a compilation error. Print it.
            print( 'Vertex Shader Compilation failed! Details follow.' )
            print( 'Compilation errors are: %s ' %( str( GL.glGetShaderInfoLog( _vertexShaderObj ) ) ) )

            # Delete this shader.
            GL.glDeleteShader( _vertexShaderObj )
            return # Don't continue execution.
        elif GL.glGetShaderiv( _fragmentShaderObj, GL.GL_COMPILE_STATUS ) != GL.GL_TRUE:
            print( 'Fragment Shader Compilation failed! Details follow.' )
            print( 'Compilation errors are: %s ' %( str( GL.glGetShaderInfoLog( _fragmentShaderObj ) ) ) )

            # Delete this shader.
            GL.glDeleteShader( _fragmentShaderObj )
            return # Don't continue execution.

        self._renderProgram = GL.glCreateProgram()
        GL.glAttachShader( self._renderProgram, _vertexShaderObj )
        GL.glAttachShader( self._renderProgram, _fragmentShaderObj )

        GL.glLinkProgram( self._renderProgram )


        if GL.glGetProgramiv( self._renderProgram, GL.GL_LINK_STATUS ) != GL.GL_TRUE:
            print( 'Shader linking failed! Details follow.' )
            print( 'Linking errors are: %s ' %( str( GL.glGetProgramInfoLog( self._renderProgram ) ) ) )

            GL.glDetachShader( self._renderProgram, _vertexShaderObj )
            GL.glDetachShader( self._renderProgram, _fragmentShaderObj )
            GL.glDeleteShader( _vertexShaderObj )
            GL.glDeleteShader( _fragmentShaderObj )

            # Delete the program.
            GL.glDeleteProgram( self._renderProgram )
            return # Don't continue execution.

        # Always detach shaders after a successful link.
        GL.glDetachShader( self._renderProgram, _vertexShaderObj )
        GL.glDetachShader( self._renderProgram, _fragmentShaderObj )


    def resizeGL(self, wd, ht ):
        # Resize the viewport by calling glViewport with the new height and width.
        GL.glViewport( 0, 0, wd, ht )


    def paintGL(self):
        GL.glClearColor( 0.0, 0.0, 0.00, 1.0 ) # RGBA
        GL.glClearDepthf(1.0)
        GL.glClearStencil(0)
        GL.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT )

        # Initialize the shader program to paint.
        GL.glUseProgram( self._renderProgram )

        GL.glBindVertexArray( self._vaoColouredDelta )

        # Draw the array.
        GL.glDrawArrays( GL.GL_TRIANGLES, 0, 3 )


        # Swap the front and back buffers so the newly drawn content is visible.
        self.context().swapBuffers( self )

        # Unbind the vertex array and the program.
        GL.glBindVertexArray(0)
        GL.glUseProgram(0)


if __name__ == '__main__':
    _pww3dApp = QtGui.QGuiApplication( sys.argv )
    _pww3d = PulleysWithWeights3D()
    sys.exit( _pww3dApp.exec_() )

使用的 XYZ 值导致三角形太小而无法被渲染。

放大 X、Y、Z 值将导致显示三角形。例如,

 _vertexPos = [ 0.775, 0.775, 0.775, 1.0, \
              0.275, 0.275, 0.275, 1.0, \
              0.550, 0.550, 0.550, 1.0 ]