Esempio n. 1
0
    def setupGL(self):

        self.program = QOpenGLShaderProgram(self.context())
        info("PROGRAM", self.program)

        # addShaderFromSourceCode() only returns a bool telling whether everything went well

        if self.program.addShaderFromSourceCode(QOpenGLShader.Vertex,
                                                self.vertexShaderSource):
            info("VERTEX SHADER",
                 "Managed to load and parse the vertex shader")

        if self.program.addShaderFromSourceCode(QOpenGLShader.Fragment,
                                                self.fragmentShaderSource):
            info("FRAGMENT SHADER",
                 "Managed to load and parse the fragment shader")

        # Compile and bind the shader program to the current context
        self.program.link()
        self.program.bind()

        # Tell GL that whenever we run glClear, this is the color that
        # should be used. We only need to do this once.
        self.gl.glClearColor(0.1, 0.1, 0.1, 1.0)

        self.dumpGLLogMessages("setupGL()")
Esempio n. 2
0
    def setupGL(self):

        self.program = QOpenGLShaderProgram(self.context())
        info("PROGRAM", self.program)

        # addShaderFromSourceCode() only returns a bool telling whether everything went well

        if self.program.addShaderFromSourceCode(QOpenGLShader.Vertex,
                                                self.vertexShaderSource):
            info("VERTEX SHADER",
                 "Managed to load and parse the vertex shader")

        if self.program.addShaderFromSourceCode(QOpenGLShader.Fragment,
                                                self.fragmentShaderSource):
            info("FRAGMENT SHADER",
                 "Managed to load and parse the fragment shader")

        # Compile and bind the shader program to the current context
        self.program.link()
        self.program.bind()

        # Bind the shader attribute to a python variable
        self.somePosition = self.gl.glGetAttribLocation(
            self.program.programId(), "somePosition")

        # Use array rather than list in order to get control over actual data size
        self.vertices = array.array(
            'f',
            [-0.5, -0.5, 0.0, 0.5, 0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.0, 0.0])

        # Buffer info returns a tuple where the second part is number of elements in the array
        self.verticesLength = self.vertices.buffer_info()[1]

        # Size in bytes for each element
        self.verticesItemSize = self.vertices.itemsize

        # Total size in bytes for entire array
        self.verticesDataLength = self.verticesLength * self.verticesItemSize

        # Number of vertices in the array
        self.numberOfVertices = int(self.verticesLength / 3)

        # Tell gl to prepare a buffer
        self.vertexBuffer = self.gl.glGenBuffers(1)

        # Say that the buffer is of type GL_ARRAY_BUFFER
        self.gl.glBindBuffer(self.gl.GL_ARRAY_BUFFER, self.vertexBuffer)

        # Copy data into the buffer
        self.gl.glBufferData(self.gl.GL_ARRAY_BUFFER, self.verticesDataLength,
                             self.vertices.tobytes(), self.gl.GL_STATIC_DRAW)

        # Say that the somePosition attribute should be read from the current array, that it should take three values at a
        # time (x, y, z), and that they are of the type GL_FLOAT
        self.gl.glVertexAttribPointer(self.somePosition, 3, self.gl.GL_FLOAT,
                                      False, 0, 0)

        # When reading from the current data, start at position 0
        self.gl.glEnableVertexAttribArray(0)

        # Tell GL that whenever we run glClear, this is the color that
        # should be used. We only need to do this once.
        self.gl.glClearColor(0.1, 0.1, 0.1, 1.0)

        self.dumpGLLogMessages("setupGL()")
