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()")
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()")
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()")
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()")
def sizeHint(self): info("TESTCANVAS", "using overridden sizeHint()") return QSize(600, 600)
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()")
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()")