1

I am trying to create PyQt5/ PyOpenGL code based on this example from the OpenGL Wiki.

The paintGL() call does not render anything to the screen. The StackOverflow questions with similar titles that I read describe different issues from what I am facing:

Note: I cannot post more than 2 links at this time due to rep limitations. I have added all related StackOverflow links as comments to this question.

I also went through the Common OpenGL Mistakes page and it does not seem to help (quite possibly I did not understand the page well).

The glGetErrors function reports GL.GL_NO_ERROR at all the below stages:

  1. When creating the VAO binding
  2. On creating the VBO bindings,
  3. After calling glBindVertexArray and glEnableVertexAttribArray

The glGetShaderiv and glGetProgramiv return GL.GL_TRUE, so there do not seem to be compiling and linking errors.

The GL context seems to have been correctly created. The self.context().isValid() check returns True.

I am using PyQt5.5, Python 3.4.0 with PyOpenGL 3.1. Also, GPU Caps Viewer reports that Open GL 4.5 is available on my machine.

Any help or pointers to get moving is much appreciated.

The code is below.

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_() )
  • Here are the links that I mentioned in my post: , and – Pralines And Cream Apr 14 '16 at 14:53
  • The accepted answer for the following question seems to be referenced across many links: http://stackoverflow.com/questions/14365484/how-to-draw-with-vertex-array-objects-and-gldrawelements-in-pyopengl/14365737#14365737. Reading through it. – Pralines And Cream Apr 14 '16 at 15:05

1 Answers1

0

The XYZ values used caused a triangle too small to be noticed to be rendered.

Scaling up the X, Y, Z values will result in the triangle being displayed. E.g.,

 _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 ]