Esempio n. 3
0
    def setupGL(self):

        self.program = QOpenGLShaderProgram(self.context())
        info("PROGRAM", self.program)

        # addShaderFromSourceCode() only returns a bool telling whether everything went well

        if self.program.addShaderFromSourceCode(QOpenGLShader.Vertex,
                                                self.vertexShaderSource):
            info("VERTEX SHADER",
                 "Managed to load and parse the vertex shader")

        if self.program.addShaderFromSourceCode(QOpenGLShader.Fragment,
                                                self.fragmentShaderSource):
            info("FRAGMENT SHADER",
                 "Managed to load and parse the fragment shader")

        # Compile and bind the shader program to the current context
        self.program.link()
        self.program.bind()

        # Find the uniform location for controling the viewport scale of the vertex positions
        self.viewportScaling = self.program.uniformLocation("viewportScaling")

        # Find the uniform location for controling the rotation of the object
        self.objectRotation = self.program.uniformLocation("objectRotation")

        # Find light setting uniforms
        self.diffuseStrengthUniform = self.program.uniformLocation(
            "diffuseStrength")
        self.ambientStrengthUniform = self.program.uniformLocation(
            "ambientStrength")
        self.specularStrengthUniform = self.program.uniformLocation(
            "specularStrength")
        self.specularHardnessUniform = self.program.uniformLocation(
            "specularHardness")

        # This returns a numpy array with the shape [ [XYZNNN] [XYZNNN] ... ]
        self.vertices2d = self.suzanne.getVertexAndNormalArray()

        # ... so we need to flatten it to an 1d array
        self.vertices = self.suzanne.getVertexAndNormalArray().flatten()

        # Number of elements in the flattened array
        self.verticesLength = self.vertices.size

        # Each vertex is specified with with six values (xyznnn)
        self.arrayCellsPerVertex = 6

        # Size in bytes for each vertex specification (self.vertices.itemsize is the size in bytes
        # of a single array cell)
        self.vertexSpecificationSize = self.vertices.itemsize * self.arrayCellsPerVertex

        # In bytes, where in a vertex specification does the normal data start? (it starts after
        # x, y, z.. i.e after 3 array cells)
        self.normalBytesOffset = self.vertices.itemsize * 3

        # How many bytes are there in between vertex location specifications
        self.vertexStride = self.vertices.itemsize * self.arrayCellsPerVertex

        # What GL datatype should we tell the buffer that we're using? This is necessary, since it
        # might be different on 32-bit and 64-bit machines

        self.glDataType = None  # let it crash if it isn't float or double

        if self.vertices.itemsize == 4:
            self.glDataType = self.gl.GL_FLOAT

        if self.vertices.itemsize == 8:
            self.glDataType = self.gl.GL_DOUBLE

        # Total size in bytes for entire array
        self.verticesDataLength = self.vertices.nbytes

        # 2d Array with vertex indices that make up faces
        self.indices2d = self.suzanne.getFaceArray()

        # Flattened version suitable for drawElements
        self.indices = self.indices2d.flatten().tolist()

        # Number of elements in the index array.
        self.numberOfVertices = self.indices2d.size

        # Start specifying the Vertex Array Object (VAO).
        self.suzanneVAO = QOpenGLVertexArrayObject()
        self.suzanneVAO.create()
        self.suzanneVAO.bind()

        # Create a VBO for holding vertex info (both positions and normals)
        self.verticesBuffer = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
        self.verticesBuffer.create()
        self.verticesBuffer.bind()
        self.verticesBuffer.setUsagePattern(QOpenGLBuffer.StaticDraw)
        self.verticesBuffer.allocate(self.vertices.tobytes(),
                                     self.verticesDataLength)

        # Here we specify that there is a program attribute that should get data that is sent
        # to it (by glDraw* operations), and in what form the data will arrive.
        self.program.enableAttributeArray(
            self.program.attributeLocation("somePosition"))
        self.program.setAttributeBuffer(
            self.program.attributeLocation("somePosition"), self.glDataType, 0,
            3, self.vertexStride)

        # Say that the inputNormal attribute should be read from the same array, that it should take three values at a
        # time (the normal vector), and that they are of type GL_FLOAT. The same byte offset as for the position info is used, but
        # we now also specify that the normal information starts at normalBytesOffset bytes into each vertex specification
        self.program.enableAttributeArray(
            self.program.attributeLocation("inputNormal"))
        self.program.setAttributeBuffer(
            self.program.attributeLocation("inputNormal"), self.glDataType,
            self.normalBytesOffset, 3, self.vertexStride)

        # Once we have set up everything related to the VBOs, we can release that and the
        # related VAO.
        self.verticesBuffer.release()
        self.suzanneVAO.release()

        # Release the program until we need to actually draw something.
        self.program.release()

        self.gl.glClearColor(0.1, 0.1, 0.1, 1.0)

        self.dumpGLLogMessages("setupGL()")
Esempio n. 4
0
    def setupGL(self):

        self.program = QOpenGLShaderProgram(self.context())
        info("PROGRAM", self.program)

        # addShaderFromSourceCode() only returns a bool telling whether everything went well

        if self.program.addShaderFromSourceCode(QOpenGLShader.Vertex,
                                                self.vertexShaderSource):
            info("VERTEX SHADER",
                 "Managed to load and parse the vertex shader")

        if self.program.addShaderFromSourceCode(QOpenGLShader.Fragment,
                                                self.fragmentShaderSource):
            info("FRAGMENT SHADER",
                 "Managed to load and parse the fragment shader")

        # Compile and bind the shader program to the current context
        self.program.link()
        self.program.bind()

        # Bind the shader attribute for transfering vertex positions to a python variable
        self.somePosition = self.gl.glGetAttribLocation(
            self.program.programId(), "somePosition")

        # Bind the shader attribute for transfering vertex colors to a python variable
        self.inputColor = self.gl.glGetAttribLocation(self.program.programId(),
                                                      "inputColor")

        # Bind the shader "uniform" for controling the viewport scale of the vertex positions
        self.viewportScaling = self.gl.glGetUniformLocation(
            self.program.programId(), "viewportScaling")

        # Bind the shader "uniform" for controling the rotation of the object
        self.objectRotation = self.gl.glGetUniformLocation(
            self.program.programId(), "objectRotation")

        # Here we mix vertex data (x, y, z) with color data (r, g, b, a).
        self.vertices = array.array(
            'f',
            [
                -0.5,
                -0.5,
                0.0,
                1.0,
                0.0,
                0.0,
                1.0,  # Bottom left is red
                -0.5,
                0.5,
                0.0,
                0.0,
                1.0,
                0.0,
                1.0,  # Top left is green
                0.5,
                0.5,
                0.0,
                0.0,
                0.0,
                1.0,
                1.0,  # Top right is blue
                0.5,
                -0.5,
                0.0,
                1.0,
                1.0,
                0.0,
                1.0  # Bottom right is yellow
            ])

        # Buffer info returns a tuple where the second part is number of elements in the array
        self.verticesLength = self.vertices.buffer_info()[1]

        # Each vertex is specified with with seven values (xyzrgba)
        self.arrayCellsPerVertex = 7

        # Size in bytes for each vertex specification (self.vertices.itemsize is the size in bytes
        # of a single array cell)
        self.vertexSpecificationSize = self.vertices.itemsize * self.arrayCellsPerVertex

        # In bytes, where in a vertex specification does the color data start? (it starts after
        # x, y, z.. i.e after 3 array cells)
        self.colorBytesOffset = self.vertices.itemsize * 3

        # Total size in bytes for entire array
        self.verticesDataLength = self.verticesLength * self.vertices.itemsize

        # Number of vertices in the array
        self.numberOfVertices = int(self.verticesLength /
                                    self.arrayCellsPerVertex)

        # Tell gl to prepare a single buffer
        self.vertexBuffer = self.gl.glGenBuffers(1)

        # Say that the buffer is of type GL_ARRAY_BUFFER
        self.gl.glBindBuffer(self.gl.GL_ARRAY_BUFFER, self.vertexBuffer)

        # Copy data into the buffer
        self.gl.glBufferData(self.gl.GL_ARRAY_BUFFER, self.verticesDataLength,
                             self.vertices.tobytes(), self.gl.GL_STATIC_DRAW)

        # Say that the somePosition attribute should be read from the current array, that it should take three values at a
        # time (x, y, z), and that they are of the type GL_FLOAT. We now also specify a byte offset (vertexSpecificationSize)
        # to say that each new vertex specification is starting this many bytes after the prior one.
        self.gl.glVertexAttribPointer(self.somePosition, 3, self.gl.GL_FLOAT,
                                      False, self.vertexSpecificationSize, 0)

        # Connect the array to the somePosition variable
        self.gl.glEnableVertexAttribArray(self.somePosition)

        # Say that the inputColor attribute should be read from the current array, that it should take four values at a
        # time (r, g, b, a), and that they are of type GL_FLOAT. The same byte offset as for the position info is used, but
        # we now also specify that the color information starts at colorBytesOffset bytes into each vertex specification
        self.gl.glVertexAttribPointer(self.inputColor, 4, self.gl.GL_FLOAT,
                                      False, self.vertexSpecificationSize,
                                      self.colorBytesOffset)

        # Connect the array to the inputColor variable
        self.gl.glEnableVertexAttribArray(self.inputColor)

        # Tell GL that whenever we run glClear, this is the color that
        # should be used. We only need to do this once.
        self.gl.glClearColor(0.1, 0.1, 0.1, 1.0)

        self.dumpGLLogMessages("setupGL()")
Esempio n. 5
0
 def sizeHint(self):
     info("TESTCANVAS", "using overridden sizeHint()")
     return QSize(600, 600)
Esempio n. 6
0
    def setupGL(self):

        self.program = QOpenGLShaderProgram(self.context())
        info("PROGRAM", self.program)

        # addShaderFromSourceCode() only returns a bool telling whether everything went well

        if self.program.addShaderFromSourceCode(QOpenGLShader.Vertex,
                                                self.vertexShaderSource):
            info("VERTEX SHADER",
                 "Managed to load and parse the vertex shader")

        if self.program.addShaderFromSourceCode(QOpenGLShader.Fragment,
                                                self.fragmentShaderSource):
            info("FRAGMENT SHADER",
                 "Managed to load and parse the fragment shader")

        # Compile and bind the shader program to the current context
        self.program.link()
        self.program.bind()

        # Find the uniform location for controling the viewport scale of the vertex positions
        self.viewportScaling = self.program.uniformLocation("viewportScaling")

        # Find the uniform location for controling the rotation of the object
        self.objectRotation = self.program.uniformLocation("objectRotation")

        # Use arrays to specify two different triangles.
        self.vertices1 = array.array(
            'f', [-0.5, -0.5, 0.0, 0.5, 0.5, 0.0, 0.5, -0.5, 0.0])
        self.vertices2 = array.array(
            'f', [-0.8, 0.8, 0.0, -0.1, 0.8, 0.0, -0.8, 0.1, 0.0])

        # We'll take a shortcut here and use the same size/length for both objects. In reality
        # the following calculations should be done for each vertex array.

        # Buffer info returns a tuple where the second part is number of elements in the array
        self.verticesLength = self.vertices1.buffer_info()[1]

        # Size in bytes for each element
        self.verticesItemSize = self.vertices1.itemsize

        # Total size in bytes for entire array
        self.verticesDataLength = self.verticesLength * self.verticesItemSize

        # Number of vertices in the array
        self.numberOfVertices = int(self.verticesLength / 3)

        # Start specifying the first Vertex Array Object (VAO). The upside of this approach
        # is that we can keep all settings pertaining to the Vertex Buffer Object (VBO) specified
        # here and not have to specify them again at draw time. This will make it a lot easier
        # to keep multiple conceptual graphical objects around.
        #
        # The VAO will remember all that was specified for its VBOs between the VAOs bind() and
        # its close()
        self.triangleVAO1 = QOpenGLVertexArrayObject()
        self.triangleVAO1.create()
        self.triangleVAO1.bind()

        # Instead of asking GL directly to allocate an array buffer, we ask QT
        # to set up one for us. In GL language we are creating a "VBO" here.
        self.verticesBuffer1 = QOpenGLBuffer()
        self.verticesBuffer1.create()
        self.verticesBuffer1.bind()
        self.verticesBuffer1.setUsagePattern(QOpenGLBuffer.StaticDraw)
        self.verticesBuffer1.allocate(self.vertices1.tobytes(),
                                      self.verticesDataLength)

        # Here we specify that there is a program attribute that should get data that is sent
        # to it (by glDraw* operations), and in what form the data will arrive.
        self.program.enableAttributeArray(
            self.program.attributeLocation("somePosition"))
        self.program.setAttributeBuffer(
            self.program.attributeLocation("somePosition"), self.gl.GL_FLOAT,
            0, 3, 0)

        # Once we have set up everything related to the VBO, we can release that and the
        # related VAO.
        self.verticesBuffer1.release()
        self.triangleVAO1.release()

        # Start specifying the second VAO
        self.triangleVAO2 = QOpenGLVertexArrayObject()
        self.triangleVAO2.create()
        self.triangleVAO2.bind()

        # Create the second VBO
        self.verticesBuffer2 = QOpenGLBuffer()
        self.verticesBuffer2.create()
        self.verticesBuffer2.bind()
        self.verticesBuffer2.setUsagePattern(QOpenGLBuffer.StaticDraw)
        self.verticesBuffer2.allocate(self.vertices2.tobytes(),
                                      self.verticesDataLength)

        # Specify location of vertex attribute in the shader.
        self.program.enableAttributeArray(
            self.program.attributeLocation("somePosition"))
        self.program.setAttributeBuffer(
            self.program.attributeLocation("somePosition"), self.gl.GL_FLOAT,
            0, 3, 0)

        # Release the second VAO and VBO
        self.verticesBuffer2.release()
        self.triangleVAO2.release()

        # Release the program until we need to actually draw something.
        self.program.release()

        self.gl.glClearColor(0.1, 0.1, 0.1, 1.0)

        self.dumpGLLogMessages("setupGL()")
Esempio n. 7
0
    def setupGL(self):

        self.program = QOpenGLShaderProgram(self.context())
        info("PROGRAM",self.program)

        # addShaderFromSourceCode() only returns a bool telling whether everything went well

        if self.program.addShaderFromSourceCode(QOpenGLShader.Vertex, self.vertexShaderSource):
            info("VERTEX SHADER","Managed to load and parse the vertex shader")

        if self.program.addShaderFromSourceCode(QOpenGLShader.Fragment, self.fragmentShaderSource):
            info("FRAGMENT SHADER","Managed to load and parse the fragment shader")

        # Compile and bind the shader program to the current context
        self.program.link()
        self.program.bind()

        # Find the uniform location for controling the viewport scale of the vertex positions
        self.viewportScaling = self.program.uniformLocation("viewportScaling")

        # Find the uniform location for controling the rotation of the object
        self.objectRotation = self.program.uniformLocation("objectRotation")

        # Location and color for vertices. We specity vertices independently of
        # faces, so it does not matter in which order they occur. 
        self.vertices = array.array('f', [
            -0.5,-0.5,-0.5,   1.0, 0.0, 0.0, 1.0, # Front bottom left is red
            -0.5, 0.5,-0.5,   0.0, 1.0, 0.0, 1.0, # Front top left is green
             0.5, 0.5,-0.5,   0.0, 0.0, 1.0, 1.0, # Front top right is blue
             0.5,-0.5,-0.5,   1.0, 1.0, 0.0, 1.0, # Front bottom right is yellow
            -0.5,-0.5, 0.5,   0.0, 1.0, 1.0, 1.0, # Back bottom left is cyan
            -0.5, 0.5, 0.5,   1.0, 1.0, 1.0, 1.0, # Back top left is white
             0.5, 0.5, 0.5,   1.0, 0.0, 1.0, 1.0, # Back top right is purple
             0.5,-0.5, 0.5,   0.5, 0.5, 0.5, 1.0  # Back bottom right is gray
        ])

        # Buffer info returns a tuple where the second part is number of elements in the array
        self.verticesLength = self.vertices.buffer_info()[1]

        # Each vertex is specified with with seven values (xyzrgba)
        self.arrayCellsPerVertex = 7

        # Size in bytes for each vertex specification (self.vertices.itemsize is the size in bytes
        # of a single array cell)
        self.vertexSpecificationSize = self.vertices.itemsize * self.arrayCellsPerVertex

        # In bytes, where in a vertex specification does the color data start? (it starts after 
        # x, y, z.. i.e after 3 array cells)
        self.colorBytesOffset = self.vertices.itemsize * 3

        # How many bytes are there in between vertex location specifications
        self.vertexStride = self.vertices.itemsize * 7  # (7 because XYZRGBA)

        # Total size in bytes for entire array
        self.verticesDataLength = self.verticesLength * self.vertices.itemsize

        # Create an array with unsigned short values for specifying each face 
        # of the cube
        self.indices = array.array('H', [
            0, 1, 2, 3,    # Front face
            4, 5, 6, 7,    # Back face
            1, 0, 4, 5,    # Left face
            2, 3, 7, 6,    # Right face
            1, 2, 6, 5,    # Top face
            0, 3, 7, 4     # Bottom face
        ])

        # Number of vertices in the index array. Note that this is different
        # from the number of vertices in the *vertex* array (which are 8 in 
        # total). In the *index* array, each vertex can be counted multiple 
        # times. So for 6 faces with 4 vertices each, we have 24 vertices 
        # specified by their indexes. 
        self.numberOfVertices = self.indices.buffer_info()[1]

        # Start specifying the Vertex Array Object (VAO). 
        self.cubeVAO = QOpenGLVertexArrayObject()
        self.cubeVAO.create()
        self.cubeVAO.bind()
 
        # Create a VBO for holding vertex position info
        self.verticesBuffer = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer)
        self.verticesBuffer.create()
        self.verticesBuffer.bind()
        self.verticesBuffer.setUsagePattern(QOpenGLBuffer.StaticDraw)
        self.verticesBuffer.allocate(self.vertices.tobytes(), self.verticesDataLength)

        # Here we specify that there is a program attribute that should get data that is sent
        # to it (by glDraw* operations), and in what form the data will arrive. 
        self.program.enableAttributeArray( self.program.attributeLocation("somePosition") )
        self.program.setAttributeBuffer( self.program.attributeLocation("somePosition"), self.gl.GL_FLOAT, 0, 3, self.vertexStride )
        
        # Say that the inputColor attribute should be read from the same array, that it should take four values at a 
        # time (r, g, b, a), and that they are of type GL_FLOAT. The same byte offset as for the position info is used, but
        # we now also specify that the color information starts at colorBytesOffset bytes into each vertex specification
        self.program.enableAttributeArray( self.program.attributeLocation("inputColor") )
        self.program.setAttributeBuffer( self.program.attributeLocation("inputColor"), self.gl.GL_FLOAT, self.colorBytesOffset, 4, self.vertexStride )
        
        # Once we have set up everything related to the VBOs, we can release that and the 
        # related VAO.
        self.verticesBuffer.release()
        self.cubeVAO.release()
     
        # Release the program until we need to actually draw something. 
        self.program.release()

        self.gl.glClearColor(0.1, 0.1, 0.1, 1.0)

        self.dumpGLLogMessages("setupGL()")