├── LICENSE ├── README.md ├── Tut 01 Hello Triangle ├── framework.py └── tut1.py ├── Tut 02 Playing with Colors ├── FragPosition.py ├── VertexColors.py ├── data │ ├── FragPosition.frag │ ├── FragPosition.vert │ ├── VertexColors.frag │ └── VertexColors.vert └── framework.py ├── Tut 03 OpenGLs Moving Triangle ├── cpuPositionOffset.py ├── data │ ├── calcColor.frag │ ├── calcOffset.vert │ ├── positionOffset.vert │ ├── standard.frag │ └── standard.vert ├── fragChangeColor.py ├── framework.py ├── vertCalcOffset.py └── vertPositionOffset.py ├── Tut 04 Objects at Rest ├── AspectRatio.py ├── AspectRatio_modified.py ├── MatrixPerspective.py ├── OrthoCube.py ├── ShaderPerspective.py ├── data │ ├── ManualPerspective.vert │ ├── MatrixPerspective.vert │ ├── OrthoWithOffset.vert │ └── StandardColors.frag └── framework.py ├── Tut 05 Objects in Depth ├── BaseVertexOverlap.py ├── DepthBuffer.py ├── DepthClamping.py ├── OverlapNoDepth.py ├── VertexClipping.py ├── data │ ├── Standard.frag │ └── Standard.vert └── framework.py └── Tut 06 Objects in Motion ├── Rotations.py ├── Scale.py ├── Translation.py ├── data ├── ColorMultUniform.frag ├── ColorPassthrough.frag └── PosColorLocalTransform.vert ├── framework.py └── framework.pyc /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Mario Rosasco 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PyOpenGL-Tutorial 2 | A Python/PyOpenGL implementation of the first few example programs from Jason McKesson's excellent OpenGL tutorial. 3 | 4 | The tutorial book associated with these programs can be found at https://alfonse.bitbucket.io/oldtut/index.html (copyright Jason McKesson). 5 | 6 | The goal of this project is to convert the tutorial's C++ OpenGL examples to Python to demonstrate the ways in which PyOpenGL differs from C++ OpenGL. 7 | -------------------------------------------------------------------------------- /Tut 01 Hello Triangle/framework.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from framework.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | # 5 | # NB: Unlike in the framework.cpp organization, the main loop is contained 6 | # in the tutorial files, not in this framework file. Additionally, a copy of 7 | # this module file must exist in the same directory as the tutorial files 8 | # to be imported properly. 9 | 10 | from OpenGL.GLUT import * 11 | from OpenGL.GLU import * 12 | from OpenGL.GL import * 13 | import os 14 | import sys 15 | 16 | # Function that creates and compiles shaders according to the given type (a GL enum value) and 17 | # shader program (a file containing a GLSL program). 18 | def loadShader(shaderType, shaderFile): 19 | # check if file exists, get full path name 20 | strFilename = findFileOrThrow(shaderFile) 21 | shaderData = None 22 | with open(strFilename, 'r') as f: 23 | shaderData = f.read() 24 | 25 | shader = glCreateShader(shaderType) 26 | glShaderSource(shader, shaderData) # note that this is a simpler function call than in C 27 | 28 | # This shader compilation is more explicit than the one used in 29 | # framework.cpp, which relies on a glutil wrapper function. 30 | # This is made explicit here mainly to decrease dependence on pyOpenGL 31 | # utilities and wrappers, which docs caution may change in future versions. 32 | glCompileShader(shader) 33 | 34 | status = glGetShaderiv(shader, GL_COMPILE_STATUS) 35 | if status == GL_FALSE: 36 | # Note that getting the error log is much simpler in Python than in C/C++ 37 | # and does not require explicit handling of the string buffer 38 | strInfoLog = glGetShaderInforLog(shader) 39 | strShaderType = "" 40 | if shaderType is GL_VERTEX_SHADER: 41 | strShaderType = "vertex" 42 | elif shaderType is GL_GEOMETRY_SHADER: 43 | strShaderType = "geometry" 44 | elif shaderType is GL_FRAGMENT_SHADER: 45 | strShaderType = "fragment" 46 | 47 | print "Compilation failure for " + strShaderType + " shader:\n" + strInfoLog 48 | 49 | return shader 50 | 51 | # Function that accepts a list of shaders, compiles them, and returns a handle to the compiled program 52 | def createProgram(shaderList): 53 | program = glCreateProgram() 54 | 55 | for shader in shaderList: 56 | glAttachShader(program, shader) 57 | 58 | glLinkProgram(program) 59 | 60 | status = glGetProgramiv(program, GL_LINK_STATUS) 61 | if status == GL_FALSE: 62 | # Note that getting the error log is much simpler in Python than in C/C++ 63 | # and does not require explicit handling of the string buffer 64 | strInfoLog = glGetProgramInfoLog(program) 65 | print "Linker failure: \n" + strInfoLog 66 | 67 | for shader in shaderList: 68 | glDetachShader(program, shader) 69 | 70 | return program 71 | 72 | 73 | # Helper function to locate and open the target file (passed in as a string). 74 | # Returns the full path to the file as a string. 75 | def findFileOrThrow(strBasename): 76 | # Keep constant names in C-style convention, for readability 77 | # when comparing to C(/C++) code. 78 | LOCAL_FILE_DIR = "data" + os.sep 79 | GLOBAL_FILE_DIR = ".." + os.sep + "data" + os.sep 80 | 81 | strFilename = LOCAL_FILE_DIR + strBasename 82 | if os.path.isfile(strFilename): 83 | return strFilename 84 | 85 | strFilename = GLOBAL_FILE_DIR + strBasename 86 | if os.path.isfile(strFilename): 87 | return strFilename 88 | 89 | raise IOError('Could not find target file ' + strBasename) 90 | -------------------------------------------------------------------------------- /Tut 01 Hello Triangle/tut1.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from tut1.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | from array import array 9 | import numpy as np 10 | from framework import * 11 | 12 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 13 | # Note that this must be a numpy array, since as of 14 | # 170111 support for lists has not been implemented. 15 | vertexPositions = np.array( 16 | [0.75, 0.75, 0.0, 1.0, 17 | 0.75, -0.75, 0.0, 1.0, 18 | -0.75, -0.75, 0.0, 1.0], 19 | dtype='float32' 20 | ) 21 | 22 | vertexDim = 4 23 | nVertices = 3 24 | 25 | # Function that creates and compiles shaders according to the given type (a GL enum value) and 26 | # shader program (a string containing a GLSL program). 27 | def createShader(shaderType, shaderFile): 28 | shader = glCreateShader(shaderType) 29 | glShaderSource(shader, shaderFile) # note that this is a simpler function call than in C 30 | 31 | glCompileShader(shader) 32 | 33 | status = None 34 | glGetShaderiv(shader, GL_COMPILE_STATUS, status) 35 | if status == GL_FALSE: 36 | # Note that getting the error log is much simpler in Python than in C/C++ 37 | # and does not require explicit handling of the string buffer 38 | strInfoLog = glGetShaderInforLog(shader) 39 | strShaderType = "" 40 | if shaderType is GL_VERTEX_SHADER: 41 | strShaderType = "vertex" 42 | elif shaderType is GL_GEOMETRY_SHADER: 43 | strShaderType = "geometry" 44 | elif shaderType is GL_FRAGMENT_SHADER: 45 | strShaderType = "fragment" 46 | 47 | print "Compilation failure for " + strShaderType + " shader:\n" + strInfoLog 48 | 49 | return shader 50 | 51 | # String containing vertex shader program written in GLSL 52 | strVertexShader = """ 53 | #version 330 54 | 55 | layout(location = 0) in vec4 position; 56 | void main() 57 | { 58 | gl_Position = position; 59 | } 60 | """ 61 | 62 | # String containing fragment shader program written in GLSL 63 | strFragmentShader = """ 64 | #version 330 65 | 66 | out vec4 outputColor; 67 | void main() 68 | { 69 | outputColor = vec4(1.0f, 1.0f, 1.0f, 1.0f); 70 | } 71 | """ 72 | 73 | # Global variable to represent the compiled shader program, written in GLSL 74 | theProgram = None 75 | 76 | # Global variable to represent the buffer that will hold the position vectors 77 | positionBufferObject = None 78 | 79 | 80 | 81 | # Set up the list of shaders, and call functions to compile them 82 | def initializeProgram(): 83 | shaderList = [] 84 | 85 | shaderList.append(createShader(GL_VERTEX_SHADER, strVertexShader)) 86 | shaderList.append(createShader(GL_FRAGMENT_SHADER, strFragmentShader)) 87 | 88 | global theProgram 89 | theProgram = createProgram(shaderList) 90 | 91 | for shader in shaderList: 92 | glDeleteShader(shader) 93 | 94 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 95 | def initializeVertexBuffer(): 96 | global positionBufferObject 97 | positionBufferObject = glGenBuffers(1) 98 | 99 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 100 | glBufferData( # PyOpenGL allows for the omission of the size parameter 101 | GL_ARRAY_BUFFER, 102 | vertexPositions, 103 | GL_STATIC_DRAW 104 | ) 105 | glBindBuffer(GL_ARRAY_BUFFER, 0) 106 | 107 | # Initialize the OpenGL environment 108 | def init(): 109 | initializeProgram() 110 | initializeVertexBuffer() 111 | glBindVertexArray(glGenVertexArrays(1)) 112 | 113 | # Called to update the display. 114 | # Because we are using double-buffering, glutSwapBuffers is called at the end 115 | # to write the rendered buffer to the display. 116 | def display(): 117 | glClearColor(0.0, 0.0, 0.0, 0.0) 118 | glClear(GL_COLOR_BUFFER_BIT) 119 | 120 | glUseProgram(theProgram) 121 | 122 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 123 | glEnableVertexAttribArray(0) 124 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 125 | 126 | glDrawArrays(GL_TRIANGLES, 0, nVertices) 127 | 128 | glDisableVertexAttribArray(0) 129 | glUseProgram(0) 130 | 131 | glutSwapBuffers() 132 | 133 | # keyboard input handler: exits the program if 'esc' is pressed 134 | def keyboard(key, x, y): 135 | if ord(key) == 27: # ord() is needed to get the keycode 136 | glutLeaveMainLoop() 137 | return 138 | 139 | # Called whenever the window's size changes (including once when the program starts) 140 | def reshape(w, h): 141 | glViewport(0, 0, w, h) 142 | 143 | # The main function 144 | def main(): 145 | glutInit() 146 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 147 | glutInitDisplayMode (displayMode) 148 | 149 | width = 500; 150 | height = 500; 151 | glutInitWindowSize (width, height) 152 | 153 | glutInitWindowPosition (300, 200) 154 | 155 | window = glutCreateWindow("Triangle Window: Tut1") 156 | 157 | init() 158 | glutDisplayFunc(display) 159 | glutReshapeFunc(reshape) 160 | glutKeyboardFunc(keyboard) 161 | 162 | glutMainLoop(); 163 | 164 | if __name__ == '__main__': 165 | main() 166 | -------------------------------------------------------------------------------- /Tut 02 Playing with Colors/FragPosition.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from FragPosition.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | from array import array 9 | import os 10 | import sys 11 | import numpy as np 12 | from framework import * 13 | 14 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 15 | # Note that this must be a numpy array, since as of 16 | # 170111 support for lists has not been implemented. 17 | vertexPositions = np.array( 18 | [0.75, 0.75, 0.0, 1.0, 19 | 0.75, -0.75, 0.0, 1.0, 20 | -0.75, -0.75, 0.0, 1.0], 21 | dtype='float32' 22 | ) 23 | 24 | vertexDim = 4 25 | nVertices = 3 26 | 27 | # Global variable to represent the compiled shader program, written in GLSL 28 | theProgram = None 29 | 30 | # Global variable to represent the buffer that will hold the position vectors 31 | vertexBufferObject = None 32 | 33 | # Set up the list of shaders, and call functions to compile them 34 | def initializeProgram(): 35 | shaderList = [] 36 | 37 | shaderList.append(loadShader(GL_VERTEX_SHADER, "FragPosition.vert")) 38 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "FragPosition.frag")) 39 | 40 | global theProgram 41 | theProgram = createProgram(shaderList) 42 | 43 | for shader in shaderList: 44 | glDeleteShader(shader) 45 | 46 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 47 | def initializeVertexBuffer(): 48 | global vertexBufferObject 49 | vertexBufferObject = glGenBuffers(1) 50 | 51 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 52 | glBufferData( # PyOpenGL allows for the omission of the size parameter 53 | GL_ARRAY_BUFFER, 54 | vertexPositions, 55 | GL_STATIC_DRAW 56 | ) 57 | glBindBuffer(GL_ARRAY_BUFFER, 0) 58 | 59 | # Initialize the OpenGL environment 60 | def init(): 61 | initializeProgram() 62 | initializeVertexBuffer() 63 | glBindVertexArray(glGenVertexArrays(1)) 64 | 65 | # Called to update the display. 66 | # Because we are using double-buffering, glutSwapBuffers is called at the end 67 | # to write the rendered buffer to the display. 68 | def display(): 69 | glClearColor(0.0, 0.0, 0.0, 0.0) 70 | glClear(GL_COLOR_BUFFER_BIT) 71 | 72 | glUseProgram(theProgram) 73 | 74 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 75 | glEnableVertexAttribArray(0) 76 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 77 | 78 | glDrawArrays(GL_TRIANGLES, 0, nVertices) 79 | 80 | glDisableVertexAttribArray(0) 81 | glUseProgram(0) 82 | 83 | glutSwapBuffers() 84 | 85 | # keyboard input handler: exits the program if 'esc' is pressed 86 | def keyboard(key, x, y): 87 | if ord(key) == 27: # ord() is needed to get the keycode 88 | glutLeaveMainLoop() 89 | return 90 | 91 | # Called whenever the window's size changes (including once when the program starts) 92 | def reshape(w, h): 93 | glViewport(0, 0, w, h) 94 | 95 | # The main function 96 | def main(): 97 | glutInit() 98 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 99 | glutInitDisplayMode (displayMode) 100 | 101 | width = 500; 102 | height = 500; 103 | glutInitWindowSize (width, height) 104 | 105 | glutInitWindowPosition (300, 200) 106 | 107 | window = glutCreateWindow("Triangle Window: Tut1") 108 | 109 | init() 110 | glutDisplayFunc(display) 111 | glutReshapeFunc(reshape) 112 | glutKeyboardFunc(keyboard) 113 | 114 | glutMainLoop(); 115 | 116 | if __name__ == '__main__': 117 | main() 118 | -------------------------------------------------------------------------------- /Tut 02 Playing with Colors/VertexColors.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from VertexColors.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | from array import array 9 | import os 10 | import sys 11 | import numpy as np 12 | from ctypes import c_void_p 13 | from framework import * 14 | 15 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 16 | # Note that this must be a numpy array, since as of 17 | # 170111 support for lists has not been implemented. 18 | vertexPositions = np.array( 19 | [0.0, 0.5, 0.0, 1.0, 20 | 0.5, -0.366, 0.0, 1.0, 21 | -0.5, -0.366, 0.0, 1.0, 22 | 1.0, 0.0, 0.0, 1.0, 23 | 0.0, 1.0, 0.0, 1.0, 24 | 0.0, 0.0, 1.0, 1.0], 25 | dtype='float32' 26 | ) 27 | 28 | vertexDim = 4 29 | nVertices = 3 30 | 31 | # Global variable to represent the compiled shader program, written in GLSL 32 | theProgram = None 33 | 34 | # Global variable to represent the buffer that will hold the position vectors 35 | vertexBufferObject = None 36 | 37 | # Set up the list of shaders, and call functions to compile them 38 | def initializeProgram(): 39 | shaderList = [] 40 | 41 | shaderList.append(loadShader(GL_VERTEX_SHADER, "VertexColors.vert")) 42 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "VertexColors.frag")) 43 | 44 | global theProgram 45 | theProgram = createProgram(shaderList) 46 | 47 | for shader in shaderList: 48 | glDeleteShader(shader) 49 | 50 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 51 | def initializeVertexBuffer(): 52 | global vertexBufferObject 53 | vertexBufferObject = glGenBuffers(1) 54 | 55 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 56 | glBufferData( # PyOpenGL allows for the omission of the size parameter 57 | GL_ARRAY_BUFFER, 58 | vertexPositions, 59 | GL_STATIC_DRAW 60 | ) 61 | glBindBuffer(GL_ARRAY_BUFFER, 0) 62 | 63 | # Initialize the OpenGL environment 64 | def init(): 65 | initializeProgram() 66 | initializeVertexBuffer() 67 | glBindVertexArray(glGenVertexArrays(1)) 68 | 69 | # Called to update the display. 70 | # Because we are using double-buffering, glutSwapBuffers is called at the end 71 | # to write the rendered buffer to the display. 72 | def display(): 73 | glClearColor(0.0, 0.0, 0.0, 0.0) 74 | glClear(GL_COLOR_BUFFER_BIT) 75 | 76 | glUseProgram(theProgram) 77 | 78 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 79 | glEnableVertexAttribArray(0) 80 | glEnableVertexAttribArray(1) 81 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 82 | # a ctype void pointer must be used to pass in the offset into the bound GL_ARRAY_BUFFER 83 | # also note that python's underlying float type is usally 64-bit, but 84 | # we have specified that our vertex array contains float32 data. 85 | colorOffset = c_void_p(vertexDim*nVertices*4) 86 | glVertexAttribPointer(1, vertexDim, GL_FLOAT, GL_FALSE, 0, colorOffset) 87 | 88 | glDrawArrays(GL_TRIANGLES, 0, nVertices) 89 | 90 | glDisableVertexAttribArray(0) 91 | glDisableVertexAttribArray(1) 92 | glUseProgram(0) 93 | 94 | glutSwapBuffers() 95 | glutPostRedisplay() 96 | 97 | # keyboard input handler: exits the program if 'esc' is pressed 98 | def keyboard(key, x, y): 99 | if ord(key) == 27: # ord() is needed to get the keycode 100 | glutLeaveMainLoop() 101 | return 102 | 103 | # Called whenever the window's size changes (including once when the program starts) 104 | def reshape(w, h): 105 | glViewport(0, 0, w, h) 106 | 107 | # The main function 108 | def main(): 109 | glutInit() 110 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 111 | glutInitDisplayMode (displayMode) 112 | 113 | width = 500; 114 | height = 500; 115 | glutInitWindowSize (width, height) 116 | 117 | glutInitWindowPosition (300, 200) 118 | 119 | window = glutCreateWindow("Tutorial Window") 120 | 121 | init() 122 | glutDisplayFunc(display) 123 | glutReshapeFunc(reshape) 124 | glutKeyboardFunc(keyboard) 125 | 126 | glutMainLoop(); 127 | 128 | if __name__ == '__main__': 129 | main() 130 | -------------------------------------------------------------------------------- /Tut 02 Playing with Colors/data/FragPosition.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | out vec4 outputColor; 4 | 5 | void main() 6 | { 7 | float lerpValue = gl_FragCoord.y / 500.0f; 8 | 9 | outputColor = mix(vec4(1.0f, 1.0f, 1.0f, 1.0f), vec4(0.2f, 0.2f, 0.2f, 1.0f), lerpValue); 10 | } 11 | -------------------------------------------------------------------------------- /Tut 02 Playing with Colors/data/FragPosition.vert: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | layout (location = 0) in vec4 position; 4 | 5 | void main() 6 | { 7 | gl_Position = position; 8 | } 9 | -------------------------------------------------------------------------------- /Tut 02 Playing with Colors/data/VertexColors.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | smooth in vec4 theColor; 4 | 5 | out vec4 outputColor; 6 | 7 | void main() 8 | { 9 | outputColor = theColor; 10 | } 11 | -------------------------------------------------------------------------------- /Tut 02 Playing with Colors/data/VertexColors.vert: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | layout (location = 0) in vec4 position; 4 | layout (location = 1) in vec4 color; 5 | 6 | smooth out vec4 theColor; 7 | 8 | void main() 9 | { 10 | gl_Position = position; 11 | theColor = color; 12 | } 13 | -------------------------------------------------------------------------------- /Tut 02 Playing with Colors/framework.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from framework.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | # 5 | # NB: Unlike in the framework.cpp organization, the main loop is contained 6 | # in the tutorial files, not in this framework file. Additionally, a copy of 7 | # this module file must exist in the same directory as the tutorial files 8 | # to be imported properly. 9 | 10 | from OpenGL.GLUT import * 11 | from OpenGL.GLU import * 12 | from OpenGL.GL import * 13 | import os 14 | import sys 15 | 16 | # Function that creates and compiles shaders according to the given type (a GL enum value) and 17 | # shader program (a file containing a GLSL program). 18 | def loadShader(shaderType, shaderFile): 19 | # check if file exists, get full path name 20 | strFilename = findFileOrThrow(shaderFile) 21 | shaderData = None 22 | with open(strFilename, 'r') as f: 23 | shaderData = f.read() 24 | 25 | shader = glCreateShader(shaderType) 26 | glShaderSource(shader, shaderData) # note that this is a simpler function call than in C 27 | 28 | # This shader compilation is more explicit than the one used in 29 | # framework.cpp, which relies on a glutil wrapper function. 30 | # This is made explicit here mainly to decrease dependence on pyOpenGL 31 | # utilities and wrappers, which docs caution may change in future versions. 32 | glCompileShader(shader) 33 | 34 | status = glGetShaderiv(shader, GL_COMPILE_STATUS) 35 | if status == GL_FALSE: 36 | # Note that getting the error log is much simpler in Python than in C/C++ 37 | # and does not require explicit handling of the string buffer 38 | strInfoLog = glGetShaderInforLog(shader) 39 | strShaderType = "" 40 | if shaderType is GL_VERTEX_SHADER: 41 | strShaderType = "vertex" 42 | elif shaderType is GL_GEOMETRY_SHADER: 43 | strShaderType = "geometry" 44 | elif shaderType is GL_FRAGMENT_SHADER: 45 | strShaderType = "fragment" 46 | 47 | print "Compilation failure for " + strShaderType + " shader:\n" + strInfoLog 48 | 49 | return shader 50 | 51 | # Function that accepts a list of shaders, compiles them, and returns a handle to the compiled program 52 | def createProgram(shaderList): 53 | program = glCreateProgram() 54 | 55 | for shader in shaderList: 56 | glAttachShader(program, shader) 57 | 58 | glLinkProgram(program) 59 | 60 | status = glGetProgramiv(program, GL_LINK_STATUS) 61 | if status == GL_FALSE: 62 | # Note that getting the error log is much simpler in Python than in C/C++ 63 | # and does not require explicit handling of the string buffer 64 | strInfoLog = glGetProgramInfoLog(program) 65 | print "Linker failure: \n" + strInfoLog 66 | 67 | for shader in shaderList: 68 | glDetachShader(program, shader) 69 | 70 | return program 71 | 72 | 73 | # Helper function to locate and open the target file (passed in as a string). 74 | # Returns the full path to the file as a string. 75 | def findFileOrThrow(strBasename): 76 | # Keep constant names in C-style convention, for readability 77 | # when comparing to C(/C++) code. 78 | LOCAL_FILE_DIR = "data" + os.sep 79 | GLOBAL_FILE_DIR = ".." + os.sep + "data" + os.sep 80 | 81 | strFilename = LOCAL_FILE_DIR + strBasename 82 | if os.path.isfile(strFilename): 83 | return strFilename 84 | 85 | strFilename = GLOBAL_FILE_DIR + strBasename 86 | if os.path.isfile(strFilename): 87 | return strFilename 88 | 89 | raise IOError('Could not find target file ' + strBasename) 90 | -------------------------------------------------------------------------------- /Tut 03 OpenGLs Moving Triangle/cpuPositionOffset.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from cpuPositionOffset.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | from array import array 9 | import os 10 | import sys 11 | import numpy as np 12 | from math import cos, sin 13 | from framework import * 14 | 15 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 16 | # Note that this must be a numpy array, since as of 17 | # 170111 support for lists has not been implemented. 18 | vertexPositions = np.array( 19 | [0.25, 0.25, 0.0, 1.0, 20 | 0.25, -0.25, 0.0, 1.0, 21 | -0.25, -0.25, 0.0, 1.0], 22 | dtype='float32' 23 | ) 24 | 25 | vertexDim = 4 26 | nVertices = 3 27 | 28 | # Global variable to represent the compiled shader program, written in GLSL 29 | theProgram = None 30 | 31 | # Global variable to represent the buffer that will hold the position vectors 32 | positionBufferObject = None 33 | 34 | # Set up the list of shaders, and call functions to compile them 35 | def initializeProgram(): 36 | shaderList = [] 37 | 38 | shaderList.append(loadShader(GL_VERTEX_SHADER, "standard.vert")) 39 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "standard.frag")) 40 | 41 | global theProgram 42 | theProgram = createProgram(shaderList) 43 | 44 | for shader in shaderList: 45 | glDeleteShader(shader) 46 | 47 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 48 | def initializeVertexBuffer(): 49 | global positionBufferObject 50 | positionBufferObject = glGenBuffers(1) 51 | 52 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 53 | glBufferData( # PyOpenGL allows for the omission of the size parameter 54 | GL_ARRAY_BUFFER, 55 | vertexPositions, 56 | GL_STREAM_DRAW 57 | ) 58 | glBindBuffer(GL_ARRAY_BUFFER, 0) 59 | 60 | # Initialize the OpenGL environment 61 | def init(): 62 | initializeProgram() 63 | initializeVertexBuffer() 64 | glBindVertexArray(glGenVertexArrays(1)) 65 | 66 | # compute the offsets required to rotate the image 67 | def computePositionOffsets(): 68 | fLoopDuration = 5.0 69 | fScale = 3.14159 * 2.0 / fLoopDuration 70 | 71 | fElapsedTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0 72 | 73 | fCurrTimeThroughLoop = fElapsedTime % fLoopDuration 74 | 75 | fXOffset = cos(fCurrTimeThroughLoop * fScale) * 0.5 76 | fYOffset = sin(fCurrTimeThroughLoop * fScale) * 0.5 77 | return (fXOffset, fYOffset) 78 | 79 | # Directly rearrange the vertex position data to move the image 80 | def adjustVertexData(fXOffset, fYOffset): 81 | fNewData = np.array(vertexPositions, copy=True) 82 | 83 | for i in range(0, len(vertexPositions), vertexDim): 84 | fNewData[i] += fXOffset 85 | fNewData[i + 1] += fYOffset 86 | 87 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 88 | size = len(fNewData) * 4 # sizeof(float32) 89 | glBufferSubData(GL_ARRAY_BUFFER, 0, size, fNewData) 90 | glBindBuffer(GL_ARRAY_BUFFER, 0) 91 | 92 | # Called to update the display. 93 | # Because we are using double-buffering, glutSwapBuffers is called at the end 94 | # to write the rendered buffer to the display. 95 | def display(): 96 | offsets = computePositionOffsets() 97 | fXOffset = offsets[0] 98 | fYOffset = offsets[1] 99 | adjustVertexData(fXOffset, fYOffset) 100 | 101 | glClearColor(0.0, 0.0, 0.0, 0.0) 102 | glClear(GL_COLOR_BUFFER_BIT) 103 | 104 | glUseProgram(theProgram) 105 | 106 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 107 | glEnableVertexAttribArray(0) 108 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 109 | 110 | glDrawArrays(GL_TRIANGLES, 0, nVertices) 111 | 112 | glDisableVertexAttribArray(0) 113 | glUseProgram(0) 114 | 115 | glutSwapBuffers() 116 | glutPostRedisplay() 117 | 118 | # keyboard input handler: exits the program if 'esc' is pressed 119 | def keyboard(key, x, y): 120 | if ord(key) == 27: # ord() is needed to get the keycode 121 | glutLeaveMainLoop() 122 | return 123 | 124 | # Called whenever the window's size changes (including once when the program starts) 125 | def reshape(w, h): 126 | glViewport(0, 0, w, h) 127 | 128 | # The main function 129 | def main(): 130 | glutInit() 131 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 132 | glutInitDisplayMode (displayMode) 133 | 134 | width = 500; 135 | height = 500; 136 | glutInitWindowSize (width, height) 137 | 138 | glutInitWindowPosition (300, 200) 139 | 140 | window = glutCreateWindow("Tutorial Window") 141 | 142 | init() 143 | glutDisplayFunc(display) 144 | glutReshapeFunc(reshape) 145 | glutKeyboardFunc(keyboard) 146 | 147 | glutMainLoop(); 148 | 149 | if __name__ == '__main__': 150 | main() 151 | -------------------------------------------------------------------------------- /Tut 03 OpenGLs Moving Triangle/data/calcColor.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | out vec4 outputColor; 4 | 5 | uniform float fragLoopDuration; 6 | uniform float time; 7 | 8 | const vec4 firstColor = vec4(1.0f, 1.0f, 1.0f, 1.0f); 9 | const vec4 secondColor = vec4(0.0f, 1.0f, 0.0f, 1.0f); 10 | 11 | void main() 12 | { 13 | float currTime = mod(time, fragLoopDuration); 14 | float currLerp = currTime / fragLoopDuration; 15 | 16 | outputColor = mix(firstColor, secondColor, currLerp); 17 | } 18 | -------------------------------------------------------------------------------- /Tut 03 OpenGLs Moving Triangle/data/calcOffset.vert: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | layout(location = 0) in vec4 position; 4 | uniform float loopDuration; 5 | uniform float time; 6 | 7 | void main() 8 | { 9 | float timeScale = 3.14159f * 2.0f / loopDuration; 10 | 11 | float currTime = mod(time, loopDuration); 12 | vec4 totalOffset = vec4( 13 | cos(currTime * timeScale) * 0.5f, 14 | sin(currTime * timeScale) * 0.5f, 15 | 0.0f, 16 | 0.0f); 17 | 18 | gl_Position = position + totalOffset; 19 | } 20 | -------------------------------------------------------------------------------- /Tut 03 OpenGLs Moving Triangle/data/positionOffset.vert: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | layout(location = 0) in vec4 position; 4 | uniform vec2 offset; 5 | 6 | void main() 7 | { 8 | vec4 totalOffset = vec4(offset.x, offset.y, 0.0, 0.0); 9 | gl_Position = position + totalOffset; 10 | } 11 | -------------------------------------------------------------------------------- /Tut 03 OpenGLs Moving Triangle/data/standard.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | out vec4 outputColor; 4 | 5 | void main() 6 | { 7 | outputColor = vec4(1.0f, 1.0f, 1.0f, 1.0f); 8 | } 9 | -------------------------------------------------------------------------------- /Tut 03 OpenGLs Moving Triangle/data/standard.vert: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | layout(location = 0) in vec4 position; 4 | 5 | void main() 6 | { 7 | gl_Position = position; 8 | } 9 | -------------------------------------------------------------------------------- /Tut 03 OpenGLs Moving Triangle/fragChangeColor.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from fragChangeColor.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | from array import array 9 | import os 10 | import sys 11 | import numpy as np 12 | from math import cos, sin 13 | from framework import * 14 | 15 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 16 | # Note that this must be a numpy array, since as of 17 | # 170111 support for lists has not been implemented. 18 | vertexPositions = np.array( 19 | [0.25, 0.25, 0.0, 1.0, 20 | 0.25, -0.25, 0.0, 1.0, 21 | -0.25, -0.25, 0.0, 1.0], 22 | dtype='float32' 23 | ) 24 | 25 | vertexDim = 4 26 | nVertices = 3 27 | 28 | # Global variable to represent the compiled shader program, written in GLSL 29 | theProgram = None 30 | 31 | # Global variable to represent the buffer that will hold the position vectors 32 | positionBufferObject = None 33 | 34 | # Global variable to store the location of the shader's uniform variable "time" 35 | elapsedTimeUniform = None 36 | 37 | # Set up the list of shaders, and call functions to compile them 38 | def initializeProgram(): 39 | shaderList = [] 40 | 41 | shaderList.append(loadShader(GL_VERTEX_SHADER, "calcOffset.vert")) 42 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "calcColor.frag")) 43 | 44 | global theProgram 45 | theProgram = createProgram(shaderList) 46 | 47 | for shader in shaderList: 48 | glDeleteShader(shader) 49 | 50 | global elapsedTimeUniform 51 | elapsedTimeUniform = glGetUniformLocation(theProgram, "time") 52 | 53 | loopDurationUnf = glGetUniformLocation(theProgram, "loopDuration") 54 | fragLoopDurUnf = glGetUniformLocation(theProgram, "fragLoopDuration") 55 | 56 | glUseProgram(theProgram) 57 | glUniform1f(loopDurationUnf, 5.0) 58 | glUniform1f(fragLoopDurUnf, 10.0) 59 | glUseProgram(0) 60 | 61 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 62 | def initializeVertexBuffer(): 63 | global positionBufferObject 64 | positionBufferObject = glGenBuffers(1) 65 | 66 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 67 | glBufferData( # PyOpenGL allows for the omission of the size parameter 68 | GL_ARRAY_BUFFER, 69 | vertexPositions, 70 | GL_STREAM_DRAW 71 | ) 72 | glBindBuffer(GL_ARRAY_BUFFER, 0) 73 | 74 | # Initialize the OpenGL environment 75 | def init(): 76 | initializeProgram() 77 | initializeVertexBuffer() 78 | glBindVertexArray(glGenVertexArrays(1)) 79 | 80 | # Called to update the display. 81 | # Because we are using double-buffering, glutSwapBuffers is called at the end 82 | # to write the rendered buffer to the display. 83 | def display(): 84 | glClearColor(0.0, 0.0, 0.0, 0.0) 85 | glClear(GL_COLOR_BUFFER_BIT) 86 | 87 | glUseProgram(theProgram) 88 | 89 | glUniform1f(elapsedTimeUniform, glutGet(GLUT_ELAPSED_TIME) / 1000.0) 90 | 91 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 92 | glEnableVertexAttribArray(0) 93 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 94 | 95 | glDrawArrays(GL_TRIANGLES, 0, nVertices) 96 | 97 | glDisableVertexAttribArray(0) 98 | glUseProgram(0) 99 | 100 | glutSwapBuffers() 101 | glutPostRedisplay() 102 | 103 | # keyboard input handler: exits the program if 'esc' is pressed 104 | def keyboard(key, x, y): 105 | if ord(key) == 27: # ord() is needed to get the keycode 106 | glutLeaveMainLoop() 107 | return 108 | 109 | # Called whenever the window's size changes (including once when the program starts) 110 | def reshape(w, h): 111 | glViewport(0, 0, w, h) 112 | 113 | # The main function 114 | def main(): 115 | glutInit() 116 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 117 | glutInitDisplayMode (displayMode) 118 | 119 | width = 500; 120 | height = 500; 121 | glutInitWindowSize (width, height) 122 | 123 | glutInitWindowPosition (300, 200) 124 | 125 | window = glutCreateWindow("Tutorial Window") 126 | 127 | init() 128 | glutDisplayFunc(display) 129 | glutReshapeFunc(reshape) 130 | glutKeyboardFunc(keyboard) 131 | 132 | glutMainLoop(); 133 | 134 | if __name__ == '__main__': 135 | main() 136 | -------------------------------------------------------------------------------- /Tut 03 OpenGLs Moving Triangle/framework.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from framework.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | # 5 | # NB: Unlike in the framework.cpp organization, the main loop is contained 6 | # in the tutorial files, not in this framework file. Additionally, a copy of 7 | # this module file must exist in the same directory as the tutorial files 8 | # to be imported properly. 9 | 10 | from OpenGL.GLUT import * 11 | from OpenGL.GLU import * 12 | from OpenGL.GL import * 13 | import os 14 | import sys 15 | 16 | # Function that creates and compiles shaders according to the given type (a GL enum value) and 17 | # shader program (a file containing a GLSL program). 18 | def loadShader(shaderType, shaderFile): 19 | # check if file exists, get full path name 20 | strFilename = findFileOrThrow(shaderFile) 21 | shaderData = None 22 | with open(strFilename, 'r') as f: 23 | shaderData = f.read() 24 | 25 | shader = glCreateShader(shaderType) 26 | glShaderSource(shader, shaderData) # note that this is a simpler function call than in C 27 | 28 | # This shader compilation is more explicit than the one used in 29 | # framework.cpp, which relies on a glutil wrapper function. 30 | # This is made explicit here mainly to decrease dependence on pyOpenGL 31 | # utilities and wrappers, which docs caution may change in future versions. 32 | glCompileShader(shader) 33 | 34 | status = glGetShaderiv(shader, GL_COMPILE_STATUS) 35 | if status == GL_FALSE: 36 | # Note that getting the error log is much simpler in Python than in C/C++ 37 | # and does not require explicit handling of the string buffer 38 | strInfoLog = glGetShaderInforLog(shader) 39 | strShaderType = "" 40 | if shaderType is GL_VERTEX_SHADER: 41 | strShaderType = "vertex" 42 | elif shaderType is GL_GEOMETRY_SHADER: 43 | strShaderType = "geometry" 44 | elif shaderType is GL_FRAGMENT_SHADER: 45 | strShaderType = "fragment" 46 | 47 | print "Compilation failure for " + strShaderType + " shader:\n" + strInfoLog 48 | 49 | return shader 50 | 51 | # Function that accepts a list of shaders, compiles them, and returns a handle to the compiled program 52 | def createProgram(shaderList): 53 | program = glCreateProgram() 54 | 55 | for shader in shaderList: 56 | glAttachShader(program, shader) 57 | 58 | glLinkProgram(program) 59 | 60 | status = glGetProgramiv(program, GL_LINK_STATUS) 61 | if status == GL_FALSE: 62 | # Note that getting the error log is much simpler in Python than in C/C++ 63 | # and does not require explicit handling of the string buffer 64 | strInfoLog = glGetProgramInfoLog(program) 65 | print "Linker failure: \n" + strInfoLog 66 | 67 | for shader in shaderList: 68 | glDetachShader(program, shader) 69 | 70 | return program 71 | 72 | 73 | # Helper function to locate and open the target file (passed in as a string). 74 | # Returns the full path to the file as a string. 75 | def findFileOrThrow(strBasename): 76 | # Keep constant names in C-style convention, for readability 77 | # when comparing to C(/C++) code. 78 | LOCAL_FILE_DIR = "data" + os.sep 79 | GLOBAL_FILE_DIR = ".." + os.sep + "data" + os.sep 80 | 81 | strFilename = LOCAL_FILE_DIR + strBasename 82 | if os.path.isfile(strFilename): 83 | return strFilename 84 | 85 | strFilename = GLOBAL_FILE_DIR + strBasename 86 | if os.path.isfile(strFilename): 87 | return strFilename 88 | 89 | raise IOError('Could not find target file ' + strBasename) 90 | -------------------------------------------------------------------------------- /Tut 03 OpenGLs Moving Triangle/vertCalcOffset.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from vertCalcOffset.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | from array import array 9 | import os 10 | import sys 11 | import numpy as np 12 | from math import cos, sin 13 | from framework import * 14 | 15 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 16 | # Note that this must be a numpy array, since as of 17 | # 170111 support for lists has not been implemented. 18 | vertexPositions = np.array( 19 | [0.25, 0.25, 0.0, 1.0, 20 | 0.25, -0.25, 0.0, 1.0, 21 | -0.25, -0.25, 0.0, 1.0], 22 | dtype='float32' 23 | ) 24 | 25 | vertexDim = 4 26 | nVertices = 3 27 | 28 | # Global variable to represent the compiled shader program, written in GLSL 29 | theProgram = None 30 | 31 | # Global variable to represent the buffer that will hold the position vectors 32 | positionBufferObject = None 33 | 34 | # Global variable to store the location of the shader's uniform variable "time" 35 | elapsedTimeUniform = None 36 | 37 | # Set up the list of shaders, and call functions to compile them 38 | def initializeProgram(): 39 | shaderList = [] 40 | 41 | shaderList.append(loadShader(GL_VERTEX_SHADER, "calcOffset.vert")) 42 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "standard.frag")) 43 | 44 | global theProgram 45 | theProgram = createProgram(shaderList) 46 | 47 | for shader in shaderList: 48 | glDeleteShader(shader) 49 | 50 | global elapsedTimeUniform 51 | elapsedTimeUniform = glGetUniformLocation(theProgram, "time") 52 | 53 | loopDurationUnf = glGetUniformLocation(theProgram, "loopDuration") 54 | glUseProgram(theProgram) 55 | glUniform1f(loopDurationUnf, 5.0) 56 | glUseProgram(0) 57 | 58 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 59 | def initializeVertexBuffer(): 60 | global positionBufferObject 61 | positionBufferObject = glGenBuffers(1) 62 | 63 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 64 | glBufferData( # PyOpenGL allows for the omission of the size parameter 65 | GL_ARRAY_BUFFER, 66 | vertexPositions, 67 | GL_STREAM_DRAW 68 | ) 69 | glBindBuffer(GL_ARRAY_BUFFER, 0) 70 | 71 | # Initialize the OpenGL environment 72 | def init(): 73 | initializeProgram() 74 | initializeVertexBuffer() 75 | glBindVertexArray(glGenVertexArrays(1)) 76 | 77 | # Called to update the display. 78 | # Because we are using double-buffering, glutSwapBuffers is called at the end 79 | # to write the rendered buffer to the display. 80 | def display(): 81 | glClearColor(0.0, 0.0, 0.0, 0.0) 82 | glClear(GL_COLOR_BUFFER_BIT) 83 | 84 | glUseProgram(theProgram) 85 | 86 | glUniform1f(elapsedTimeUniform, glutGet(GLUT_ELAPSED_TIME) / 1000.0) 87 | 88 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 89 | glEnableVertexAttribArray(0) 90 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 91 | 92 | glDrawArrays(GL_TRIANGLES, 0, nVertices) 93 | 94 | glDisableVertexAttribArray(0) 95 | glUseProgram(0) 96 | 97 | glutSwapBuffers() 98 | glutPostRedisplay() 99 | 100 | # keyboard input handler: exits the program if 'esc' is pressed 101 | def keyboard(key, x, y): 102 | if ord(key) == 27: # ord() is needed to get the keycode 103 | glutLeaveMainLoop() 104 | return 105 | 106 | # Called whenever the window's size changes (including once when the program starts) 107 | def reshape(w, h): 108 | glViewport(0, 0, w, h) 109 | 110 | # The main function 111 | def main(): 112 | glutInit() 113 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 114 | glutInitDisplayMode (displayMode) 115 | 116 | width = 500; 117 | height = 500; 118 | glutInitWindowSize (width, height) 119 | 120 | glutInitWindowPosition (300, 200) 121 | 122 | window = glutCreateWindow("Tutorial Window") 123 | 124 | init() 125 | glutDisplayFunc(display) 126 | glutReshapeFunc(reshape) 127 | glutKeyboardFunc(keyboard) 128 | 129 | glutMainLoop(); 130 | 131 | if __name__ == '__main__': 132 | main() 133 | -------------------------------------------------------------------------------- /Tut 03 OpenGLs Moving Triangle/vertPositionOffset.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from vertPositionOffset.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | from array import array 9 | import os 10 | import sys 11 | import numpy as np 12 | from math import cos, sin 13 | from framework import * 14 | 15 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 16 | # Note that this must be a numpy array, since as of 17 | # 170111 support for lists has not been implemented. 18 | vertexPositions = np.array( 19 | [0.25, 0.25, 0.0, 1.0, 20 | 0.25, -0.25, 0.0, 1.0, 21 | -0.25, -0.25, 0.0, 1.0], 22 | dtype='float32' 23 | ) 24 | 25 | vertexDim = 4 26 | nVertices = 3 27 | 28 | # Global variable to represent the compiled shader program, written in GLSL 29 | theProgram = None 30 | 31 | # Global variable to represent the buffer that will hold the position vectors 32 | positionBufferObject = None 33 | 34 | # Global variable to store the location of the shader's uniform variable "offset" 35 | offsetLocation = None 36 | 37 | # Set up the list of shaders, and call functions to compile them 38 | def initializeProgram(): 39 | shaderList = [] 40 | 41 | shaderList.append(loadShader(GL_VERTEX_SHADER, "positionOffset.vert")) 42 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "standard.frag")) 43 | 44 | global theProgram 45 | theProgram = createProgram(shaderList) 46 | 47 | for shader in shaderList: 48 | glDeleteShader(shader) 49 | 50 | global offsetLocation 51 | offsetLocation = glGetUniformLocation(theProgram, "offset") 52 | 53 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 54 | def initializeVertexBuffer(): 55 | global positionBufferObject 56 | positionBufferObject = glGenBuffers(1) 57 | 58 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 59 | glBufferData( # PyOpenGL allows for the omission of the size parameter 60 | GL_ARRAY_BUFFER, 61 | vertexPositions, 62 | GL_STREAM_DRAW 63 | ) 64 | glBindBuffer(GL_ARRAY_BUFFER, 0) 65 | 66 | # Initialize the OpenGL environment 67 | def init(): 68 | initializeProgram() 69 | initializeVertexBuffer() 70 | glBindVertexArray(glGenVertexArrays(1)) 71 | 72 | # compute the offsets required to rotate the image 73 | def computePositionOffsets(): 74 | fLoopDuration = 5.0 75 | fScale = 3.14159 * 2.0 / fLoopDuration 76 | 77 | fElapsedTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0 78 | 79 | fCurrTimeThroughLoop = fElapsedTime % fLoopDuration 80 | 81 | fXOffset = cos(fCurrTimeThroughLoop * fScale) * 0.5 82 | fYOffset = sin(fCurrTimeThroughLoop * fScale) * 0.5 83 | return (fXOffset, fYOffset) 84 | 85 | # Called to update the display. 86 | # Because we are using double-buffering, glutSwapBuffers is called at the end 87 | # to write the rendered buffer to the display. 88 | def display(): 89 | offsets = computePositionOffsets() 90 | fXOffset = offsets[0] 91 | fYOffset = offsets[1] 92 | 93 | glClearColor(0.0, 0.0, 0.0, 0.0) 94 | glClear(GL_COLOR_BUFFER_BIT) 95 | 96 | glUseProgram(theProgram) 97 | 98 | glUniform2f(offsetLocation, fXOffset, fYOffset) 99 | 100 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 101 | glEnableVertexAttribArray(0) 102 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 103 | 104 | glDrawArrays(GL_TRIANGLES, 0, nVertices) 105 | 106 | glDisableVertexAttribArray(0) 107 | glUseProgram(0) 108 | 109 | glutSwapBuffers() 110 | glutPostRedisplay() 111 | 112 | # keyboard input handler: exits the program if 'esc' is pressed 113 | def keyboard(key, x, y): 114 | if ord(key) == 27: # ord() is needed to get the keycode 115 | glutLeaveMainLoop() 116 | return 117 | 118 | # Called whenever the window's size changes (including once when the program starts) 119 | def reshape(w, h): 120 | glViewport(0, 0, w, h) 121 | 122 | # The main function 123 | def main(): 124 | glutInit() 125 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 126 | glutInitDisplayMode (displayMode) 127 | 128 | width = 500; 129 | height = 500; 130 | glutInitWindowSize (width, height) 131 | 132 | glutInitWindowPosition (300, 200) 133 | 134 | window = glutCreateWindow("Tutorial Window") 135 | 136 | init() 137 | glutDisplayFunc(display) 138 | glutReshapeFunc(reshape) 139 | glutKeyboardFunc(keyboard) 140 | 141 | glutMainLoop(); 142 | 143 | if __name__ == '__main__': 144 | main() 145 | -------------------------------------------------------------------------------- /Tut 04 Objects at Rest/AspectRatio.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from AspectRatio.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | import numpy as np 9 | from framework import * 10 | 11 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 12 | # Note that this must be a numpy array, since as of 13 | # 170111 support for lists has not been implemented. 14 | vertexData = np.array( 15 | [0.25, 0.25, -1.25, 1.0, 16 | 0.25, -0.25, -1.25, 1.0, 17 | -0.25, 0.25, -1.25, 1.0, 18 | 19 | 0.25, -0.25, -1.25, 1.0, 20 | -0.25, -0.25, -1.25, 1.0, 21 | -0.25, 0.25, -1.25, 1.0, 22 | 23 | 0.25, 0.25, -2.75, 1.0, 24 | -0.25, 0.25, -2.75, 1.0, 25 | 0.25, -0.25, -2.75, 1.0, 26 | 27 | 0.25, -0.25, -2.75, 1.0, 28 | -0.25, 0.25, -2.75, 1.0, 29 | -0.25, -0.25, -2.75, 1.0, 30 | 31 | -0.25, 0.25, -1.25, 1.0, 32 | -0.25, -0.25, -1.25, 1.0, 33 | -0.25, -0.25, -2.75, 1.0, 34 | 35 | -0.25, 0.25, -1.25, 1.0, 36 | -0.25, -0.25, -2.75, 1.0, 37 | -0.25, 0.25, -2.75, 1.0, 38 | 39 | 0.25, 0.25, -1.25, 1.0, 40 | 0.25, -0.25, -2.75, 1.0, 41 | 0.25, -0.25, -1.25, 1.0, 42 | 43 | 0.25, 0.25, -1.25, 1.0, 44 | 0.25, 0.25, -2.75, 1.0, 45 | 0.25, -0.25, -2.75, 1.0, 46 | 47 | 0.25, 0.25, -2.75, 1.0, 48 | 0.25, 0.25, -1.25, 1.0, 49 | -0.25, 0.25, -1.25, 1.0, 50 | 51 | 0.25, 0.25, -2.75, 1.0, 52 | -0.25, 0.25, -1.25, 1.0, 53 | -0.25, 0.25, -2.75, 1.0, 54 | 55 | 0.25, -0.25, -2.75, 1.0, 56 | -0.25, -0.25, -1.25, 1.0, 57 | 0.25, -0.25, -1.25, 1.0, 58 | 59 | 0.25, -0.25, -2.75, 1.0, 60 | -0.25, -0.25, -2.75, 1.0, 61 | -0.25, -0.25, -1.25, 1.0, 62 | 63 | 64 | 0.0, 0.0, 1.0, 1.0, 65 | 0.0, 0.0, 1.0, 1.0, 66 | 0.0, 0.0, 1.0, 1.0, 67 | 68 | 0.0, 0.0, 1.0, 1.0, 69 | 0.0, 0.0, 1.0, 1.0, 70 | 0.0, 0.0, 1.0, 1.0, 71 | 72 | 0.8, 0.8, 0.8, 1.0, 73 | 0.8, 0.8, 0.8, 1.0, 74 | 0.8, 0.8, 0.8, 1.0, 75 | 76 | 0.8, 0.8, 0.8, 1.0, 77 | 0.8, 0.8, 0.8, 1.0, 78 | 0.8, 0.8, 0.8, 1.0, 79 | 80 | 0.0, 1.0, 0.0, 1.0, 81 | 0.0, 1.0, 0.0, 1.0, 82 | 0.0, 1.0, 0.0, 1.0, 83 | 84 | 0.0, 1.0, 0.0, 1.0, 85 | 0.0, 1.0, 0.0, 1.0, 86 | 0.0, 1.0, 0.0, 1.0, 87 | 88 | 0.5, 0.5, 0.0, 1.0, 89 | 0.5, 0.5, 0.0, 1.0, 90 | 0.5, 0.5, 0.0, 1.0, 91 | 92 | 0.5, 0.5, 0.0, 1.0, 93 | 0.5, 0.5, 0.0, 1.0, 94 | 0.5, 0.5, 0.0, 1.0, 95 | 96 | 1.0, 0.0, 0.0, 1.0, 97 | 1.0, 0.0, 0.0, 1.0, 98 | 1.0, 0.0, 0.0, 1.0, 99 | 100 | 1.0, 0.0, 0.0, 1.0, 101 | 1.0, 0.0, 0.0, 1.0, 102 | 1.0, 0.0, 0.0, 1.0, 103 | 104 | 0.0, 1.0, 1.0, 1.0, 105 | 0.0, 1.0, 1.0, 1.0, 106 | 0.0, 1.0, 1.0, 1.0, 107 | 108 | 0.0, 1.0, 1.0, 1.0, 109 | 0.0, 1.0, 1.0, 1.0, 110 | 0.0, 1.0, 1.0, 1.0], 111 | dtype='float32' 112 | ) 113 | 114 | vertexDim = 4 115 | nVertices = 12*3 116 | 117 | # Global variable to represent the compiled shader program, written in GLSL 118 | theProgram = None 119 | 120 | # Global variable to represent the buffer that will hold the position vectors 121 | vertexBufferObject = None 122 | 123 | # Global variables to store the location of the shader's uniform variables 124 | offsetUniform = None 125 | perspectiveMatrixUnif = None 126 | 127 | # Global display variables 128 | perspectiveMatrix = None 129 | fFrustumScale = 1.0 130 | 131 | # Set up the list of shaders, and call functions to compile them 132 | def initializeProgram(): 133 | shaderList = [] 134 | 135 | shaderList.append(loadShader(GL_VERTEX_SHADER, "MatrixPerspective.vert")) 136 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "StandardColors.frag")) 137 | 138 | global theProgram 139 | theProgram = createProgram(shaderList) 140 | 141 | for shader in shaderList: 142 | glDeleteShader(shader) 143 | 144 | global offsetUniform 145 | offsetUniform = glGetUniformLocation(theProgram, "offset") 146 | 147 | global perspectiveMatrixUnif 148 | perspectiveMatrixUnif = glGetUniformLocation(theProgram, "perspectiveMatrix") 149 | 150 | fzNear = 0.5 151 | fzFar = 3.0 152 | 153 | global perspectiveMatrix 154 | perspectiveMatrix = np.zeros(16, dtype='float32') # note type 155 | perspectiveMatrix[0] = fFrustumScale 156 | perspectiveMatrix[5] = fFrustumScale 157 | perspectiveMatrix[10] = (fzFar + fzNear) / (fzNear - fzFar) 158 | perspectiveMatrix[14] = (2 * fzFar * fzNear) / (fzNear - fzFar) 159 | perspectiveMatrix[11] = -1.0 160 | 161 | glUseProgram(theProgram) 162 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 163 | glUseProgram(0) 164 | 165 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 166 | def initializeVertexBuffer(): 167 | global vertexBufferObject 168 | vertexBufferObject = glGenBuffers(1) 169 | 170 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 171 | glBufferData( # PyOpenGL allows for the omission of the size parameter 172 | GL_ARRAY_BUFFER, 173 | vertexData, 174 | GL_STREAM_DRAW 175 | ) 176 | glBindBuffer(GL_ARRAY_BUFFER, 0) 177 | 178 | # Initialize the OpenGL environment 179 | def init(): 180 | initializeProgram() 181 | initializeVertexBuffer() 182 | glBindVertexArray(glGenVertexArrays(1)) 183 | 184 | glEnable(GL_CULL_FACE) 185 | glCullFace(GL_BACK) 186 | glFrontFace(GL_CW) 187 | 188 | # Called to update the display. 189 | # Because we are using double-buffering, glutSwapBuffers is called at the end 190 | # to write the rendered buffer to the display. 191 | def display(): 192 | glClearColor(0.0, 0.0, 0.0, 0.0) 193 | glClear(GL_COLOR_BUFFER_BIT) 194 | 195 | glUseProgram(theProgram) 196 | 197 | glUniform2f(offsetUniform, 1.5, 0.5) 198 | 199 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 200 | glEnableVertexAttribArray(0) 201 | glEnableVertexAttribArray(1) 202 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 203 | # a ctype void pointer must be used to pass in the offset into the bound GL_ARRAY_BUFFER 204 | # also note that python's underlying float type is usally 64-bit, but 205 | # we have specified that our vertex array contains float32 data. 206 | colorOffset = c_void_p(vertexDim*nVertices*4) 207 | glVertexAttribPointer(1, vertexDim, GL_FLOAT, GL_FALSE, 0, colorOffset) 208 | 209 | glDrawArrays(GL_TRIANGLES, 0, nVertices) 210 | 211 | glDisableVertexAttribArray(0) 212 | glDisableVertexAttribArray(1) 213 | glUseProgram(0) 214 | 215 | glutSwapBuffers() 216 | glutPostRedisplay() 217 | 218 | # keyboard input handler: exits the program if 'esc' is pressed 219 | def keyboard(key, x, y): 220 | if ord(key) == 27: # ord() is needed to get the keycode 221 | glutLeaveMainLoop() 222 | return 223 | 224 | # Called whenever the window's size changes (including once when the program starts) 225 | def reshape(w, h): 226 | global perspectiveMatrix 227 | perspectiveMatrix[0] = fFrustumScale / (w / float(h)) 228 | perspectiveMatrix[5] = fFrustumScale 229 | 230 | glUseProgram(theProgram) 231 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 232 | glUseProgram(0) 233 | 234 | glViewport(0, 0, w, h) 235 | 236 | # The main function 237 | def main(): 238 | glutInit() 239 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 240 | glutInitDisplayMode (displayMode) 241 | 242 | width = 500; 243 | height = 500; 244 | glutInitWindowSize (width, height) 245 | 246 | glutInitWindowPosition (300, 200) 247 | 248 | window = glutCreateWindow("Tutorial Window") 249 | 250 | init() 251 | glutDisplayFunc(display) 252 | glutReshapeFunc(reshape) 253 | glutKeyboardFunc(keyboard) 254 | 255 | glutMainLoop(); 256 | 257 | if __name__ == '__main__': 258 | main() 259 | -------------------------------------------------------------------------------- /Tut 04 Objects at Rest/AspectRatio_modified.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from AspectRatio.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | import numpy as np 9 | from framework import * 10 | 11 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 12 | # Note that this must be a numpy array, since as of 13 | # 170111 support for lists has not been implemented. 14 | vertexData = np.array( 15 | [0.25, 0.25, -1.25, 1.0, 16 | 0.25, -0.25, -1.25, 1.0, 17 | -0.25, 0.25, -1.25, 1.0, 18 | 19 | 0.25, -0.25, -1.25, 1.0, 20 | -0.25, -0.25, -1.25, 1.0, 21 | -0.25, 0.25, -1.25, 1.0, 22 | 23 | 0.25, 0.25, -2.75, 1.0, 24 | -0.25, 0.25, -2.75, 1.0, 25 | 0.25, -0.25, -2.75, 1.0, 26 | 27 | 0.25, -0.25, -2.75, 1.0, 28 | -0.25, 0.25, -2.75, 1.0, 29 | -0.25, -0.25, -2.75, 1.0, 30 | 31 | -0.25, 0.25, -1.25, 1.0, 32 | -0.25, -0.25, -1.25, 1.0, 33 | -0.25, -0.25, -2.75, 1.0, 34 | 35 | -0.25, 0.25, -1.25, 1.0, 36 | -0.25, -0.25, -2.75, 1.0, 37 | -0.25, 0.25, -2.75, 1.0, 38 | 39 | 0.25, 0.25, -1.25, 1.0, 40 | 0.25, -0.25, -2.75, 1.0, 41 | 0.25, -0.25, -1.25, 1.0, 42 | 43 | 0.25, 0.25, -1.25, 1.0, 44 | 0.25, 0.25, -2.75, 1.0, 45 | 0.25, -0.25, -2.75, 1.0, 46 | 47 | 0.25, 0.25, -2.75, 1.0, 48 | 0.25, 0.25, -1.25, 1.0, 49 | -0.25, 0.25, -1.25, 1.0, 50 | 51 | 0.25, 0.25, -2.75, 1.0, 52 | -0.25, 0.25, -1.25, 1.0, 53 | -0.25, 0.25, -2.75, 1.0, 54 | 55 | 0.25, -0.25, -2.75, 1.0, 56 | -0.25, -0.25, -1.25, 1.0, 57 | 0.25, -0.25, -1.25, 1.0, 58 | 59 | 0.25, -0.25, -2.75, 1.0, 60 | -0.25, -0.25, -2.75, 1.0, 61 | -0.25, -0.25, -1.25, 1.0, 62 | 63 | 64 | 0.0, 0.0, 1.0, 1.0, 65 | 0.0, 0.0, 1.0, 1.0, 66 | 0.0, 0.0, 1.0, 1.0, 67 | 68 | 0.0, 0.0, 1.0, 1.0, 69 | 0.0, 0.0, 1.0, 1.0, 70 | 0.0, 0.0, 1.0, 1.0, 71 | 72 | 0.8, 0.8, 0.8, 1.0, 73 | 0.8, 0.8, 0.8, 1.0, 74 | 0.8, 0.8, 0.8, 1.0, 75 | 76 | 0.8, 0.8, 0.8, 1.0, 77 | 0.8, 0.8, 0.8, 1.0, 78 | 0.8, 0.8, 0.8, 1.0, 79 | 80 | 0.0, 1.0, 0.0, 1.0, 81 | 0.0, 1.0, 0.0, 1.0, 82 | 0.0, 1.0, 0.0, 1.0, 83 | 84 | 0.0, 1.0, 0.0, 1.0, 85 | 0.0, 1.0, 0.0, 1.0, 86 | 0.0, 1.0, 0.0, 1.0, 87 | 88 | 0.5, 0.5, 0.0, 1.0, 89 | 0.5, 0.5, 0.0, 1.0, 90 | 0.5, 0.5, 0.0, 1.0, 91 | 92 | 0.5, 0.5, 0.0, 1.0, 93 | 0.5, 0.5, 0.0, 1.0, 94 | 0.5, 0.5, 0.0, 1.0, 95 | 96 | 1.0, 0.0, 0.0, 1.0, 97 | 1.0, 0.0, 0.0, 1.0, 98 | 1.0, 0.0, 0.0, 1.0, 99 | 100 | 1.0, 0.0, 0.0, 1.0, 101 | 1.0, 0.0, 0.0, 1.0, 102 | 1.0, 0.0, 0.0, 1.0, 103 | 104 | 0.0, 1.0, 1.0, 1.0, 105 | 0.0, 1.0, 1.0, 1.0, 106 | 0.0, 1.0, 1.0, 1.0, 107 | 108 | 0.0, 1.0, 1.0, 1.0, 109 | 0.0, 1.0, 1.0, 1.0, 110 | 0.0, 1.0, 1.0, 1.0], 111 | dtype='float32' 112 | ) 113 | 114 | vertexDim = 4 115 | nVertices = 12*3 116 | 117 | # Global variable to represent the compiled shader program, written in GLSL 118 | theProgram = None 119 | 120 | # Global variable to represent the buffer that will hold the position vectors 121 | vertexBufferObject = None 122 | 123 | # Global variables to store the location of the shader's uniform variables 124 | offsetUniform = None 125 | perspectiveMatrixUnif = None 126 | 127 | # Global display variables 128 | perspectiveMatrix = None 129 | fFrustumScale = 1 130 | 131 | # Set up the list of shaders, and call functions to compile them 132 | def initializeProgram(): 133 | shaderList = [] 134 | 135 | shaderList.append(loadShader(GL_VERTEX_SHADER, "MatrixPerspective.vert")) 136 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "StandardColors.frag")) 137 | 138 | global theProgram 139 | theProgram = createProgram(shaderList) 140 | 141 | for shader in shaderList: 142 | glDeleteShader(shader) 143 | 144 | global offsetUniform 145 | offsetUniform = glGetUniformLocation(theProgram, "offset") 146 | 147 | global perspectiveMatrixUnif 148 | perspectiveMatrixUnif = glGetUniformLocation(theProgram, "perspectiveMatrix") 149 | 150 | fzNear = 0.5 151 | fzFar = 3.0 152 | 153 | global perspectiveMatrix 154 | perspectiveMatrix = np.zeros(16, dtype='float32') # note type 155 | perspectiveMatrix[0] = fFrustumScale 156 | perspectiveMatrix[5] = fFrustumScale 157 | perspectiveMatrix[10] = (fzFar + fzNear) / (fzNear - fzFar) 158 | perspectiveMatrix[14] = (2 * fzFar * fzNear) / (fzNear - fzFar) 159 | perspectiveMatrix[11] = -1.0 160 | 161 | glUseProgram(theProgram) 162 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 163 | glUseProgram(0) 164 | 165 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 166 | def initializeVertexBuffer(): 167 | global vertexBufferObject 168 | vertexBufferObject = glGenBuffers(1) 169 | 170 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 171 | glBufferData( # PyOpenGL allows for the omission of the size parameter 172 | GL_ARRAY_BUFFER, 173 | vertexData, 174 | GL_STREAM_DRAW 175 | ) 176 | glBindBuffer(GL_ARRAY_BUFFER, 0) 177 | 178 | # Initialize the OpenGL environment 179 | def init(): 180 | initializeProgram() 181 | initializeVertexBuffer() 182 | glBindVertexArray(glGenVertexArrays(1)) 183 | 184 | glEnable(GL_CULL_FACE) 185 | glCullFace(GL_BACK) 186 | glFrontFace(GL_CW) 187 | 188 | # Called to update the display. 189 | # Because we are using double-buffering, glutSwapBuffers is called at the end 190 | # to write the rendered buffer to the display. 191 | def display(): 192 | glClearColor(0.0, 0.0, 0.0, 0.0) 193 | glClear(GL_COLOR_BUFFER_BIT) 194 | 195 | glUseProgram(theProgram) 196 | 197 | #glUniform2f(offsetUniform, 0, 0) 198 | 199 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 200 | glEnableVertexAttribArray(0) 201 | glEnableVertexAttribArray(1) 202 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 203 | # a ctype void pointer must be used to pass in the offset into the bound GL_ARRAY_BUFFER 204 | # also note that python's underlying float type is usally 64-bit, but 205 | # we have specified that our vertex array contains float32 data. 206 | colorOffset = c_void_p(vertexDim*nVertices*4) 207 | glVertexAttribPointer(1, vertexDim, GL_FLOAT, GL_FALSE, 0, colorOffset) 208 | 209 | glDrawArrays(GL_TRIANGLES, 0, nVertices) 210 | 211 | glDisableVertexAttribArray(0) 212 | glDisableVertexAttribArray(1) 213 | glUseProgram(0) 214 | 215 | glutSwapBuffers() 216 | glutPostRedisplay() 217 | 218 | # keyboard input handler: exits the program if 'esc' is pressed 219 | def keyboard(key, x, y): 220 | if ord(key) == 27: # ord() is needed to get the keycode 221 | glutLeaveMainLoop() 222 | return 223 | 224 | def mouse(button, state, x, y): 225 | # set offsets so center of window is 0, 0 226 | w = glutGet(GLUT_WINDOW_WIDTH) 227 | h = glutGet(GLUT_WINDOW_HEIGHT) 228 | xOffset = (x - (w/2.0)) / (w/2.0) 229 | yOffset = -(y - (h/2.0)) / (h/2.0) 230 | 231 | print (xOffset, yOffset) 232 | 233 | glUseProgram(theProgram) 234 | glUniform2f(offsetUniform, xOffset, yOffset) 235 | glUseProgram(0) 236 | 237 | 238 | # Called whenever the window's size changes (including once when the program starts) 239 | def reshape(w, h): 240 | global perspectiveMatrix 241 | perspectiveMatrix[0] = fFrustumScale / (w / float(h)) 242 | perspectiveMatrix[5] = fFrustumScale 243 | 244 | glUseProgram(theProgram) 245 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 246 | glUseProgram(0) 247 | 248 | glViewport(0, 0, w, h) 249 | 250 | # The main function 251 | def main(): 252 | glutInit() 253 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 254 | glutInitDisplayMode (displayMode) 255 | 256 | width = 500; 257 | height = 500; 258 | glutInitWindowSize (width, height) 259 | 260 | glutInitWindowPosition (300, 200) 261 | 262 | window = glutCreateWindow("Tutorial Window") 263 | 264 | init() 265 | glutDisplayFunc(display) 266 | glutReshapeFunc(reshape) 267 | glutKeyboardFunc(keyboard) 268 | glutMouseFunc(mouse) 269 | 270 | glutMainLoop(); 271 | 272 | if __name__ == '__main__': 273 | main() 274 | -------------------------------------------------------------------------------- /Tut 04 Objects at Rest/MatrixPerspective.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from MatrixPerspective.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | import numpy as np 9 | from framework import * 10 | 11 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 12 | # Note that this must be a numpy array, since as of 13 | # 170111 support for lists has not been implemented. 14 | vertexData = np.array( 15 | [0.25, 0.25, -1.25, 1.0, 16 | 0.25, -0.25, -1.25, 1.0, 17 | -0.25, 0.25, -1.25, 1.0, 18 | 19 | 0.25, -0.25, -1.25, 1.0, 20 | -0.25, -0.25, -1.25, 1.0, 21 | -0.25, 0.25, -1.25, 1.0, 22 | 23 | 0.25, 0.25, -2.75, 1.0, 24 | -0.25, 0.25, -2.75, 1.0, 25 | 0.25, -0.25, -2.75, 1.0, 26 | 27 | 0.25, -0.25, -2.75, 1.0, 28 | -0.25, 0.25, -2.75, 1.0, 29 | -0.25, -0.25, -2.75, 1.0, 30 | 31 | -0.25, 0.25, -1.25, 1.0, 32 | -0.25, -0.25, -1.25, 1.0, 33 | -0.25, -0.25, -2.75, 1.0, 34 | 35 | -0.25, 0.25, -1.25, 1.0, 36 | -0.25, -0.25, -2.75, 1.0, 37 | -0.25, 0.25, -2.75, 1.0, 38 | 39 | 0.25, 0.25, -1.25, 1.0, 40 | 0.25, -0.25, -2.75, 1.0, 41 | 0.25, -0.25, -1.25, 1.0, 42 | 43 | 0.25, 0.25, -1.25, 1.0, 44 | 0.25, 0.25, -2.75, 1.0, 45 | 0.25, -0.25, -2.75, 1.0, 46 | 47 | 0.25, 0.25, -2.75, 1.0, 48 | 0.25, 0.25, -1.25, 1.0, 49 | -0.25, 0.25, -1.25, 1.0, 50 | 51 | 0.25, 0.25, -2.75, 1.0, 52 | -0.25, 0.25, -1.25, 1.0, 53 | -0.25, 0.25, -2.75, 1.0, 54 | 55 | 0.25, -0.25, -2.75, 1.0, 56 | -0.25, -0.25, -1.25, 1.0, 57 | 0.25, -0.25, -1.25, 1.0, 58 | 59 | 0.25, -0.25, -2.75, 1.0, 60 | -0.25, -0.25, -2.75, 1.0, 61 | -0.25, -0.25, -1.25, 1.0, 62 | 63 | 64 | 0.0, 0.0, 1.0, 1.0, 65 | 0.0, 0.0, 1.0, 1.0, 66 | 0.0, 0.0, 1.0, 1.0, 67 | 68 | 0.0, 0.0, 1.0, 1.0, 69 | 0.0, 0.0, 1.0, 1.0, 70 | 0.0, 0.0, 1.0, 1.0, 71 | 72 | 0.8, 0.8, 0.8, 1.0, 73 | 0.8, 0.8, 0.8, 1.0, 74 | 0.8, 0.8, 0.8, 1.0, 75 | 76 | 0.8, 0.8, 0.8, 1.0, 77 | 0.8, 0.8, 0.8, 1.0, 78 | 0.8, 0.8, 0.8, 1.0, 79 | 80 | 0.0, 1.0, 0.0, 1.0, 81 | 0.0, 1.0, 0.0, 1.0, 82 | 0.0, 1.0, 0.0, 1.0, 83 | 84 | 0.0, 1.0, 0.0, 1.0, 85 | 0.0, 1.0, 0.0, 1.0, 86 | 0.0, 1.0, 0.0, 1.0, 87 | 88 | 0.5, 0.5, 0.0, 1.0, 89 | 0.5, 0.5, 0.0, 1.0, 90 | 0.5, 0.5, 0.0, 1.0, 91 | 92 | 0.5, 0.5, 0.0, 1.0, 93 | 0.5, 0.5, 0.0, 1.0, 94 | 0.5, 0.5, 0.0, 1.0, 95 | 96 | 1.0, 0.0, 0.0, 1.0, 97 | 1.0, 0.0, 0.0, 1.0, 98 | 1.0, 0.0, 0.0, 1.0, 99 | 100 | 1.0, 0.0, 0.0, 1.0, 101 | 1.0, 0.0, 0.0, 1.0, 102 | 1.0, 0.0, 0.0, 1.0, 103 | 104 | 0.0, 1.0, 1.0, 1.0, 105 | 0.0, 1.0, 1.0, 1.0, 106 | 0.0, 1.0, 1.0, 1.0, 107 | 108 | 0.0, 1.0, 1.0, 1.0, 109 | 0.0, 1.0, 1.0, 1.0, 110 | 0.0, 1.0, 1.0, 1.0], 111 | dtype='float32' 112 | ) 113 | 114 | vertexDim = 4 115 | nVertices = 12*3 116 | 117 | # Global variable to represent the compiled shader program, written in GLSL 118 | theProgram = None 119 | 120 | # Global variable to represent the buffer that will hold the position vectors 121 | vertexBufferObject = None 122 | 123 | # Global variables to store the location of the shader's uniform variables 124 | offsetUniform = None 125 | 126 | 127 | # Set up the list of shaders, and call functions to compile them 128 | def initializeProgram(): 129 | shaderList = [] 130 | 131 | shaderList.append(loadShader(GL_VERTEX_SHADER, "MatrixPerspective.vert")) 132 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "StandardColors.frag")) 133 | 134 | global theProgram 135 | theProgram = createProgram(shaderList) 136 | 137 | for shader in shaderList: 138 | glDeleteShader(shader) 139 | 140 | global offsetUniform 141 | offsetUniform = glGetUniformLocation(theProgram, "offset") 142 | 143 | perspectiveMatrixUnif = glGetUniformLocation(theProgram, "perspectiveMatrix") 144 | 145 | fFrustumScale = 1.0 146 | fzNear = 0.5 147 | fzFar = 3.0 148 | 149 | theMatrix = np.zeros(16, dtype='float32') # note type 150 | theMatrix[0] = fFrustumScale 151 | theMatrix[5] = fFrustumScale 152 | theMatrix[10] = (fzFar + fzNear) / (fzNear - fzFar) 153 | theMatrix[14] = (2 * fzFar * fzNear) / (fzNear - fzFar) 154 | theMatrix[11] = -1.0 155 | 156 | glUseProgram(theProgram) 157 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, theMatrix) 158 | glUseProgram(0) 159 | 160 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 161 | def initializeVertexBuffer(): 162 | global vertexBufferObject 163 | vertexBufferObject = glGenBuffers(1) 164 | 165 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 166 | glBufferData( # PyOpenGL allows for the omission of the size parameter 167 | GL_ARRAY_BUFFER, 168 | vertexData, 169 | GL_STREAM_DRAW 170 | ) 171 | glBindBuffer(GL_ARRAY_BUFFER, 0) 172 | 173 | # Initialize the OpenGL environment 174 | def init(): 175 | initializeProgram() 176 | initializeVertexBuffer() 177 | glBindVertexArray(glGenVertexArrays(1)) 178 | 179 | glEnable(GL_CULL_FACE) 180 | glCullFace(GL_BACK) 181 | glFrontFace(GL_CW) 182 | 183 | # Called to update the display. 184 | # Because we are using double-buffering, glutSwapBuffers is called at the end 185 | # to write the rendered buffer to the display. 186 | def display(): 187 | glClearColor(0.0, 0.0, 0.0, 0.0) 188 | glClear(GL_COLOR_BUFFER_BIT) 189 | 190 | glUseProgram(theProgram) 191 | 192 | glUniform2f(offsetUniform, 0.5, 0.5) 193 | 194 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 195 | glEnableVertexAttribArray(0) 196 | glEnableVertexAttribArray(1) 197 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 198 | # a ctype void pointer must be used to pass in the offset into the bound GL_ARRAY_BUFFER 199 | # also note that python's underlying float type is usally 64-bit, but 200 | # we have specified that our vertex array contains float32 data. 201 | colorOffset = c_void_p(vertexDim*nVertices*4) 202 | glVertexAttribPointer(1, vertexDim, GL_FLOAT, GL_FALSE, 0, colorOffset) 203 | 204 | glDrawArrays(GL_TRIANGLES, 0, nVertices) 205 | 206 | glDisableVertexAttribArray(0) 207 | glDisableVertexAttribArray(1) 208 | glUseProgram(0) 209 | 210 | glutSwapBuffers() 211 | glutPostRedisplay() 212 | 213 | # keyboard input handler: exits the program if 'esc' is pressed 214 | def keyboard(key, x, y): 215 | if ord(key) == 27: # ord() is needed to get the keycode 216 | glutLeaveMainLoop() 217 | return 218 | 219 | # Called whenever the window's size changes (including once when the program starts) 220 | def reshape(w, h): 221 | glViewport(0, 0, w, h) 222 | 223 | # The main function 224 | def main(): 225 | glutInit() 226 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 227 | glutInitDisplayMode (displayMode) 228 | 229 | width = 500; 230 | height = 500; 231 | glutInitWindowSize (width, height) 232 | 233 | glutInitWindowPosition (300, 200) 234 | 235 | window = glutCreateWindow("Tutorial Window") 236 | 237 | init() 238 | glutDisplayFunc(display) 239 | glutReshapeFunc(reshape) 240 | glutKeyboardFunc(keyboard) 241 | 242 | glutMainLoop(); 243 | 244 | if __name__ == '__main__': 245 | main() 246 | -------------------------------------------------------------------------------- /Tut 04 Objects at Rest/OrthoCube.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from OrthoCube.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | import numpy as np 9 | from framework import * 10 | 11 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 12 | # Note that this must be a numpy array, since as of 13 | # 170111 support for lists has not been implemented. 14 | vertexPositions = np.array( 15 | [0.25, 0.25, 0.75, 1.0, 16 | 0.25, -0.25, 0.75, 1.0, 17 | -0.25, 0.25, 0.75, 1.0, 18 | 19 | 0.25, -0.25, 0.75, 1.0, 20 | -0.25, -0.25, 0.75, 1.0, 21 | -0.25, 0.25, 0.75, 1.0, 22 | 23 | 0.25, 0.25, -0.75, 1.0, 24 | -0.25, 0.25, -0.75, 1.0, 25 | 0.25, -0.25, -0.75, 1.0, 26 | 27 | 0.25, -0.25, -0.75, 1.0, 28 | -0.25, 0.25, -0.75, 1.0, 29 | -0.25, -0.25, -0.75, 1.0, 30 | 31 | -0.25, 0.25, 0.75, 1.0, 32 | -0.25, -0.25, 0.75, 1.0, 33 | -0.25, -0.25, -0.75, 1.0, 34 | 35 | -0.25, 0.25, 0.75, 1.0, 36 | -0.25, -0.25, -0.75, 1.0, 37 | -0.25, 0.25, -0.75, 1.0, 38 | 39 | 0.25, 0.25, 0.75, 1.0, 40 | 0.25, -0.25, -0.75, 1.0, 41 | 0.25, -0.25, 0.75, 1.0, 42 | 43 | 0.25, 0.25, 0.75, 1.0, 44 | 0.25, 0.25, -0.75, 1.0, 45 | 0.25, -0.25, -0.75, 1.0, 46 | 47 | 0.25, 0.25, -0.75, 1.0, 48 | 0.25, 0.25, 0.75, 1.0, 49 | -0.25, 0.25, 0.75, 1.0, 50 | 51 | 0.25, 0.25, -0.75, 1.0, 52 | -0.25, 0.25, 0.75, 1.0, 53 | -0.25, 0.25, -0.75, 1.0, 54 | 55 | 0.25, -0.25, -0.75, 1.0, 56 | -0.25, -0.25, 0.75, 1.0, 57 | 0.25, -0.25, 0.75, 1.0, 58 | 59 | 0.25, -0.25, -0.75, 1.0, 60 | -0.25, -0.25, -0.75, 1.0, 61 | -0.25, -0.25, 0.75, 1.0, 62 | 63 | 64 | 65 | 66 | 0.0, 0.0, 1.0, 1.0, 67 | 0.0, 0.0, 1.0, 1.0, 68 | 0.0, 0.0, 1.0, 1.0, 69 | 70 | 0.0, 0.0, 1.0, 1.0, 71 | 0.0, 0.0, 1.0, 1.0, 72 | 0.0, 0.0, 1.0, 1.0, 73 | 74 | 0.8, 0.8, 0.8, 1.0, 75 | 0.8, 0.8, 0.8, 1.0, 76 | 0.8, 0.8, 0.8, 1.0, 77 | 78 | 0.8, 0.8, 0.8, 1.0, 79 | 0.8, 0.8, 0.8, 1.0, 80 | 0.8, 0.8, 0.8, 1.0, 81 | 82 | 0.0, 1.0, 0.0, 1.0, 83 | 0.0, 1.0, 0.0, 1.0, 84 | 0.0, 1.0, 0.0, 1.0, 85 | 86 | 0.0, 1.0, 0.0, 1.0, 87 | 0.0, 1.0, 0.0, 1.0, 88 | 0.0, 1.0, 0.0, 1.0, 89 | 90 | 0.5, 0.5, 0.0, 1.0, 91 | 0.5, 0.5, 0.0, 1.0, 92 | 0.5, 0.5, 0.0, 1.0, 93 | 94 | 0.5, 0.5, 0.0, 1.0, 95 | 0.5, 0.5, 0.0, 1.0, 96 | 0.5, 0.5, 0.0, 1.0, 97 | 98 | 1.0, 0.0, 0.0, 1.0, 99 | 1.0, 0.0, 0.0, 1.0, 100 | 1.0, 0.0, 0.0, 1.0, 101 | 102 | 1.0, 0.0, 0.0, 1.0, 103 | 1.0, 0.0, 0.0, 1.0, 104 | 1.0, 0.0, 0.0, 1.0, 105 | 106 | 0.0, 1.0, 1.0, 1.0, 107 | 0.0, 1.0, 1.0, 1.0, 108 | 0.0, 1.0, 1.0, 1.0, 109 | 110 | 0.0, 1.0, 1.0, 1.0, 111 | 0.0, 1.0, 1.0, 1.0, 112 | 0.0, 1.0, 1.0, 1.0], 113 | dtype='float32' 114 | ) 115 | 116 | vertexDim = 4 117 | nVertices = 12*3 118 | 119 | # Global variable to represent the compiled shader program, written in GLSL 120 | theProgram = None 121 | 122 | # Global variable to represent the buffer that will hold the position vectors 123 | positionBufferObject = None 124 | 125 | # Global variable to store the location of the shader's uniform variable "offset" 126 | offsetUniform = None 127 | 128 | # Set up the list of shaders, and call functions to compile them 129 | def initializeProgram(): 130 | shaderList = [] 131 | 132 | shaderList.append(loadShader(GL_VERTEX_SHADER, "OrthoWithOffset.vert")) 133 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "StandardColors.frag")) 134 | 135 | global theProgram 136 | theProgram = createProgram(shaderList) 137 | 138 | for shader in shaderList: 139 | glDeleteShader(shader) 140 | 141 | global offsetUniform 142 | offsetUniform = glGetUniformLocation(theProgram, "offset") 143 | 144 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 145 | def initializeVertexBuffer(): 146 | global positionBufferObject 147 | positionBufferObject = glGenBuffers(1) 148 | 149 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 150 | glBufferData( # PyOpenGL allows for the omission of the size parameter 151 | GL_ARRAY_BUFFER, 152 | vertexPositions, 153 | GL_STREAM_DRAW 154 | ) 155 | glBindBuffer(GL_ARRAY_BUFFER, 0) 156 | 157 | # Initialize the OpenGL environment 158 | def init(): 159 | initializeProgram() 160 | initializeVertexBuffer() 161 | glBindVertexArray(glGenVertexArrays(1)) 162 | 163 | glEnable(GL_CULL_FACE) 164 | glCullFace(GL_BACK) 165 | glFrontFace(GL_CW) 166 | 167 | # Called to update the display. 168 | # Because we are using double-buffering, glutSwapBuffers is called at the end 169 | # to write the rendered buffer to the display. 170 | def display(): 171 | glClearColor(0.0, 0.0, 0.0, 0.0) 172 | glClear(GL_COLOR_BUFFER_BIT) 173 | 174 | glUseProgram(theProgram) 175 | 176 | glUniform2f(offsetUniform, 0.5, 0.25) 177 | 178 | glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject) 179 | glEnableVertexAttribArray(0) 180 | glEnableVertexAttribArray(1) 181 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 182 | # a ctype void pointer must be used to pass in the offset into the bound GL_ARRAY_BUFFER 183 | # also note that python's underlying float type is usally 64-bit, but 184 | # we have specified that our vertex array contains float32 data. 185 | colorOffset = c_void_p(vertexDim*nVertices*4) 186 | glVertexAttribPointer(1, vertexDim, GL_FLOAT, GL_FALSE, 0, colorOffset) 187 | 188 | glDrawArrays(GL_TRIANGLES, 0, nVertices) 189 | 190 | glDisableVertexAttribArray(0) 191 | glDisableVertexAttribArray(1) 192 | glUseProgram(0) 193 | 194 | glutSwapBuffers() 195 | glutPostRedisplay() 196 | 197 | # keyboard input handler: exits the program if 'esc' is pressed 198 | def keyboard(key, x, y): 199 | if ord(key) == 27: # ord() is needed to get the keycode 200 | glutLeaveMainLoop() 201 | return 202 | 203 | # Called whenever the window's size changes (including once when the program starts) 204 | def reshape(w, h): 205 | glViewport(0, 0, w, h) 206 | 207 | # The main function 208 | def main(): 209 | glutInit() 210 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 211 | glutInitDisplayMode (displayMode) 212 | 213 | width = 500; 214 | height = 500; 215 | glutInitWindowSize (width, height) 216 | 217 | glutInitWindowPosition (300, 200) 218 | 219 | window = glutCreateWindow("Tutorial Window") 220 | 221 | init() 222 | glutDisplayFunc(display) 223 | glutReshapeFunc(reshape) 224 | glutKeyboardFunc(keyboard) 225 | 226 | glutMainLoop(); 227 | 228 | if __name__ == '__main__': 229 | main() 230 | -------------------------------------------------------------------------------- /Tut 04 Objects at Rest/ShaderPerspective.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from ShaderPerspective.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | import numpy as np 9 | from framework import * 10 | 11 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 12 | # Note that this must be a numpy array, since as of 13 | # 170111 support for lists has not been implemented. 14 | vertexData = np.array( 15 | [0.25, 0.25, -1.25, 1.0, 16 | 0.25, -0.25, -1.25, 1.0, 17 | -0.25, 0.25, -1.25, 1.0, 18 | 19 | 0.25, -0.25, -1.25, 1.0, 20 | -0.25, -0.25, -1.25, 1.0, 21 | -0.25, 0.25, -1.25, 1.0, 22 | 23 | 0.25, 0.25, -2.75, 1.0, 24 | -0.25, 0.25, -2.75, 1.0, 25 | 0.25, -0.25, -2.75, 1.0, 26 | 27 | 0.25, -0.25, -2.75, 1.0, 28 | -0.25, 0.25, -2.75, 1.0, 29 | -0.25, -0.25, -2.75, 1.0, 30 | 31 | -0.25, 0.25, -1.25, 1.0, 32 | -0.25, -0.25, -1.25, 1.0, 33 | -0.25, -0.25, -2.75, 1.0, 34 | 35 | -0.25, 0.25, -1.25, 1.0, 36 | -0.25, -0.25, -2.75, 1.0, 37 | -0.25, 0.25, -2.75, 1.0, 38 | 39 | 0.25, 0.25, -1.25, 1.0, 40 | 0.25, -0.25, -2.75, 1.0, 41 | 0.25, -0.25, -1.25, 1.0, 42 | 43 | 0.25, 0.25, -1.25, 1.0, 44 | 0.25, 0.25, -2.75, 1.0, 45 | 0.25, -0.25, -2.75, 1.0, 46 | 47 | 0.25, 0.25, -2.75, 1.0, 48 | 0.25, 0.25, -1.25, 1.0, 49 | -0.25, 0.25, -1.25, 1.0, 50 | 51 | 0.25, 0.25, -2.75, 1.0, 52 | -0.25, 0.25, -1.25, 1.0, 53 | -0.25, 0.25, -2.75, 1.0, 54 | 55 | 0.25, -0.25, -2.75, 1.0, 56 | -0.25, -0.25, -1.25, 1.0, 57 | 0.25, -0.25, -1.25, 1.0, 58 | 59 | 0.25, -0.25, -2.75, 1.0, 60 | -0.25, -0.25, -2.75, 1.0, 61 | -0.25, -0.25, -1.25, 1.0, 62 | 63 | 64 | 0.0, 0.0, 1.0, 1.0, 65 | 0.0, 0.0, 1.0, 1.0, 66 | 0.0, 0.0, 1.0, 1.0, 67 | 68 | 0.0, 0.0, 1.0, 1.0, 69 | 0.0, 0.0, 1.0, 1.0, 70 | 0.0, 0.0, 1.0, 1.0, 71 | 72 | 0.8, 0.8, 0.8, 1.0, 73 | 0.8, 0.8, 0.8, 1.0, 74 | 0.8, 0.8, 0.8, 1.0, 75 | 76 | 0.8, 0.8, 0.8, 1.0, 77 | 0.8, 0.8, 0.8, 1.0, 78 | 0.8, 0.8, 0.8, 1.0, 79 | 80 | 0.0, 1.0, 0.0, 1.0, 81 | 0.0, 1.0, 0.0, 1.0, 82 | 0.0, 1.0, 0.0, 1.0, 83 | 84 | 0.0, 1.0, 0.0, 1.0, 85 | 0.0, 1.0, 0.0, 1.0, 86 | 0.0, 1.0, 0.0, 1.0, 87 | 88 | 0.5, 0.5, 0.0, 1.0, 89 | 0.5, 0.5, 0.0, 1.0, 90 | 0.5, 0.5, 0.0, 1.0, 91 | 92 | 0.5, 0.5, 0.0, 1.0, 93 | 0.5, 0.5, 0.0, 1.0, 94 | 0.5, 0.5, 0.0, 1.0, 95 | 96 | 1.0, 0.0, 0.0, 1.0, 97 | 1.0, 0.0, 0.0, 1.0, 98 | 1.0, 0.0, 0.0, 1.0, 99 | 100 | 1.0, 0.0, 0.0, 1.0, 101 | 1.0, 0.0, 0.0, 1.0, 102 | 1.0, 0.0, 0.0, 1.0, 103 | 104 | 0.0, 1.0, 1.0, 1.0, 105 | 0.0, 1.0, 1.0, 1.0, 106 | 0.0, 1.0, 1.0, 1.0, 107 | 108 | 0.0, 1.0, 1.0, 1.0, 109 | 0.0, 1.0, 1.0, 1.0, 110 | 0.0, 1.0, 1.0, 1.0], 111 | dtype='float32' 112 | ) 113 | 114 | vertexDim = 4 115 | nVertices = 12*3 116 | 117 | # Global variable to represent the compiled shader program, written in GLSL 118 | theProgram = None 119 | 120 | # Global variable to represent the buffer that will hold the position vectors 121 | vertexBufferObject = None 122 | 123 | # Global variable to store the location of the shader's uniform variables 124 | offsetUniform = None 125 | 126 | # Set up the list of shaders, and call functions to compile them 127 | def initializeProgram(): 128 | shaderList = [] 129 | 130 | shaderList.append(loadShader(GL_VERTEX_SHADER, "ManualPerspective.vert")) 131 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "StandardColors.frag")) 132 | 133 | global theProgram 134 | theProgram = createProgram(shaderList) 135 | 136 | for shader in shaderList: 137 | glDeleteShader(shader) 138 | 139 | global offsetUniform 140 | offsetUniform = glGetUniformLocation(theProgram, "offset") 141 | 142 | # note that these uniform variable holders do not need to be global, 143 | # since they are only set once in this program, in this function 144 | frustumScaleUnif = glGetUniformLocation(theProgram, "frustumScale") 145 | zNearUnif = glGetUniformLocation(theProgram, "zNear") 146 | zFarUnif = glGetUniformLocation(theProgram, "zFar") 147 | 148 | glUseProgram(theProgram) 149 | glUniform1f(frustumScaleUnif, 1.0) 150 | glUniform1f(zNearUnif, 1.0) 151 | glUniform1f(zFarUnif, 3.0) 152 | glUseProgram(0) 153 | 154 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 155 | def initializeVertexBuffer(): 156 | global vertexBufferObject 157 | vertexBufferObject = glGenBuffers(1) 158 | 159 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 160 | glBufferData( # PyOpenGL allows for the omission of the size parameter 161 | GL_ARRAY_BUFFER, 162 | vertexData, 163 | GL_STREAM_DRAW 164 | ) 165 | glBindBuffer(GL_ARRAY_BUFFER, 0) 166 | 167 | # Initialize the OpenGL environment 168 | def init(): 169 | initializeProgram() 170 | initializeVertexBuffer() 171 | glBindVertexArray(glGenVertexArrays(1)) 172 | 173 | glEnable(GL_CULL_FACE) 174 | glCullFace(GL_BACK) 175 | glFrontFace(GL_CW) 176 | 177 | # Called to update the display. 178 | # Because we are using double-buffering, glutSwapBuffers is called at the end 179 | # to write the rendered buffer to the display. 180 | def display(): 181 | glClearColor(0.0, 0.0, 0.0, 0.0) 182 | glClear(GL_COLOR_BUFFER_BIT) 183 | 184 | glUseProgram(theProgram) 185 | 186 | glUniform2f(offsetUniform, 0.5, 0.5) 187 | 188 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 189 | glEnableVertexAttribArray(0) 190 | glEnableVertexAttribArray(1) 191 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 192 | # a ctype void pointer must be used to pass in the offset into the bound GL_ARRAY_BUFFER 193 | # also note that python's underlying float type is usally 64-bit, but 194 | # we have specified that our vertex array contains float32 data. 195 | colorOffset = c_void_p(vertexDim*nVertices*4) 196 | glVertexAttribPointer(1, vertexDim, GL_FLOAT, GL_FALSE, 0, colorOffset) 197 | 198 | glDrawArrays(GL_TRIANGLES, 0, nVertices) 199 | 200 | glDisableVertexAttribArray(0) 201 | glDisableVertexAttribArray(1) 202 | glUseProgram(0) 203 | 204 | glutSwapBuffers() 205 | glutPostRedisplay() 206 | 207 | # keyboard input handler: exits the program if 'esc' is pressed 208 | def keyboard(key, x, y): 209 | if ord(key) == 27: # ord() is needed to get the keycode 210 | glutLeaveMainLoop() 211 | return 212 | 213 | # Called whenever the window's size changes (including once when the program starts) 214 | def reshape(w, h): 215 | glViewport(0, 0, w, h) 216 | 217 | # The main function 218 | def main(): 219 | glutInit() 220 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 221 | glutInitDisplayMode (displayMode) 222 | 223 | width = 500; 224 | height = 500; 225 | glutInitWindowSize (width, height) 226 | 227 | glutInitWindowPosition (300, 200) 228 | 229 | window = glutCreateWindow("Tutorial Window") 230 | 231 | init() 232 | glutDisplayFunc(display) 233 | glutReshapeFunc(reshape) 234 | glutKeyboardFunc(keyboard) 235 | 236 | glutMainLoop(); 237 | 238 | if __name__ == '__main__': 239 | main() 240 | -------------------------------------------------------------------------------- /Tut 04 Objects at Rest/data/ManualPerspective.vert: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | layout(location = 0) in vec4 position; 4 | layout(location = 1) in vec4 color; 5 | 6 | smooth out vec4 theColor; 7 | 8 | uniform vec2 offset; 9 | uniform float zNear; 10 | uniform float zFar; 11 | uniform float frustumScale; 12 | 13 | 14 | void main() 15 | { 16 | vec4 cameraPos = position + vec4(offset.x, offset.y, 0.0, 0.0); 17 | vec4 clipPos; 18 | 19 | clipPos.xy = cameraPos.xy * frustumScale; 20 | 21 | clipPos.z = cameraPos.z * (zNear + zFar) / (zNear - zFar); 22 | clipPos.z += 2 * zNear * zFar / (zNear - zFar); 23 | 24 | clipPos.w = -cameraPos.z; 25 | 26 | gl_Position = clipPos; 27 | theColor = color; 28 | } 29 | -------------------------------------------------------------------------------- /Tut 04 Objects at Rest/data/MatrixPerspective.vert: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | layout(location = 0) in vec4 position; 4 | layout(location = 1) in vec4 color; 5 | 6 | smooth out vec4 theColor; 7 | 8 | uniform vec2 offset; 9 | uniform mat4 perspectiveMatrix; 10 | 11 | void main() 12 | { 13 | vec4 cameraPos = position + vec4(offset.x, offset.y, 0.0, 0.0); 14 | 15 | gl_Position = perspectiveMatrix * cameraPos; 16 | theColor = color; 17 | } 18 | -------------------------------------------------------------------------------- /Tut 04 Objects at Rest/data/OrthoWithOffset.vert: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | layout(location = 0) in vec4 position; 4 | layout(location = 1) in vec4 color; 5 | 6 | smooth out vec4 theColor; 7 | 8 | uniform vec2 offset; 9 | 10 | void main() 11 | { 12 | gl_Position = position + vec4(offset.x, offset.y, 0.0, 0.0); 13 | theColor = color; 14 | } 15 | -------------------------------------------------------------------------------- /Tut 04 Objects at Rest/data/StandardColors.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | smooth in vec4 theColor; 4 | 5 | out vec4 outputColor; 6 | 7 | void main() 8 | { 9 | outputColor = theColor; 10 | } 11 | -------------------------------------------------------------------------------- /Tut 04 Objects at Rest/framework.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from framework.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | # 5 | # NB: Unlike in the framework.cpp organization, the main loop is contained 6 | # in the tutorial files, not in this framework file. Additionally, a copy of 7 | # this module file must exist in the same directory as the tutorial files 8 | # to be imported properly. 9 | 10 | from OpenGL.GLUT import * 11 | from OpenGL.GLU import * 12 | from OpenGL.GL import * 13 | import os 14 | import sys 15 | 16 | # Function that creates and compiles shaders according to the given type (a GL enum value) and 17 | # shader program (a file containing a GLSL program). 18 | def loadShader(shaderType, shaderFile): 19 | # check if file exists, get full path name 20 | strFilename = findFileOrThrow(shaderFile) 21 | shaderData = None 22 | with open(strFilename, 'r') as f: 23 | shaderData = f.read() 24 | 25 | shader = glCreateShader(shaderType) 26 | glShaderSource(shader, shaderData) # note that this is a simpler function call than in C 27 | 28 | # This shader compilation is more explicit than the one used in 29 | # framework.cpp, which relies on a glutil wrapper function. 30 | # This is made explicit here mainly to decrease dependence on pyOpenGL 31 | # utilities and wrappers, which docs caution may change in future versions. 32 | glCompileShader(shader) 33 | 34 | status = glGetShaderiv(shader, GL_COMPILE_STATUS) 35 | if status == GL_FALSE: 36 | # Note that getting the error log is much simpler in Python than in C/C++ 37 | # and does not require explicit handling of the string buffer 38 | strInfoLog = glGetShaderInforLog(shader) 39 | strShaderType = "" 40 | if shaderType is GL_VERTEX_SHADER: 41 | strShaderType = "vertex" 42 | elif shaderType is GL_GEOMETRY_SHADER: 43 | strShaderType = "geometry" 44 | elif shaderType is GL_FRAGMENT_SHADER: 45 | strShaderType = "fragment" 46 | 47 | print "Compilation failure for " + strShaderType + " shader:\n" + strInfoLog 48 | 49 | return shader 50 | 51 | # Function that accepts a list of shaders, compiles them, and returns a handle to the compiled program 52 | def createProgram(shaderList): 53 | program = glCreateProgram() 54 | 55 | for shader in shaderList: 56 | glAttachShader(program, shader) 57 | 58 | glLinkProgram(program) 59 | 60 | status = glGetProgramiv(program, GL_LINK_STATUS) 61 | if status == GL_FALSE: 62 | # Note that getting the error log is much simpler in Python than in C/C++ 63 | # and does not require explicit handling of the string buffer 64 | strInfoLog = glGetProgramInfoLog(program) 65 | print "Linker failure: \n" + strInfoLog 66 | 67 | for shader in shaderList: 68 | glDetachShader(program, shader) 69 | 70 | return program 71 | 72 | 73 | # Helper function to locate and open the target file (passed in as a string). 74 | # Returns the full path to the file as a string. 75 | def findFileOrThrow(strBasename): 76 | # Keep constant names in C-style convention, for readability 77 | # when comparing to C(/C++) code. 78 | LOCAL_FILE_DIR = "data" + os.sep 79 | GLOBAL_FILE_DIR = ".." + os.sep + "data" + os.sep 80 | 81 | strFilename = LOCAL_FILE_DIR + strBasename 82 | if os.path.isfile(strFilename): 83 | return strFilename 84 | 85 | strFilename = GLOBAL_FILE_DIR + strBasename 86 | if os.path.isfile(strFilename): 87 | return strFilename 88 | 89 | raise IOError('Could not find target file ' + strBasename) 90 | -------------------------------------------------------------------------------- /Tut 05 Objects in Depth/BaseVertexOverlap.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from BaseVertexOverlap.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | import numpy as np 9 | from framework import * 10 | from itertools import chain 11 | 12 | # Set some global constants. Naming scheme is unchanged to maintain 13 | # analogy to the C++ code. Note that because of the lack of #define macros 14 | # in python, the color values were input manually 15 | RIGHT_EXTENT = 0.8 16 | LEFT_EXTENT = -RIGHT_EXTENT 17 | TOP_EXTENT = 0.20 18 | MIDDLE_EXTENT = 0.0 19 | BOTTOM_EXTENT = -TOP_EXTENT 20 | FRONT_EXTENT = -1.25 21 | REAR_EXTENT = -1.75 22 | 23 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 24 | # Note that this must be a numpy array, since as of 25 | # 170111 support for lists has not been implemented. 26 | vertexData = np.array([ 27 | #Object 1 positions 28 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 29 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 30 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 31 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 32 | 33 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 34 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 35 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 36 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 37 | 38 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 39 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 40 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 41 | 42 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 43 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 44 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 45 | 46 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 47 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 48 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 49 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 50 | 51 | #Object 2 positions 52 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 53 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 54 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 55 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 56 | 57 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 58 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 59 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 60 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 61 | 62 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 63 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 64 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 65 | 66 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 67 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 68 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 69 | 70 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 71 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 72 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 73 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 74 | 75 | #Object 1 colors 76 | # GREEN_COLOR 77 | 0.75, 0.75, 1.0, 1.0, 78 | 0.75, 0.75, 1.0, 1.0, 79 | 0.75, 0.75, 1.0, 1.0, 80 | 0.75, 0.75, 1.0, 1.0, 81 | 82 | # BLUE_COLOR 83 | 0.0, 0.5, 0.0, 1.0, 84 | 0.0, 0.5, 0.0, 1.0, 85 | 0.0, 0.5, 0.0, 1.0, 86 | 0.0, 0.5, 0.0, 1.0, 87 | 88 | # RED_COLOR 89 | 1.0, 0.0, 0.0, 1.0, 90 | 1.0, 0.0, 0.0, 1.0, 91 | 1.0, 0.0, 0.0, 1.0, 92 | 93 | # GREY_COLOR 94 | 0.8, 0.8, 0.8, 1.0, 95 | 0.8, 0.8, 0.8, 1.0, 96 | 0.8, 0.8, 0.8, 1.0, 97 | 98 | # BROWN_COLOR 99 | 0.5, 0.5, 0.0, 1.0, 100 | 0.5, 0.5, 0.0, 1.0, 101 | 0.5, 0.5, 0.0, 1.0, 102 | 0.5, 0.5, 0.0, 1.0, 103 | 104 | #Object 2 colors 105 | # RED_COLOR 106 | 1.0, 0.0, 0.0, 1.0, 107 | 1.0, 0.0, 0.0, 1.0, 108 | 1.0, 0.0, 0.0, 1.0, 109 | 1.0, 0.0, 0.0, 1.0, 110 | 111 | # BROWN_COLOR 112 | 0.5, 0.5, 0.0, 1.0, 113 | 0.5, 0.5, 0.0, 1.0, 114 | 0.5, 0.5, 0.0, 1.0, 115 | 0.5, 0.5, 0.0, 1.0, 116 | 117 | # BLUE_COLOR 118 | 0.0, 0.5, 0.0, 1.0, 119 | 0.0, 0.5, 0.0, 1.0, 120 | 0.0, 0.5, 0.0, 1.0, 121 | 122 | # GREEN_COLOR 123 | 0.75, 0.75, 1.0, 1.0, 124 | 0.75, 0.75, 1.0, 1.0, 125 | 0.75, 0.75, 1.0, 1.0, 126 | 127 | # GREY_COLOR 128 | 0.8, 0.8, 0.8, 1.0, 129 | 0.8, 0.8, 0.8, 1.0, 130 | 0.8, 0.8, 0.8, 1.0, 131 | 0.8, 0.8, 0.8, 1.0], 132 | dtype='float32' 133 | ).flatten() # flatten the array into 1D 134 | 135 | indexData = np.array( 136 | [0, 2, 1, 137 | 3, 2, 0, 138 | 139 | 4, 5, 6, 140 | 6, 7, 4, 141 | 142 | 8, 9, 10, 143 | 11, 13, 12, 144 | 145 | 14, 16, 15, 146 | 17, 16, 14], 147 | dtype='uint16') 148 | 149 | vertexDim = 3 150 | colorDim = 4 151 | nVertices = 12*3 152 | 153 | # Global variable to represent the compiled shader program, written in GLSL 154 | theProgram = None 155 | 156 | # Global variable to represent the buffer that will hold the position vectors 157 | vertexBufferObject = None 158 | # Global variables to hold vertex array objects 159 | vao = None 160 | # Global variable to hold the position index buffer object 161 | indexBufferObject = None 162 | 163 | # Global variables to store the location of the shader's uniform variables 164 | offsetUniform = None 165 | perspectiveMatrixUnif = None 166 | 167 | # Global display variables 168 | perspectiveMatrix = None 169 | fFrustumScale = 1.0 170 | 171 | # Set up the list of shaders, and call functions to compile them 172 | def initializeProgram(): 173 | shaderList = [] 174 | 175 | shaderList.append(loadShader(GL_VERTEX_SHADER, "Standard.vert")) 176 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "Standard.frag")) 177 | 178 | global theProgram 179 | theProgram = createProgram(shaderList) 180 | 181 | for shader in shaderList: 182 | glDeleteShader(shader) 183 | 184 | global offsetUniform 185 | offsetUniform = glGetUniformLocation(theProgram, "offset") 186 | 187 | global perspectiveMatrixUnif 188 | perspectiveMatrixUnif = glGetUniformLocation(theProgram, "perspectiveMatrix") 189 | 190 | fzNear = 1.0 191 | fzFar = 3.0 192 | 193 | global perspectiveMatrix 194 | perspectiveMatrix = np.zeros(16, dtype='float32') # note type 195 | perspectiveMatrix[0] = fFrustumScale 196 | perspectiveMatrix[5] = fFrustumScale 197 | perspectiveMatrix[10] = (fzFar + fzNear) / (fzNear - fzFar) 198 | perspectiveMatrix[14] = (2 * fzFar * fzNear) / (fzNear - fzFar) 199 | perspectiveMatrix[11] = -1.0 200 | 201 | glUseProgram(theProgram) 202 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 203 | glUseProgram(0) 204 | 205 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 206 | def initializeVertexBuffer(): 207 | global vertexBufferObject, indexBufferObject 208 | vertexBufferObject = glGenBuffers(1) 209 | 210 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 211 | glBufferData( # PyOpenGL allows for the omission of the size parameter 212 | GL_ARRAY_BUFFER, 213 | vertexData, 214 | GL_STATIC_DRAW 215 | ) 216 | glBindBuffer(GL_ARRAY_BUFFER, 0) 217 | 218 | indexBufferObject = glGenBuffers(1) 219 | 220 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 221 | glBufferData( 222 | GL_ELEMENT_ARRAY_BUFFER, 223 | indexData, 224 | GL_STATIC_DRAW 225 | ) 226 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 227 | 228 | # Initialize the OpenGL environment 229 | def init(): 230 | initializeProgram() 231 | initializeVertexBuffer() 232 | 233 | global vao 234 | vao = glGenVertexArrays(1) 235 | glBindVertexArray(vao) 236 | 237 | sizeOfFloat = 4 # all our arrays are dtype='float32' 238 | colorDataOffset = c_void_p(vertexDim * nVertices * sizeOfFloat) 239 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 240 | glEnableVertexAttribArray(0) 241 | glEnableVertexAttribArray(1) 242 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 243 | glVertexAttribPointer(1, colorDim, GL_FLOAT, GL_FALSE, 0, colorDataOffset) 244 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 245 | 246 | glBindVertexArray(0) 247 | 248 | glEnable(GL_CULL_FACE) 249 | glCullFace(GL_BACK) 250 | glFrontFace(GL_CW) 251 | 252 | # Called to update the display. 253 | # Because we are using double-buffering, glutSwapBuffers is called at the end 254 | # to write the rendered buffer to the display. 255 | def display(): 256 | glClearColor(0.0, 0.0, 0.0, 0.0) 257 | glClear(GL_COLOR_BUFFER_BIT) 258 | 259 | glUseProgram(theProgram) 260 | 261 | glBindVertexArray(vao) 262 | 263 | glUniform3f(offsetUniform, 0.0,0.0,0.0) 264 | glDrawElements(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None) 265 | 266 | glUniform3f(offsetUniform, 0.0,0.0,-1.0) 267 | glDrawElementsBaseVertex(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None, nVertices/2) 268 | 269 | glBindVertexArray(0) 270 | glUseProgram(0) 271 | 272 | glutSwapBuffers() 273 | 274 | # keyboard input handler: exits the program if 'esc' is pressed 275 | def keyboard(key, x, y): 276 | if ord(key) == 27: # ord() is needed to get the keycode 277 | glutLeaveMainLoop() 278 | return 279 | 280 | # Called whenever the window's size changes (including once when the program starts) 281 | def reshape(w, h): 282 | global perspectiveMatrix 283 | perspectiveMatrix[0] = fFrustumScale / (w / float(h)) 284 | perspectiveMatrix[5] = fFrustumScale 285 | 286 | glUseProgram(theProgram) 287 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 288 | glUseProgram(0) 289 | 290 | glViewport(0, 0, w, h) 291 | 292 | # The main function 293 | def main(): 294 | glutInit() 295 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 296 | glutInitDisplayMode (displayMode) 297 | 298 | width = 500; 299 | height = 500; 300 | glutInitWindowSize (width, height) 301 | 302 | glutInitWindowPosition (300, 200) 303 | 304 | window = glutCreateWindow("Tutorial Window") 305 | 306 | init() 307 | glutDisplayFunc(display) 308 | glutReshapeFunc(reshape) 309 | glutKeyboardFunc(keyboard) 310 | 311 | glutMainLoop(); 312 | 313 | if __name__ == '__main__': 314 | main() 315 | -------------------------------------------------------------------------------- /Tut 05 Objects in Depth/DepthBuffer.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from DepthBuffer.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | import numpy as np 9 | from framework import * 10 | from itertools import chain 11 | 12 | # Set some global constants. Naming scheme is unchanged to maintain 13 | # analogy to the C++ code. Note that because of the lack of #define macros 14 | # in python, the color values were input manually 15 | RIGHT_EXTENT = 0.8 16 | LEFT_EXTENT = -RIGHT_EXTENT 17 | TOP_EXTENT = 0.20 18 | MIDDLE_EXTENT = 0.0 19 | BOTTOM_EXTENT = -TOP_EXTENT 20 | FRONT_EXTENT = -1.25 21 | REAR_EXTENT = -1.75 22 | 23 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 24 | # Note that this must be a numpy array, since as of 25 | # 170111 support for lists has not been implemented. 26 | vertexData = np.array([ 27 | #Object 1 positions 28 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 29 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 30 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 31 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 32 | 33 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 34 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 35 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 36 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 37 | 38 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 39 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 40 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 41 | 42 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 43 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 44 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 45 | 46 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 47 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 48 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 49 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 50 | 51 | #Object 2 positions 52 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 53 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 54 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 55 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 56 | 57 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 58 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 59 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 60 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 61 | 62 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 63 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 64 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 65 | 66 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 67 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 68 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 69 | 70 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 71 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 72 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 73 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 74 | 75 | #Object 1 colors 76 | # GREEN_COLOR 77 | 0.75, 0.75, 1.0, 1.0, 78 | 0.75, 0.75, 1.0, 1.0, 79 | 0.75, 0.75, 1.0, 1.0, 80 | 0.75, 0.75, 1.0, 1.0, 81 | 82 | # BLUE_COLOR 83 | 0.0, 0.5, 0.0, 1.0, 84 | 0.0, 0.5, 0.0, 1.0, 85 | 0.0, 0.5, 0.0, 1.0, 86 | 0.0, 0.5, 0.0, 1.0, 87 | 88 | # RED_COLOR 89 | 1.0, 0.0, 0.0, 1.0, 90 | 1.0, 0.0, 0.0, 1.0, 91 | 1.0, 0.0, 0.0, 1.0, 92 | 93 | # GREY_COLOR 94 | 0.8, 0.8, 0.8, 1.0, 95 | 0.8, 0.8, 0.8, 1.0, 96 | 0.8, 0.8, 0.8, 1.0, 97 | 98 | # BROWN_COLOR 99 | 0.5, 0.5, 0.0, 1.0, 100 | 0.5, 0.5, 0.0, 1.0, 101 | 0.5, 0.5, 0.0, 1.0, 102 | 0.5, 0.5, 0.0, 1.0, 103 | 104 | #Object 2 colors 105 | # RED_COLOR 106 | 1.0, 0.0, 0.0, 1.0, 107 | 1.0, 0.0, 0.0, 1.0, 108 | 1.0, 0.0, 0.0, 1.0, 109 | 1.0, 0.0, 0.0, 1.0, 110 | 111 | # BROWN_COLOR 112 | 0.5, 0.5, 0.0, 1.0, 113 | 0.5, 0.5, 0.0, 1.0, 114 | 0.5, 0.5, 0.0, 1.0, 115 | 0.5, 0.5, 0.0, 1.0, 116 | 117 | # BLUE_COLOR 118 | 0.0, 0.5, 0.0, 1.0, 119 | 0.0, 0.5, 0.0, 1.0, 120 | 0.0, 0.5, 0.0, 1.0, 121 | 122 | # GREEN_COLOR 123 | 0.75, 0.75, 1.0, 1.0, 124 | 0.75, 0.75, 1.0, 1.0, 125 | 0.75, 0.75, 1.0, 1.0, 126 | 127 | # GREY_COLOR 128 | 0.8, 0.8, 0.8, 1.0, 129 | 0.8, 0.8, 0.8, 1.0, 130 | 0.8, 0.8, 0.8, 1.0, 131 | 0.8, 0.8, 0.8, 1.0], 132 | dtype='float32' 133 | ).flatten() # flatten the array into 1D 134 | 135 | indexData = np.array( 136 | [0, 2, 1, 137 | 3, 2, 0, 138 | 139 | 4, 5, 6, 140 | 6, 7, 4, 141 | 142 | 8, 9, 10, 143 | 11, 13, 12, 144 | 145 | 14, 16, 15, 146 | 17, 16, 14], 147 | dtype='uint16') 148 | 149 | vertexDim = 3 150 | colorDim = 4 151 | nVertices = 12*3 152 | 153 | # Global variable to represent the compiled shader program, written in GLSL 154 | theProgram = None 155 | 156 | # Global variable to represent the buffer that will hold the position vectors 157 | vertexBufferObject = None 158 | # Global variables to hold vertex array objects 159 | vao = None 160 | # Global variable to hold the position index buffer object 161 | indexBufferObject = None 162 | 163 | # Global variables to store the location of the shader's uniform variables 164 | offsetUniform = None 165 | perspectiveMatrixUnif = None 166 | 167 | # Global display variables 168 | perspectiveMatrix = None 169 | fFrustumScale = 1.0 170 | 171 | # Set up the list of shaders, and call functions to compile them 172 | def initializeProgram(): 173 | shaderList = [] 174 | 175 | shaderList.append(loadShader(GL_VERTEX_SHADER, "Standard.vert")) 176 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "Standard.frag")) 177 | 178 | global theProgram 179 | theProgram = createProgram(shaderList) 180 | 181 | for shader in shaderList: 182 | glDeleteShader(shader) 183 | 184 | global offsetUniform 185 | offsetUniform = glGetUniformLocation(theProgram, "offset") 186 | 187 | global perspectiveMatrixUnif 188 | perspectiveMatrixUnif = glGetUniformLocation(theProgram, "perspectiveMatrix") 189 | 190 | fzNear = 1.0 191 | fzFar = 3.0 192 | 193 | global perspectiveMatrix 194 | perspectiveMatrix = np.zeros(16, dtype='float32') # note type 195 | perspectiveMatrix[0] = fFrustumScale 196 | perspectiveMatrix[5] = fFrustumScale 197 | perspectiveMatrix[10] = (fzFar + fzNear) / (fzNear - fzFar) 198 | perspectiveMatrix[14] = (2 * fzFar * fzNear) / (fzNear - fzFar) 199 | perspectiveMatrix[11] = -1.0 200 | 201 | glUseProgram(theProgram) 202 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 203 | glUseProgram(0) 204 | 205 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 206 | def initializeVertexBuffer(): 207 | global vertexBufferObject, indexBufferObject 208 | vertexBufferObject = glGenBuffers(1) 209 | 210 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 211 | glBufferData( # PyOpenGL allows for the omission of the size parameter 212 | GL_ARRAY_BUFFER, 213 | vertexData, 214 | GL_STATIC_DRAW 215 | ) 216 | glBindBuffer(GL_ARRAY_BUFFER, 0) 217 | 218 | indexBufferObject = glGenBuffers(1) 219 | 220 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 221 | glBufferData( 222 | GL_ELEMENT_ARRAY_BUFFER, 223 | indexData, 224 | GL_STATIC_DRAW 225 | ) 226 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 227 | 228 | # Initialize the OpenGL environment 229 | def init(): 230 | initializeProgram() 231 | initializeVertexBuffer() 232 | 233 | global vao 234 | vao = glGenVertexArrays(1) 235 | glBindVertexArray(vao) 236 | 237 | sizeOfFloat = 4 # all our arrays are dtype='float32' 238 | colorDataOffset = c_void_p(vertexDim * nVertices * sizeOfFloat) 239 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 240 | glEnableVertexAttribArray(0) 241 | glEnableVertexAttribArray(1) 242 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 243 | glVertexAttribPointer(1, colorDim, GL_FLOAT, GL_FALSE, 0, colorDataOffset) 244 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 245 | 246 | glBindVertexArray(0) 247 | 248 | glEnable(GL_CULL_FACE) 249 | glCullFace(GL_BACK) 250 | glFrontFace(GL_CW) 251 | 252 | glEnable(GL_DEPTH_TEST) 253 | glDepthMask(GL_TRUE) 254 | glDepthFunc(GL_LEQUAL) 255 | glDepthRange(0.0, 1.0) 256 | 257 | # Called to update the display. 258 | # Because we are using double-buffering, glutSwapBuffers is called at the end 259 | # to write the rendered buffer to the display. 260 | def display(): 261 | glClearColor(0.0, 0.0, 0.0, 0.0) 262 | glClearDepth(1.0) 263 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 264 | 265 | glUseProgram(theProgram) 266 | 267 | glBindVertexArray(vao) 268 | 269 | glUniform3f(offsetUniform, 0.0,0.0,0.0) 270 | glDrawElements(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None) 271 | 272 | glUniform3f(offsetUniform, 0.0,0.0,-1.0) 273 | glDrawElementsBaseVertex(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None, nVertices/2) 274 | 275 | glBindVertexArray(0) 276 | glUseProgram(0) 277 | 278 | glutSwapBuffers() 279 | 280 | # keyboard input handler: exits the program if 'esc' is pressed 281 | def keyboard(key, x, y): 282 | if ord(key) == 27: # ord() is needed to get the keycode 283 | glutLeaveMainLoop() 284 | return 285 | 286 | # Called whenever the window's size changes (including once when the program starts) 287 | def reshape(w, h): 288 | global perspectiveMatrix 289 | perspectiveMatrix[0] = fFrustumScale / (w / float(h)) 290 | perspectiveMatrix[5] = fFrustumScale 291 | 292 | glUseProgram(theProgram) 293 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 294 | glUseProgram(0) 295 | 296 | glViewport(0, 0, w, h) 297 | 298 | # The main function 299 | def main(): 300 | glutInit() 301 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 302 | glutInitDisplayMode (displayMode) 303 | 304 | width = 500; 305 | height = 500; 306 | glutInitWindowSize (width, height) 307 | 308 | glutInitWindowPosition (300, 200) 309 | 310 | window = glutCreateWindow("Tutorial Window") 311 | 312 | init() 313 | glutDisplayFunc(display) 314 | glutReshapeFunc(reshape) 315 | glutKeyboardFunc(keyboard) 316 | 317 | glutMainLoop(); 318 | 319 | if __name__ == '__main__': 320 | main() 321 | -------------------------------------------------------------------------------- /Tut 05 Objects in Depth/DepthClamping.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from VertexClipping.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | import numpy as np 9 | from framework import * 10 | from itertools import chain 11 | 12 | # Set some global constants. Naming scheme is unchanged to maintain 13 | # analogy to the C++ code. Note that because of the lack of #define macros 14 | # in python, the color values were input manually 15 | RIGHT_EXTENT = 0.8 16 | LEFT_EXTENT = -RIGHT_EXTENT 17 | TOP_EXTENT = 0.20 18 | MIDDLE_EXTENT = 0.0 19 | BOTTOM_EXTENT = -TOP_EXTENT 20 | FRONT_EXTENT = -1.25 21 | REAR_EXTENT = -1.75 22 | 23 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 24 | # Note that this must be a numpy array, since as of 25 | # 170111 support for lists has not been implemented. 26 | vertexData = np.array([ 27 | #Object 1 positions 28 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 29 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 30 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 31 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 32 | 33 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 34 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 35 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 36 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 37 | 38 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 39 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 40 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 41 | 42 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 43 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 44 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 45 | 46 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 47 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 48 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 49 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 50 | 51 | #Object 2 positions 52 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 53 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 54 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 55 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 56 | 57 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 58 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 59 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 60 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 61 | 62 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 63 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 64 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 65 | 66 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 67 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 68 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 69 | 70 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 71 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 72 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 73 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 74 | 75 | #Object 1 colors 76 | # GREEN_COLOR 77 | 0.75, 0.75, 1.0, 1.0, 78 | 0.75, 0.75, 1.0, 1.0, 79 | 0.75, 0.75, 1.0, 1.0, 80 | 0.75, 0.75, 1.0, 1.0, 81 | 82 | # BLUE_COLOR 83 | 0.0, 0.5, 0.0, 1.0, 84 | 0.0, 0.5, 0.0, 1.0, 85 | 0.0, 0.5, 0.0, 1.0, 86 | 0.0, 0.5, 0.0, 1.0, 87 | 88 | # RED_COLOR 89 | 1.0, 0.0, 0.0, 1.0, 90 | 1.0, 0.0, 0.0, 1.0, 91 | 1.0, 0.0, 0.0, 1.0, 92 | 93 | # GREY_COLOR 94 | 0.8, 0.8, 0.8, 1.0, 95 | 0.8, 0.8, 0.8, 1.0, 96 | 0.8, 0.8, 0.8, 1.0, 97 | 98 | # BROWN_COLOR 99 | 0.5, 0.5, 0.0, 1.0, 100 | 0.5, 0.5, 0.0, 1.0, 101 | 0.5, 0.5, 0.0, 1.0, 102 | 0.5, 0.5, 0.0, 1.0, 103 | 104 | #Object 2 colors 105 | # RED_COLOR 106 | 1.0, 0.0, 0.0, 1.0, 107 | 1.0, 0.0, 0.0, 1.0, 108 | 1.0, 0.0, 0.0, 1.0, 109 | 1.0, 0.0, 0.0, 1.0, 110 | 111 | # BROWN_COLOR 112 | 0.5, 0.5, 0.0, 1.0, 113 | 0.5, 0.5, 0.0, 1.0, 114 | 0.5, 0.5, 0.0, 1.0, 115 | 0.5, 0.5, 0.0, 1.0, 116 | 117 | # BLUE_COLOR 118 | 0.0, 0.5, 0.0, 1.0, 119 | 0.0, 0.5, 0.0, 1.0, 120 | 0.0, 0.5, 0.0, 1.0, 121 | 122 | # GREEN_COLOR 123 | 0.75, 0.75, 1.0, 1.0, 124 | 0.75, 0.75, 1.0, 1.0, 125 | 0.75, 0.75, 1.0, 1.0, 126 | 127 | # GREY_COLOR 128 | 0.8, 0.8, 0.8, 1.0, 129 | 0.8, 0.8, 0.8, 1.0, 130 | 0.8, 0.8, 0.8, 1.0, 131 | 0.8, 0.8, 0.8, 1.0], 132 | dtype='float32' 133 | ).flatten() # flatten the array into 1D 134 | 135 | indexData = np.array( 136 | [0, 2, 1, 137 | 3, 2, 0, 138 | 139 | 4, 5, 6, 140 | 6, 7, 4, 141 | 142 | 8, 9, 10, 143 | 11, 13, 12, 144 | 145 | 14, 16, 15, 146 | 17, 16, 14], 147 | dtype='uint16') 148 | 149 | vertexDim = 3 150 | colorDim = 4 151 | nVertices = 12*3 152 | 153 | # Global variable to represent the compiled shader program, written in GLSL 154 | theProgram = None 155 | 156 | # Global variable to represent the buffer that will hold the position vectors 157 | vertexBufferObject = None 158 | # Global variables to hold vertex array objects 159 | vao = None 160 | # Global variable to hold the position index buffer object 161 | indexBufferObject = None 162 | 163 | # Global variables to store the location of the shader's uniform variables 164 | offsetUniform = None 165 | perspectiveMatrixUnif = None 166 | 167 | # Global display variables 168 | perspectiveMatrix = None 169 | fFrustumScale = 1.0 170 | 171 | # Global depth clamping switch 172 | bDepthClampingActive = False 173 | 174 | # Set up the list of shaders, and call functions to compile them 175 | def initializeProgram(): 176 | shaderList = [] 177 | 178 | shaderList.append(loadShader(GL_VERTEX_SHADER, "Standard.vert")) 179 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "Standard.frag")) 180 | 181 | global theProgram 182 | theProgram = createProgram(shaderList) 183 | 184 | for shader in shaderList: 185 | glDeleteShader(shader) 186 | 187 | global offsetUniform 188 | offsetUniform = glGetUniformLocation(theProgram, "offset") 189 | 190 | global perspectiveMatrixUnif 191 | perspectiveMatrixUnif = glGetUniformLocation(theProgram, "perspectiveMatrix") 192 | 193 | fzNear = 1.0 194 | fzFar = 3.0 195 | 196 | global perspectiveMatrix 197 | perspectiveMatrix = np.zeros(16, dtype='float32') # note type 198 | perspectiveMatrix[0] = fFrustumScale 199 | perspectiveMatrix[5] = fFrustumScale 200 | perspectiveMatrix[10] = (fzFar + fzNear) / (fzNear - fzFar) 201 | perspectiveMatrix[14] = (2 * fzFar * fzNear) / (fzNear - fzFar) 202 | perspectiveMatrix[11] = -1.0 203 | 204 | glUseProgram(theProgram) 205 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 206 | glUseProgram(0) 207 | 208 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 209 | def initializeVertexBuffer(): 210 | global vertexBufferObject, indexBufferObject 211 | vertexBufferObject = glGenBuffers(1) 212 | 213 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 214 | glBufferData( # PyOpenGL allows for the omission of the size parameter 215 | GL_ARRAY_BUFFER, 216 | vertexData, 217 | GL_STATIC_DRAW 218 | ) 219 | glBindBuffer(GL_ARRAY_BUFFER, 0) 220 | 221 | indexBufferObject = glGenBuffers(1) 222 | 223 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 224 | glBufferData( 225 | GL_ELEMENT_ARRAY_BUFFER, 226 | indexData, 227 | GL_STATIC_DRAW 228 | ) 229 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 230 | 231 | # Initialize the OpenGL environment 232 | def init(): 233 | initializeProgram() 234 | initializeVertexBuffer() 235 | 236 | global vao 237 | vao = glGenVertexArrays(1) 238 | glBindVertexArray(vao) 239 | 240 | sizeOfFloat = 4 # all our arrays are dtype='float32' 241 | colorDataOffset = c_void_p(vertexDim * nVertices * sizeOfFloat) 242 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 243 | glEnableVertexAttribArray(0) 244 | glEnableVertexAttribArray(1) 245 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 246 | glVertexAttribPointer(1, colorDim, GL_FLOAT, GL_FALSE, 0, colorDataOffset) 247 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 248 | 249 | glBindVertexArray(0) 250 | 251 | glEnable(GL_CULL_FACE) 252 | glCullFace(GL_BACK) 253 | glFrontFace(GL_CW) 254 | 255 | glEnable(GL_DEPTH_TEST) 256 | glDepthMask(GL_TRUE) 257 | glDepthFunc(GL_LEQUAL) 258 | glDepthRange(0.0, 1.0) 259 | 260 | # Called to update the display. 261 | # Because we are using double-buffering, glutSwapBuffers is called at the end 262 | # to write the rendered buffer to the display. 263 | def display(): 264 | glClearColor(0.0, 0.0, 0.0, 0.0) 265 | glClearDepth(1.0) 266 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 267 | 268 | glUseProgram(theProgram) 269 | 270 | glBindVertexArray(vao) 271 | 272 | glUniform3f(offsetUniform, 0.0,0.0,0.5) 273 | glDrawElements(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None) 274 | 275 | glUniform3f(offsetUniform, 0.0,0.0,-1.0) 276 | glDrawElementsBaseVertex(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None, nVertices/2) 277 | 278 | glBindVertexArray(0) 279 | glUseProgram(0) 280 | 281 | glutSwapBuffers() 282 | 283 | # keyboard input handler: exits the program if 'esc' is pressed 284 | def keyboard(key, x, y): 285 | global bDepthClampingActive 286 | 287 | # ord() is needed to get the keycode 288 | keyval = ord(key) 289 | if keyval == 27: 290 | glutLeaveMainLoop() 291 | return 292 | elif keyval == 32: 293 | if (bDepthClampingActive): 294 | glDisable(GL_DEPTH_CLAMP) 295 | else: 296 | glEnable(GL_DEPTH_CLAMP) 297 | 298 | bDepthClampingActive = not bDepthClampingActive 299 | glutPostRedisplay() 300 | 301 | # Called whenever the window's size changes (including once when the program starts) 302 | def reshape(w, h): 303 | global perspectiveMatrix 304 | perspectiveMatrix[0] = fFrustumScale / (w / float(h)) 305 | perspectiveMatrix[5] = fFrustumScale 306 | 307 | glUseProgram(theProgram) 308 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 309 | glUseProgram(0) 310 | 311 | glViewport(0, 0, w, h) 312 | 313 | # The main function 314 | def main(): 315 | glutInit() 316 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 317 | glutInitDisplayMode (displayMode) 318 | 319 | width = 500; 320 | height = 500; 321 | glutInitWindowSize (width, height) 322 | 323 | glutInitWindowPosition (300, 200) 324 | 325 | window = glutCreateWindow("Tutorial Window") 326 | 327 | init() 328 | glutDisplayFunc(display) 329 | glutReshapeFunc(reshape) 330 | glutKeyboardFunc(keyboard) 331 | 332 | glutMainLoop(); 333 | 334 | if __name__ == '__main__': 335 | main() 336 | -------------------------------------------------------------------------------- /Tut 05 Objects in Depth/OverlapNoDepth.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from OverlapNoDepth.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | import numpy as np 9 | from framework import * 10 | from itertools import chain 11 | 12 | # Set some global constants. Naming scheme is unchanged to maintain 13 | # analogy to the C++ code. Note that because of the lack of #define macros 14 | # in python, the color values were input manually 15 | RIGHT_EXTENT = 0.8 16 | LEFT_EXTENT = -RIGHT_EXTENT 17 | TOP_EXTENT = 0.20 18 | MIDDLE_EXTENT = 0.0 19 | BOTTOM_EXTENT = -TOP_EXTENT 20 | FRONT_EXTENT = -1.25 21 | REAR_EXTENT = -1.75 22 | 23 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 24 | # Note that this must be a numpy array, since as of 25 | # 170111 support for lists has not been implemented. 26 | vertexData = np.array([ 27 | #Object 1 positions 28 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 29 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 30 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 31 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 32 | 33 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 34 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 35 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 36 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 37 | 38 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 39 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 40 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 41 | 42 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 43 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 44 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 45 | 46 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 47 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 48 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 49 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 50 | 51 | #Object 2 positions 52 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 53 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 54 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 55 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 56 | 57 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 58 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 59 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 60 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 61 | 62 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 63 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 64 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 65 | 66 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 67 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 68 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 69 | 70 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 71 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 72 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 73 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 74 | 75 | #Object 1 colors 76 | # GREEN_COLOR 77 | 0.75, 0.75, 1.0, 1.0, 78 | 0.75, 0.75, 1.0, 1.0, 79 | 0.75, 0.75, 1.0, 1.0, 80 | 0.75, 0.75, 1.0, 1.0, 81 | 82 | # BLUE_COLOR 83 | 0.0, 0.5, 0.0, 1.0, 84 | 0.0, 0.5, 0.0, 1.0, 85 | 0.0, 0.5, 0.0, 1.0, 86 | 0.0, 0.5, 0.0, 1.0, 87 | 88 | # RED_COLOR 89 | 1.0, 0.0, 0.0, 1.0, 90 | 1.0, 0.0, 0.0, 1.0, 91 | 1.0, 0.0, 0.0, 1.0, 92 | 93 | # GREY_COLOR 94 | 0.8, 0.8, 0.8, 1.0, 95 | 0.8, 0.8, 0.8, 1.0, 96 | 0.8, 0.8, 0.8, 1.0, 97 | 98 | # BROWN_COLOR 99 | 0.5, 0.5, 0.0, 1.0, 100 | 0.5, 0.5, 0.0, 1.0, 101 | 0.5, 0.5, 0.0, 1.0, 102 | 0.5, 0.5, 0.0, 1.0, 103 | 104 | #Object 2 colors 105 | # RED_COLOR 106 | 1.0, 0.0, 0.0, 1.0, 107 | 1.0, 0.0, 0.0, 1.0, 108 | 1.0, 0.0, 0.0, 1.0, 109 | 1.0, 0.0, 0.0, 1.0, 110 | 111 | # BROWN_COLOR 112 | 0.5, 0.5, 0.0, 1.0, 113 | 0.5, 0.5, 0.0, 1.0, 114 | 0.5, 0.5, 0.0, 1.0, 115 | 0.5, 0.5, 0.0, 1.0, 116 | 117 | # BLUE_COLOR 118 | 0.0, 0.5, 0.0, 1.0, 119 | 0.0, 0.5, 0.0, 1.0, 120 | 0.0, 0.5, 0.0, 1.0, 121 | 122 | # GREEN_COLOR 123 | 0.75, 0.75, 1.0, 1.0, 124 | 0.75, 0.75, 1.0, 1.0, 125 | 0.75, 0.75, 1.0, 1.0, 126 | 127 | # GREY_COLOR 128 | 0.8, 0.8, 0.8, 1.0, 129 | 0.8, 0.8, 0.8, 1.0, 130 | 0.8, 0.8, 0.8, 1.0, 131 | 0.8, 0.8, 0.8, 1.0], 132 | dtype='float32' 133 | ).flatten() # flatten the array into 1D 134 | 135 | indexData = np.array( 136 | [0, 2, 1, 137 | 3, 2, 0, 138 | 139 | 4, 5, 6, 140 | 6, 7, 4, 141 | 142 | 8, 9, 10, 143 | 11, 13, 12, 144 | 145 | 14, 16, 15, 146 | 17, 16, 14], 147 | dtype='uint16') 148 | 149 | vertexDim = 3 150 | colorDim = 4 151 | nVertices = 12*3 152 | 153 | # Global variable to represent the compiled shader program, written in GLSL 154 | theProgram = None 155 | 156 | # Global variable to represent the buffer that will hold the position vectors 157 | vertexBufferObject = None 158 | # Global variables to hold vertex array objects 159 | vaoObject1, vaoObject2 = None, None 160 | # Global variable to hold the position index buffer object 161 | indexBufferObject = None 162 | 163 | # Global variables to store the location of the shader's uniform variables 164 | offsetUniform = None 165 | perspectiveMatrixUnif = None 166 | 167 | # Global display variables 168 | perspectiveMatrix = None 169 | fFrustumScale = 1.0 170 | 171 | # Set up the list of shaders, and call functions to compile them 172 | def initializeProgram(): 173 | shaderList = [] 174 | 175 | shaderList.append(loadShader(GL_VERTEX_SHADER, "Standard.vert")) 176 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "Standard.frag")) 177 | 178 | global theProgram 179 | theProgram = createProgram(shaderList) 180 | 181 | for shader in shaderList: 182 | glDeleteShader(shader) 183 | 184 | global offsetUniform 185 | offsetUniform = glGetUniformLocation(theProgram, "offset") 186 | 187 | global perspectiveMatrixUnif 188 | perspectiveMatrixUnif = glGetUniformLocation(theProgram, "perspectiveMatrix") 189 | 190 | fzNear = 1.0 191 | fzFar = 3.0 192 | 193 | global perspectiveMatrix 194 | perspectiveMatrix = np.zeros(16, dtype='float32') # note type 195 | perspectiveMatrix[0] = fFrustumScale 196 | perspectiveMatrix[5] = fFrustumScale 197 | perspectiveMatrix[10] = (fzFar + fzNear) / (fzNear - fzFar) 198 | perspectiveMatrix[14] = (2 * fzFar * fzNear) / (fzNear - fzFar) 199 | perspectiveMatrix[11] = -1.0 200 | 201 | glUseProgram(theProgram) 202 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 203 | glUseProgram(0) 204 | 205 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 206 | def initializeVertexBuffer(): 207 | global vertexBufferObject, indexBufferObject 208 | vertexBufferObject = glGenBuffers(1) 209 | 210 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 211 | glBufferData( # PyOpenGL allows for the omission of the size parameter 212 | GL_ARRAY_BUFFER, 213 | vertexData, 214 | GL_STATIC_DRAW 215 | ) 216 | glBindBuffer(GL_ARRAY_BUFFER, 0) 217 | 218 | indexBufferObject = glGenBuffers(1) 219 | 220 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 221 | glBufferData( 222 | GL_ELEMENT_ARRAY_BUFFER, 223 | indexData, 224 | GL_STATIC_DRAW 225 | ) 226 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 227 | 228 | # Set up the vertex array objects 229 | def initializeVertexArrayObjects(): 230 | global vaoObject1, vaoObject2 231 | sizeOfFloat = 4 # all our arrays are dtype='float32' 232 | vaoObject1 = glGenVertexArrays(1) 233 | glBindVertexArray(vaoObject1) 234 | 235 | colorDataOffset = c_void_p(vertexDim * nVertices * sizeOfFloat) 236 | 237 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 238 | glEnableVertexAttribArray(0) 239 | glEnableVertexAttribArray(1) 240 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 241 | glVertexAttribPointer(1, colorDim, GL_FLOAT, GL_FALSE, 0, colorDataOffset) 242 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 243 | 244 | glBindVertexArray(0) 245 | 246 | vaoObject2 = glGenVertexArrays(1) 247 | glBindVertexArray(vaoObject2) 248 | 249 | posDataOffset = c_void_p(sizeOfFloat * vertexDim * (nVertices/2)) 250 | colorDataOffset = c_void_p( 251 | vertexDim * nVertices * sizeOfFloat + 252 | sizeOfFloat * colorDim * (nVertices/2)) 253 | 254 | # Use the same buffer object previously bound to GL_ARRAY_BUFFER 255 | glEnableVertexAttribArray(0) 256 | glEnableVertexAttribArray(1) 257 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, posDataOffset) 258 | glVertexAttribPointer(1, colorDim, GL_FLOAT, GL_FALSE, 0, colorDataOffset) 259 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 260 | 261 | glBindVertexArray(0) 262 | 263 | # Initialize the OpenGL environment 264 | def init(): 265 | initializeProgram() 266 | initializeVertexBuffer() 267 | initializeVertexArrayObjects() 268 | 269 | glEnable(GL_CULL_FACE) 270 | glCullFace(GL_BACK) 271 | glFrontFace(GL_CW) 272 | 273 | # Called to update the display. 274 | # Because we are using double-buffering, glutSwapBuffers is called at the end 275 | # to write the rendered buffer to the display. 276 | def display(): 277 | glClearColor(0.0, 0.0, 0.0, 0.0) 278 | glClear(GL_COLOR_BUFFER_BIT) 279 | 280 | glUseProgram(theProgram) 281 | 282 | glBindVertexArray(vaoObject1) 283 | glUniform3f(offsetUniform, 0.0,0.0,0.0) 284 | glDrawElements(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None) 285 | 286 | glBindVertexArray(vaoObject2) 287 | glUniform3f(offsetUniform, 0.0,0.0,-1.0) 288 | glDrawElements(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None) 289 | 290 | glBindVertexArray(0) 291 | glUseProgram(0) 292 | 293 | glutSwapBuffers() 294 | 295 | # keyboard input handler: exits the program if 'esc' is pressed 296 | def keyboard(key, x, y): 297 | if ord(key) == 27: # ord() is needed to get the keycode 298 | glutLeaveMainLoop() 299 | return 300 | 301 | # Called whenever the window's size changes (including once when the program starts) 302 | def reshape(w, h): 303 | global perspectiveMatrix 304 | perspectiveMatrix[0] = fFrustumScale / (w / float(h)) 305 | perspectiveMatrix[5] = fFrustumScale 306 | 307 | glUseProgram(theProgram) 308 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 309 | glUseProgram(0) 310 | 311 | glViewport(0, 0, w, h) 312 | 313 | # The main function 314 | def main(): 315 | glutInit() 316 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 317 | glutInitDisplayMode (displayMode) 318 | 319 | width = 500; 320 | height = 500; 321 | glutInitWindowSize (width, height) 322 | 323 | glutInitWindowPosition (300, 200) 324 | 325 | window = glutCreateWindow("Tutorial Window") 326 | 327 | init() 328 | glutDisplayFunc(display) 329 | glutReshapeFunc(reshape) 330 | glutKeyboardFunc(keyboard) 331 | 332 | glutMainLoop(); 333 | 334 | if __name__ == '__main__': 335 | main() 336 | -------------------------------------------------------------------------------- /Tut 05 Objects in Depth/VertexClipping.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from VertexClipping.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLU import * 7 | from OpenGL.GL import * 8 | import numpy as np 9 | from framework import * 10 | from itertools import chain 11 | 12 | # Set some global constants. Naming scheme is unchanged to maintain 13 | # analogy to the C++ code. Note that because of the lack of #define macros 14 | # in python, the color values were input manually 15 | RIGHT_EXTENT = 0.8 16 | LEFT_EXTENT = -RIGHT_EXTENT 17 | TOP_EXTENT = 0.20 18 | MIDDLE_EXTENT = 0.0 19 | BOTTOM_EXTENT = -TOP_EXTENT 20 | FRONT_EXTENT = -1.25 21 | REAR_EXTENT = -1.75 22 | 23 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 24 | # Note that this must be a numpy array, since as of 25 | # 170111 support for lists has not been implemented. 26 | vertexData = np.array([ 27 | #Object 1 positions 28 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 29 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 30 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 31 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 32 | 33 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 34 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 35 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 36 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 37 | 38 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 39 | LEFT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 40 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 41 | 42 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 43 | RIGHT_EXTENT, MIDDLE_EXTENT, FRONT_EXTENT, 44 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 45 | 46 | LEFT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 47 | LEFT_EXTENT, TOP_EXTENT, REAR_EXTENT, 48 | RIGHT_EXTENT, TOP_EXTENT, REAR_EXTENT, 49 | RIGHT_EXTENT, BOTTOM_EXTENT, REAR_EXTENT, 50 | 51 | #Object 2 positions 52 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 53 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 54 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 55 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 56 | 57 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 58 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 59 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 60 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 61 | 62 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 63 | MIDDLE_EXTENT, RIGHT_EXTENT, FRONT_EXTENT, 64 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 65 | 66 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 67 | MIDDLE_EXTENT, LEFT_EXTENT, FRONT_EXTENT, 68 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 69 | 70 | BOTTOM_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 71 | TOP_EXTENT, RIGHT_EXTENT, REAR_EXTENT, 72 | TOP_EXTENT, LEFT_EXTENT, REAR_EXTENT, 73 | BOTTOM_EXTENT, LEFT_EXTENT, REAR_EXTENT, 74 | 75 | #Object 1 colors 76 | # GREEN_COLOR 77 | 0.75, 0.75, 1.0, 1.0, 78 | 0.75, 0.75, 1.0, 1.0, 79 | 0.75, 0.75, 1.0, 1.0, 80 | 0.75, 0.75, 1.0, 1.0, 81 | 82 | # BLUE_COLOR 83 | 0.0, 0.5, 0.0, 1.0, 84 | 0.0, 0.5, 0.0, 1.0, 85 | 0.0, 0.5, 0.0, 1.0, 86 | 0.0, 0.5, 0.0, 1.0, 87 | 88 | # RED_COLOR 89 | 1.0, 0.0, 0.0, 1.0, 90 | 1.0, 0.0, 0.0, 1.0, 91 | 1.0, 0.0, 0.0, 1.0, 92 | 93 | # GREY_COLOR 94 | 0.8, 0.8, 0.8, 1.0, 95 | 0.8, 0.8, 0.8, 1.0, 96 | 0.8, 0.8, 0.8, 1.0, 97 | 98 | # BROWN_COLOR 99 | 0.5, 0.5, 0.0, 1.0, 100 | 0.5, 0.5, 0.0, 1.0, 101 | 0.5, 0.5, 0.0, 1.0, 102 | 0.5, 0.5, 0.0, 1.0, 103 | 104 | #Object 2 colors 105 | # RED_COLOR 106 | 1.0, 0.0, 0.0, 1.0, 107 | 1.0, 0.0, 0.0, 1.0, 108 | 1.0, 0.0, 0.0, 1.0, 109 | 1.0, 0.0, 0.0, 1.0, 110 | 111 | # BROWN_COLOR 112 | 0.5, 0.5, 0.0, 1.0, 113 | 0.5, 0.5, 0.0, 1.0, 114 | 0.5, 0.5, 0.0, 1.0, 115 | 0.5, 0.5, 0.0, 1.0, 116 | 117 | # BLUE_COLOR 118 | 0.0, 0.5, 0.0, 1.0, 119 | 0.0, 0.5, 0.0, 1.0, 120 | 0.0, 0.5, 0.0, 1.0, 121 | 122 | # GREEN_COLOR 123 | 0.75, 0.75, 1.0, 1.0, 124 | 0.75, 0.75, 1.0, 1.0, 125 | 0.75, 0.75, 1.0, 1.0, 126 | 127 | # GREY_COLOR 128 | 0.8, 0.8, 0.8, 1.0, 129 | 0.8, 0.8, 0.8, 1.0, 130 | 0.8, 0.8, 0.8, 1.0, 131 | 0.8, 0.8, 0.8, 1.0], 132 | dtype='float32' 133 | ).flatten() # flatten the array into 1D 134 | 135 | indexData = np.array( 136 | [0, 2, 1, 137 | 3, 2, 0, 138 | 139 | 4, 5, 6, 140 | 6, 7, 4, 141 | 142 | 8, 9, 10, 143 | 11, 13, 12, 144 | 145 | 14, 16, 15, 146 | 17, 16, 14], 147 | dtype='uint16') 148 | 149 | vertexDim = 3 150 | colorDim = 4 151 | nVertices = 12*3 152 | 153 | # Global variable to represent the compiled shader program, written in GLSL 154 | theProgram = None 155 | 156 | # Global variable to represent the buffer that will hold the position vectors 157 | vertexBufferObject = None 158 | # Global variables to hold vertex array objects 159 | vao = None 160 | # Global variable to hold the position index buffer object 161 | indexBufferObject = None 162 | 163 | # Global variables to store the location of the shader's uniform variables 164 | offsetUniform = None 165 | perspectiveMatrixUnif = None 166 | 167 | # Global display variables 168 | perspectiveMatrix = None 169 | fFrustumScale = 1.0 170 | 171 | # Set up the list of shaders, and call functions to compile them 172 | def initializeProgram(): 173 | shaderList = [] 174 | 175 | shaderList.append(loadShader(GL_VERTEX_SHADER, "Standard.vert")) 176 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "Standard.frag")) 177 | 178 | global theProgram 179 | theProgram = createProgram(shaderList) 180 | 181 | for shader in shaderList: 182 | glDeleteShader(shader) 183 | 184 | global offsetUniform 185 | offsetUniform = glGetUniformLocation(theProgram, "offset") 186 | 187 | global perspectiveMatrixUnif 188 | perspectiveMatrixUnif = glGetUniformLocation(theProgram, "perspectiveMatrix") 189 | 190 | fzNear = 1.0 191 | fzFar = 3.0 192 | 193 | global perspectiveMatrix 194 | perspectiveMatrix = np.zeros(16, dtype='float32') # note type 195 | perspectiveMatrix[0] = fFrustumScale 196 | perspectiveMatrix[5] = fFrustumScale 197 | perspectiveMatrix[10] = (fzFar + fzNear) / (fzNear - fzFar) 198 | perspectiveMatrix[14] = (2 * fzFar * fzNear) / (fzNear - fzFar) 199 | perspectiveMatrix[11] = -1.0 200 | 201 | glUseProgram(theProgram) 202 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 203 | glUseProgram(0) 204 | 205 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 206 | def initializeVertexBuffer(): 207 | global vertexBufferObject, indexBufferObject 208 | vertexBufferObject = glGenBuffers(1) 209 | 210 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 211 | glBufferData( # PyOpenGL allows for the omission of the size parameter 212 | GL_ARRAY_BUFFER, 213 | vertexData, 214 | GL_STATIC_DRAW 215 | ) 216 | glBindBuffer(GL_ARRAY_BUFFER, 0) 217 | 218 | indexBufferObject = glGenBuffers(1) 219 | 220 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 221 | glBufferData( 222 | GL_ELEMENT_ARRAY_BUFFER, 223 | indexData, 224 | GL_STATIC_DRAW 225 | ) 226 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 227 | 228 | # Initialize the OpenGL environment 229 | def init(): 230 | initializeProgram() 231 | initializeVertexBuffer() 232 | 233 | global vao 234 | vao = glGenVertexArrays(1) 235 | glBindVertexArray(vao) 236 | 237 | sizeOfFloat = 4 # all our arrays are dtype='float32' 238 | colorDataOffset = c_void_p(vertexDim * nVertices * sizeOfFloat) 239 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 240 | glEnableVertexAttribArray(0) 241 | glEnableVertexAttribArray(1) 242 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 243 | glVertexAttribPointer(1, colorDim, GL_FLOAT, GL_FALSE, 0, colorDataOffset) 244 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 245 | 246 | glBindVertexArray(0) 247 | 248 | glEnable(GL_CULL_FACE) 249 | glCullFace(GL_BACK) 250 | glFrontFace(GL_CW) 251 | 252 | glEnable(GL_DEPTH_TEST) 253 | glDepthMask(GL_TRUE) 254 | glDepthFunc(GL_LEQUAL) 255 | glDepthRange(0.0, 1.0) 256 | 257 | # Called to update the display. 258 | # Because we are using double-buffering, glutSwapBuffers is called at the end 259 | # to write the rendered buffer to the display. 260 | def display(): 261 | glClearColor(0.0, 0.0, 0.0, 0.0) 262 | glClearDepth(1.0) 263 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 264 | 265 | glUseProgram(theProgram) 266 | 267 | glBindVertexArray(vao) 268 | 269 | glUniform3f(offsetUniform, 0.0,0.0,0.5) 270 | glDrawElements(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None) 271 | 272 | glUniform3f(offsetUniform, 0.0,0.0,-1.0) 273 | glDrawElementsBaseVertex(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None, nVertices/2) 274 | 275 | glBindVertexArray(0) 276 | glUseProgram(0) 277 | 278 | glutSwapBuffers() 279 | 280 | # keyboard input handler: exits the program if 'esc' is pressed 281 | def keyboard(key, x, y): 282 | if ord(key) == 27: # ord() is needed to get the keycode 283 | glutLeaveMainLoop() 284 | return 285 | 286 | # Called whenever the window's size changes (including once when the program starts) 287 | def reshape(w, h): 288 | global perspectiveMatrix 289 | perspectiveMatrix[0] = fFrustumScale / (w / float(h)) 290 | perspectiveMatrix[5] = fFrustumScale 291 | 292 | glUseProgram(theProgram) 293 | glUniformMatrix4fv(perspectiveMatrixUnif, 1, GL_FALSE, perspectiveMatrix) 294 | glUseProgram(0) 295 | 296 | glViewport(0, 0, w, h) 297 | 298 | # The main function 299 | def main(): 300 | glutInit() 301 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 302 | glutInitDisplayMode (displayMode) 303 | 304 | width = 500; 305 | height = 500; 306 | glutInitWindowSize (width, height) 307 | 308 | glutInitWindowPosition (300, 200) 309 | 310 | window = glutCreateWindow("Tutorial Window") 311 | 312 | init() 313 | glutDisplayFunc(display) 314 | glutReshapeFunc(reshape) 315 | glutKeyboardFunc(keyboard) 316 | 317 | glutMainLoop(); 318 | 319 | if __name__ == '__main__': 320 | main() 321 | -------------------------------------------------------------------------------- /Tut 05 Objects in Depth/data/Standard.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | smooth in vec4 theColor; 4 | 5 | out vec4 outputColor; 6 | 7 | void main() 8 | { 9 | outputColor = theColor; 10 | } 11 | -------------------------------------------------------------------------------- /Tut 05 Objects in Depth/data/Standard.vert: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | layout(location = 0) in vec4 position; 4 | layout(location = 1) in vec4 color; 5 | 6 | smooth out vec4 theColor; 7 | 8 | uniform vec3 offset; 9 | uniform mat4 perspectiveMatrix; 10 | 11 | void main() 12 | { 13 | vec4 cameraPos = position + vec4(offset.x, offset.y, offset.z, 0.0); 14 | 15 | gl_Position = perspectiveMatrix * cameraPos; 16 | theColor = color; 17 | } 18 | -------------------------------------------------------------------------------- /Tut 05 Objects in Depth/framework.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from framework.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | # 5 | # NB: Unlike in the framework.cpp organization, the main loop is contained 6 | # in the tutorial files, not in this framework file. Additionally, a copy of 7 | # this module file must exist in the same directory as the tutorial files 8 | # to be imported properly. 9 | 10 | from OpenGL.GLUT import * 11 | from OpenGL.GLU import * 12 | from OpenGL.GL import * 13 | import os 14 | import sys 15 | 16 | # Function that creates and compiles shaders according to the given type (a GL enum value) and 17 | # shader program (a file containing a GLSL program). 18 | def loadShader(shaderType, shaderFile): 19 | # check if file exists, get full path name 20 | strFilename = findFileOrThrow(shaderFile) 21 | shaderData = None 22 | with open(strFilename, 'r') as f: 23 | shaderData = f.read() 24 | 25 | shader = glCreateShader(shaderType) 26 | glShaderSource(shader, shaderData) # note that this is a simpler function call than in C 27 | 28 | # This shader compilation is more explicit than the one used in 29 | # framework.cpp, which relies on a glutil wrapper function. 30 | # This is made explicit here mainly to decrease dependence on pyOpenGL 31 | # utilities and wrappers, which docs caution may change in future versions. 32 | glCompileShader(shader) 33 | 34 | status = glGetShaderiv(shader, GL_COMPILE_STATUS) 35 | if status == GL_FALSE: 36 | # Note that getting the error log is much simpler in Python than in C/C++ 37 | # and does not require explicit handling of the string buffer 38 | strInfoLog = glGetShaderInforLog(shader) 39 | strShaderType = "" 40 | if shaderType is GL_VERTEX_SHADER: 41 | strShaderType = "vertex" 42 | elif shaderType is GL_GEOMETRY_SHADER: 43 | strShaderType = "geometry" 44 | elif shaderType is GL_FRAGMENT_SHADER: 45 | strShaderType = "fragment" 46 | 47 | print "Compilation failure for " + strShaderType + " shader:\n" + strInfoLog 48 | 49 | return shader 50 | 51 | # Function that accepts a list of shaders, compiles them, and returns a handle to the compiled program 52 | def createProgram(shaderList): 53 | program = glCreateProgram() 54 | 55 | for shader in shaderList: 56 | glAttachShader(program, shader) 57 | 58 | glLinkProgram(program) 59 | 60 | status = glGetProgramiv(program, GL_LINK_STATUS) 61 | if status == GL_FALSE: 62 | # Note that getting the error log is much simpler in Python than in C/C++ 63 | # and does not require explicit handling of the string buffer 64 | strInfoLog = glGetProgramInfoLog(program) 65 | print "Linker failure: \n" + strInfoLog 66 | 67 | for shader in shaderList: 68 | glDetachShader(program, shader) 69 | 70 | return program 71 | 72 | 73 | # Helper function to locate and open the target file (passed in as a string). 74 | # Returns the full path to the file as a string. 75 | def findFileOrThrow(strBasename): 76 | # Keep constant names in C-style convention, for readability 77 | # when comparing to C(/C++) code. 78 | LOCAL_FILE_DIR = "data" + os.sep 79 | GLOBAL_FILE_DIR = ".." + os.sep + "data" + os.sep 80 | 81 | strFilename = LOCAL_FILE_DIR + strBasename 82 | if os.path.isfile(strFilename): 83 | return strFilename 84 | 85 | strFilename = GLOBAL_FILE_DIR + strBasename 86 | if os.path.isfile(strFilename): 87 | return strFilename 88 | 89 | raise IOError('Could not find target file ' + strBasename) 90 | -------------------------------------------------------------------------------- /Tut 06 Objects in Motion/Rotations.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from Rotations.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLUT.freeglut import * 7 | from OpenGL.GLU import * 8 | from OpenGL.GL import * 9 | import numpy as np 10 | from framework import * 11 | from math import tan, cos, sin, sqrt 12 | 13 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 14 | # Note that this must be a numpy array, since as of 15 | # 170111 support for lists has not been implemented. 16 | vertexData = np.array([ 17 | +1.0, +1.0, +1.0, 18 | -1.0, -1.0, +1.0, 19 | -1.0, +1.0, -1.0, 20 | +1.0, -1.0, -1.0, 21 | 22 | -1.0, -1.0, -1.0, 23 | +1.0, +1.0, -1.0, 24 | +1.0, -1.0, +1.0, 25 | -1.0, +1.0, +1.0, 26 | 27 | # GREEN_COLOR 28 | 0.0, 1.0, 0.0, 1.0, 29 | # BLUE_COLOR 30 | 0.0, 0.0, 1.0, 1.0, 31 | # RED_COLOR 32 | 1.0, 0.0, 0.0, 1.0, 33 | # BROWN_COLOR 34 | 0.5, 0.5, 0.0, 1.0, 35 | 36 | # GREEN_COLOR 37 | 0.0, 1.0, 0.0, 1.0, 38 | # BLUE_COLOR 39 | 0.0, 0.0, 1.0, 1.0, 40 | # RED_COLOR 41 | 1.0, 0.0, 0.0, 1.0, 42 | # BROWN_COLOR 43 | 0.5, 0.5, 0.0, 1.0], 44 | dtype='float32' 45 | ) 46 | 47 | indexData = np.array([ 48 | 0, 1, 2, 49 | 1, 0, 3, 50 | 2, 3, 0, 51 | 3, 2, 1, 52 | 53 | 5, 4, 6, 54 | 4, 5, 7, 55 | 7, 6, 4, 56 | 6, 7, 5], 57 | dtype='uint16') 58 | 59 | vertexDim = 3 60 | colorDim = 4 61 | nVertices = 8 62 | 63 | # Helper function to calculate the frustum scale. 64 | # Accepts a field of view (in degrees) and returns the scale factor 65 | def calcFrustumScale(fFovDeg): 66 | degToRad = 3.14159 * 2.0 / 360.0 67 | fFovRad = fFovDeg * degToRad 68 | return 1.0 / tan(fFovRad / 2.0) 69 | 70 | # Global variable to represent the compiled shader program, written in GLSL 71 | theProgram = None 72 | 73 | # Global variable to represent the buffer that will hold the position vectors 74 | vertexBufferObject = None 75 | # Global variables to hold vertex array objects 76 | vao = None 77 | # Global variable to hold the position index buffer object 78 | indexBufferObject = None 79 | 80 | # Global variables to store the location of the shader's uniform variables 81 | modelToCameraMatrixUnif = None 82 | cameraToClipMatrixUnif = None 83 | 84 | # Global display variables 85 | cameraToClipMatrix = np.zeros((4,4), dtype='float32') 86 | fFrustumScale = calcFrustumScale(45.0) 87 | 88 | # Set up the list of shaders, and call functions to compile them 89 | def initializeProgram(): 90 | shaderList = [] 91 | 92 | shaderList.append(loadShader(GL_VERTEX_SHADER, "PosColorLocalTransform.vert")) 93 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "ColorPassthrough.frag")) 94 | 95 | global theProgram 96 | theProgram = createProgram(shaderList) 97 | 98 | for shader in shaderList: 99 | glDeleteShader(shader) 100 | 101 | global modelToCameraMatrixUnif, cameraToClipMatrixUnif 102 | modelToCameraMatrixUnif = glGetUniformLocation(theProgram, "modelToCameraMatrix") 103 | cameraToClipMatrixUnif = glGetUniformLocation(theProgram, "cameraToClipMatrix") 104 | 105 | fzNear = 1.0 106 | fzFar = 61.0 107 | 108 | global cameraToClipMatrix 109 | # Note that this and the transformation matrix below are both 110 | # ROW-MAJOR ordered. Thus, it is necessary to pass a transpose 111 | # of the matrix to the glUniform assignment function. 112 | cameraToClipMatrix[0][0] = fFrustumScale 113 | cameraToClipMatrix[1][1] = fFrustumScale 114 | cameraToClipMatrix[2][2] = (fzFar + fzNear) / (fzNear - fzFar) 115 | cameraToClipMatrix[2][3] = -1.0 116 | cameraToClipMatrix[3][2] = (2 * fzFar * fzNear) / (fzNear - fzFar) 117 | 118 | glUseProgram(theProgram) 119 | glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE, cameraToClipMatrix.transpose()) 120 | glUseProgram(0) 121 | 122 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 123 | def initializeVertexBuffer(): 124 | global vertexBufferObject, indexBufferObject 125 | vertexBufferObject = glGenBuffers(1) 126 | 127 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 128 | glBufferData( # PyOpenGL allows for the omission of the size parameter 129 | GL_ARRAY_BUFFER, 130 | vertexData, 131 | GL_STATIC_DRAW 132 | ) 133 | glBindBuffer(GL_ARRAY_BUFFER, 0) 134 | 135 | indexBufferObject = glGenBuffers(1) 136 | 137 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 138 | glBufferData( 139 | GL_ELEMENT_ARRAY_BUFFER, 140 | indexData, 141 | GL_STATIC_DRAW 142 | ) 143 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 144 | 145 | # Helper functions to return various types of transformation arrays 146 | def calcLerpFactor(fElapsedTime, fLoopDuration): 147 | fValue = (fElapsedTime % fLoopDuration) / fLoopDuration 148 | if fValue > 0.5: 149 | fValue = 1.0 - fValue 150 | return fValue * 2.0 151 | 152 | def computeAngleRad(fElapsedTime, fLoopDuration): 153 | fScale = 3.14159 * 2.0 / fLoopDuration 154 | fCurrTimeThroughLoop = fElapsedTime % fLoopDuration 155 | return fCurrTimeThroughLoop * fScale 156 | 157 | def nullRotation(fElapsedTime): 158 | newTransform = np.identity(4, dtype='float32') 159 | # offset 160 | newTransform[0][3] = 0.0 161 | newTransform[1][3] = 0.0 162 | newTransform[2][3] = -25.0 163 | return newTransform 164 | 165 | def rotateX(fElapsedTime): 166 | fAngRad = computeAngleRad(fElapsedTime, 3.0) 167 | fCos = cos(fAngRad) 168 | fSin = sin(fAngRad) 169 | 170 | newTransform = np.identity(4, dtype='float32') 171 | newTransform[1][1] = fCos 172 | newTransform[2][1] = -fSin 173 | newTransform[1][2] = fSin 174 | newTransform[2][2] = fCos 175 | # offset 176 | newTransform[0][3] = -5.0 177 | newTransform[1][3] = -5.0 178 | newTransform[2][3] = -25.0 179 | return newTransform 180 | 181 | def rotateY(fElapsedTime): 182 | fAngRad = computeAngleRad(fElapsedTime, 2.0) 183 | fCos = cos(fAngRad) 184 | fSin = sin(fAngRad) 185 | 186 | newTransform = np.identity(4, dtype='float32') 187 | newTransform[0][0] = fCos 188 | newTransform[2][0] = fSin 189 | newTransform[0][2] = -fSin 190 | newTransform[2][2] = fCos 191 | # offset 192 | newTransform[0][3] = -5.0 193 | newTransform[1][3] = 5.0 194 | newTransform[2][3] = -25.0 195 | return newTransform 196 | 197 | def rotateZ(fElapsedTime): 198 | fAngRad = computeAngleRad(fElapsedTime, 2.0) 199 | fCos = cos(fAngRad) 200 | fSin = sin(fAngRad) 201 | 202 | newTransform = np.identity(4, dtype='float32') 203 | newTransform[0][0] = fCos 204 | newTransform[1][0] = -fSin 205 | newTransform[0][1] = fSin 206 | newTransform[1][1] = fCos 207 | # offset 208 | newTransform[0][3] = 5.0 209 | newTransform[1][3] = 5.0 210 | newTransform[2][3] = -25.0 211 | return newTransform 212 | 213 | def rotateAxis(fElapsedTime): 214 | fAngRad = computeAngleRad(fElapsedTime, 2.0) 215 | fCos = cos(fAngRad) 216 | fInvCos = 1.0 - fCos 217 | fSin = sin(fAngRad) 218 | fInvSin = 1.0 - fSin 219 | 220 | # get the unit vector in the direction (1,1,1) 221 | magnitude = sqrt(3) # 1**2 + 1**2 + 1**2 222 | class Axis: # used to keep similar notation to the C++ files 223 | x = 0 224 | y = 0 225 | z = 0 226 | axis = Axis() 227 | axis.x = 1.0/magnitude 228 | axis.y = 1.0/magnitude 229 | axis.z = 1.0/magnitude 230 | 231 | newTransform = np.identity(4, dtype='float32') 232 | newTransform[0][0] = (axis.x * axis.x) + ((1 - axis.x * axis.x) * fCos) 233 | newTransform[1][0] = axis.x * axis.y * (fInvCos) - (axis.z * fSin) 234 | newTransform[2][0] = axis.x * axis.z * (fInvCos) + (axis.y * fSin) 235 | 236 | newTransform[0][1] = axis.x * axis.y * (fInvCos) + (axis.z * fSin) 237 | newTransform[1][1] = (axis.y * axis.y) + ((1 - axis.y * axis.y) * fCos) 238 | newTransform[2][1] = axis.y * axis.z * (fInvCos) - (axis.x * fSin) 239 | 240 | newTransform[0][2] = axis.x * axis.z * (fInvCos) - (axis.y * fSin) 241 | newTransform[1][2] = axis.y * axis.z * (fInvCos) + (axis.x * fSin) 242 | newTransform[2][2] = (axis.z * axis.z) + ((1 - axis.z * axis.z) * fCos) 243 | 244 | # offset 245 | newTransform[0][3] = 5.0 246 | newTransform[1][3] = -5.0 247 | newTransform[2][3] = -25.0 248 | return newTransform 249 | 250 | 251 | # A list of the helper offset functions. 252 | # Note that this does not require a structure def in python. 253 | # Each function is written to return the complete transform matrix. 254 | g_instanceList =[ 255 | nullRotation, 256 | rotateX, 257 | rotateY, 258 | rotateZ, 259 | rotateAxis] 260 | 261 | # Initialize the OpenGL environment 262 | def init(): 263 | initializeProgram() 264 | initializeVertexBuffer() 265 | 266 | global vao 267 | vao = glGenVertexArrays(1) 268 | glBindVertexArray(vao) 269 | 270 | sizeOfFloat = 4 # all our arrays are dtype='float32' 271 | colorDataOffset = c_void_p(vertexDim * nVertices * sizeOfFloat) 272 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 273 | glEnableVertexAttribArray(0) 274 | glEnableVertexAttribArray(1) 275 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 276 | glVertexAttribPointer(1, colorDim, GL_FLOAT, GL_FALSE, 0, colorDataOffset) 277 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 278 | 279 | glBindVertexArray(0) 280 | 281 | glEnable(GL_CULL_FACE) 282 | glCullFace(GL_BACK) 283 | glFrontFace(GL_CW) 284 | 285 | glEnable(GL_DEPTH_TEST) 286 | glDepthMask(GL_TRUE) 287 | glDepthFunc(GL_LEQUAL) 288 | glDepthRange(0.0, 1.0) 289 | 290 | # Called to update the display. 291 | # Because we are using double-buffering, glutSwapBuffers is called at the end 292 | # to write the rendered buffer to the display. 293 | def display(): 294 | glClearColor(0.0, 0.0, 0.0, 0.0) 295 | glClearDepth(1.0) 296 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 297 | 298 | glUseProgram(theProgram) 299 | 300 | glBindVertexArray(vao) 301 | 302 | fElapsedTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0 303 | for func in g_instanceList: 304 | transformMatrix = func(fElapsedTime) 305 | 306 | glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, transformMatrix.transpose()) 307 | glDrawElements(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None) 308 | 309 | glBindVertexArray(0) 310 | glUseProgram(0) 311 | 312 | glutSwapBuffers() 313 | glutPostRedisplay() 314 | 315 | # keyboard input handler: exits the program if 'esc' is pressed 316 | def keyboard(key, x, y): 317 | 318 | # ord() is needed to get the keycode 319 | keyval = ord(key) 320 | if keyval == 27: 321 | glutLeaveMainLoop() 322 | return 323 | 324 | # Called whenever the window's size changes (including once when the program starts) 325 | def reshape(w, h): 326 | global cameraToClipMatrix 327 | cameraToClipMatrix[0][0] = fFrustumScale * (h / float(w)) 328 | cameraToClipMatrix[1][1] = fFrustumScale 329 | 330 | glUseProgram(theProgram) 331 | glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE, cameraToClipMatrix.transpose()) 332 | glUseProgram(0) 333 | 334 | glViewport(0, 0, w, h) 335 | 336 | # The main function 337 | def main(): 338 | glutInit() 339 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 340 | glutInitDisplayMode (displayMode) 341 | 342 | glutInitContextVersion(3,3) 343 | glutInitContextProfile(GLUT_CORE_PROFILE) 344 | 345 | width = 500; 346 | height = 500; 347 | glutInitWindowSize (width, height) 348 | 349 | glutInitWindowPosition (300, 200) 350 | 351 | window = glutCreateWindow("Tutorial Window") 352 | 353 | init() 354 | glutDisplayFunc(display) 355 | glutReshapeFunc(reshape) 356 | glutKeyboardFunc(keyboard) 357 | 358 | glutMainLoop(); 359 | 360 | if __name__ == '__main__': 361 | main() 362 | -------------------------------------------------------------------------------- /Tut 06 Objects in Motion/Scale.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from Scale.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLUT.freeglut import * 7 | from OpenGL.GLU import * 8 | from OpenGL.GL import * 9 | import numpy as np 10 | from framework import * 11 | from math import tan, cos, sin 12 | 13 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 14 | # Note that this must be a numpy array, since as of 15 | # 170111 support for lists has not been implemented. 16 | vertexData = np.array([ 17 | +1.0, +1.0, +1.0, 18 | -1.0, -1.0, +1.0, 19 | -1.0, +1.0, -1.0, 20 | +1.0, -1.0, -1.0, 21 | 22 | -1.0, -1.0, -1.0, 23 | +1.0, +1.0, -1.0, 24 | +1.0, -1.0, +1.0, 25 | -1.0, +1.0, +1.0, 26 | 27 | # GREEN_COLOR 28 | 0.0, 1.0, 0.0, 1.0, 29 | # BLUE_COLOR 30 | 0.0, 0.0, 1.0, 1.0, 31 | # RED_COLOR 32 | 1.0, 0.0, 0.0, 1.0, 33 | # BROWN_COLOR 34 | 0.5, 0.5, 0.0, 1.0, 35 | 36 | # GREEN_COLOR 37 | 0.0, 1.0, 0.0, 1.0, 38 | # BLUE_COLOR 39 | 0.0, 0.0, 1.0, 1.0, 40 | # RED_COLOR 41 | 1.0, 0.0, 0.0, 1.0, 42 | # BROWN_COLOR 43 | 0.5, 0.5, 0.0, 1.0], 44 | dtype='float32' 45 | ) 46 | 47 | indexData = np.array([ 48 | 0, 1, 2, 49 | 1, 0, 3, 50 | 2, 3, 0, 51 | 3, 2, 1, 52 | 53 | 5, 4, 6, 54 | 4, 5, 7, 55 | 7, 6, 4, 56 | 6, 7, 5], 57 | dtype='uint16') 58 | 59 | vertexDim = 3 60 | colorDim = 4 61 | nVertices = 8 62 | 63 | # Helper function to calculate the frustum scale. 64 | # Accepts a field of view (in degrees) and returns the scale factor 65 | def calcFrustumScale(fFovDeg): 66 | degToRad = 3.14159 * 2.0 / 360.0 67 | fFovRad = fFovDeg * degToRad 68 | return 1.0 / tan(fFovRad / 2.0) 69 | 70 | # Global variable to represent the compiled shader program, written in GLSL 71 | theProgram = None 72 | 73 | # Global variable to represent the buffer that will hold the position vectors 74 | vertexBufferObject = None 75 | # Global variables to hold vertex array objects 76 | vao = None 77 | # Global variable to hold the position index buffer object 78 | indexBufferObject = None 79 | 80 | # Global variables to store the location of the shader's uniform variables 81 | modelToCameraMatrixUnif = None 82 | cameraToClipMatrixUnif = None 83 | 84 | # Global display variables 85 | cameraToClipMatrix = np.zeros((4,4), dtype='float32') 86 | fFrustumScale = calcFrustumScale(45.0) 87 | 88 | # Set up the list of shaders, and call functions to compile them 89 | def initializeProgram(): 90 | shaderList = [] 91 | 92 | shaderList.append(loadShader(GL_VERTEX_SHADER, "PosColorLocalTransform.vert")) 93 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "ColorPassthrough.frag")) 94 | 95 | global theProgram 96 | theProgram = createProgram(shaderList) 97 | 98 | for shader in shaderList: 99 | glDeleteShader(shader) 100 | 101 | global modelToCameraMatrixUnif, cameraToClipMatrixUnif 102 | modelToCameraMatrixUnif = glGetUniformLocation(theProgram, "modelToCameraMatrix") 103 | cameraToClipMatrixUnif = glGetUniformLocation(theProgram, "cameraToClipMatrix") 104 | 105 | fzNear = 1.0 106 | fzFar = 61.0 107 | 108 | global cameraToClipMatrix 109 | # Note that this and the transformation matrix below are both 110 | # ROW-MAJOR ordered. Thus, it is necessary to pass a transpose 111 | # of the matrix to the glUniform assignment function. 112 | cameraToClipMatrix[0][0] = fFrustumScale 113 | cameraToClipMatrix[1][1] = fFrustumScale 114 | cameraToClipMatrix[2][2] = (fzFar + fzNear) / (fzNear - fzFar) 115 | cameraToClipMatrix[2][3] = -1.0 116 | cameraToClipMatrix[3][2] = (2 * fzFar * fzNear) / (fzNear - fzFar) 117 | 118 | glUseProgram(theProgram) 119 | glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE, cameraToClipMatrix.transpose()) 120 | glUseProgram(0) 121 | 122 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 123 | def initializeVertexBuffer(): 124 | global vertexBufferObject, indexBufferObject 125 | vertexBufferObject = glGenBuffers(1) 126 | 127 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 128 | glBufferData( # PyOpenGL allows for the omission of the size parameter 129 | GL_ARRAY_BUFFER, 130 | vertexData, 131 | GL_STATIC_DRAW 132 | ) 133 | glBindBuffer(GL_ARRAY_BUFFER, 0) 134 | 135 | indexBufferObject = glGenBuffers(1) 136 | 137 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 138 | glBufferData( 139 | GL_ELEMENT_ARRAY_BUFFER, 140 | indexData, 141 | GL_STATIC_DRAW 142 | ) 143 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 144 | 145 | # Helper functions to scale the objects in various ways 146 | def calcLerpFactor(fElapsedTime, fLoopDuration): 147 | fValue = (fElapsedTime % fLoopDuration) / fLoopDuration 148 | if fValue > 0.5: 149 | fValue = 1.0 - fValue 150 | return fValue * 2.0 151 | 152 | def nullScale(fElapsedTime): 153 | newTransform = np.identity(4, dtype='float32') 154 | newTransform[0][0] = 1.0 #0.x 155 | newTransform[1][1] = 1.0 #1.y 156 | newTransform[2][2] = 1.0 #2.z 157 | newTransform[2][3] = -45 158 | return newTransform 159 | 160 | def staticUniformScale(fElapsedTime): 161 | newTransform = np.identity(4, dtype='float32') 162 | newTransform[0][0] = 4.0 #0.x 163 | newTransform[1][1] = 4.0 #1.y 164 | newTransform[2][2] = 4.0 #2.z 165 | newTransform[0][3] = -10.0 166 | newTransform[1][3] = -10.0 167 | newTransform[2][3] = -45.0 168 | return newTransform 169 | 170 | def staticNonUniformScale(fElapsedTime): 171 | newTransform = np.identity(4, dtype='float32') 172 | newTransform[0][0] = 0.5 #0.x 173 | newTransform[1][1] = 1.0 #1.y 174 | newTransform[2][2] = 10.0 #2.z 175 | newTransform[0][3] = -10.0 176 | newTransform[1][3] = 10.0 177 | newTransform[2][3] = -45.0 178 | return newTransform 179 | 180 | def dynamicUniformScale(fElapsedTime): 181 | fLoopDuration = 3.0 182 | lerp = calcLerpFactor(fElapsedTime, fLoopDuration) 183 | 184 | newTransform = np.identity(4, dtype='float32') 185 | newTransform[0][0] = 1.0 #0.x 186 | newTransform[1][1] = 4.0 #1.y 187 | newTransform[2][2] = lerp #2.z 188 | newTransform[0][3] = 10.0 189 | newTransform[1][3] = 10.0 190 | newTransform[2][3] = -45.0 191 | return newTransform 192 | 193 | def dynamicNonUniformScale(fElapsedTime): 194 | fXLoopDuration = 3.0 195 | fZLoopDuration = 5.0 196 | xlerp = calcLerpFactor(fElapsedTime, fXLoopDuration) 197 | zlerp = calcLerpFactor(fElapsedTime, fZLoopDuration) 198 | 199 | newTransform = np.identity(4, dtype='float32') 200 | newTransform[0][0] = xlerp #0.x 201 | newTransform[1][1] = 1.0 #1.y 202 | newTransform[2][2] = zlerp #2.z 203 | newTransform[0][3] = 10.0 204 | newTransform[1][3] = -10.0 205 | newTransform[2][3] = -45.0 206 | return newTransform 207 | 208 | 209 | # A list of the helper offset functions. 210 | # Note that this does not require a structure def in python. 211 | # Each function is written to return the complete transform matrix. 212 | g_instanceList =[ 213 | nullScale, 214 | staticUniformScale, 215 | staticNonUniformScale, 216 | dynamicUniformScale, 217 | dynamicNonUniformScale] 218 | 219 | # Initialize the OpenGL environment 220 | def init(): 221 | initializeProgram() 222 | initializeVertexBuffer() 223 | 224 | global vao 225 | vao = glGenVertexArrays(1) 226 | glBindVertexArray(vao) 227 | 228 | sizeOfFloat = 4 # all our arrays are dtype='float32' 229 | colorDataOffset = c_void_p(vertexDim * nVertices * sizeOfFloat) 230 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 231 | glEnableVertexAttribArray(0) 232 | glEnableVertexAttribArray(1) 233 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 234 | glVertexAttribPointer(1, colorDim, GL_FLOAT, GL_FALSE, 0, colorDataOffset) 235 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 236 | 237 | glBindVertexArray(0) 238 | 239 | glEnable(GL_CULL_FACE) 240 | glCullFace(GL_BACK) 241 | glFrontFace(GL_CW) 242 | 243 | glEnable(GL_DEPTH_TEST) 244 | glDepthMask(GL_TRUE) 245 | glDepthFunc(GL_LEQUAL) 246 | glDepthRange(0.0, 1.0) 247 | 248 | # Called to update the display. 249 | # Because we are using double-buffering, glutSwapBuffers is called at the end 250 | # to write the rendered buffer to the display. 251 | def display(): 252 | glClearColor(0.0, 0.0, 0.0, 0.0) 253 | glClearDepth(1.0) 254 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 255 | 256 | glUseProgram(theProgram) 257 | 258 | glBindVertexArray(vao) 259 | 260 | fElapsedTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0 261 | for func in g_instanceList: 262 | transformMatrix = func(fElapsedTime) 263 | 264 | glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, transformMatrix.transpose()) 265 | glDrawElements(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None) 266 | 267 | glBindVertexArray(0) 268 | glUseProgram(0) 269 | 270 | glutSwapBuffers() 271 | glutPostRedisplay() 272 | 273 | # keyboard input handler: exits the program if 'esc' is pressed 274 | def keyboard(key, x, y): 275 | 276 | # ord() is needed to get the keycode 277 | keyval = ord(key) 278 | if keyval == 27: 279 | glutLeaveMainLoop() 280 | return 281 | 282 | # Called whenever the window's size changes (including once when the program starts) 283 | def reshape(w, h): 284 | global cameraToClipMatrix 285 | cameraToClipMatrix[0][0] = fFrustumScale * (h / float(w)) 286 | cameraToClipMatrix[1][1] = fFrustumScale 287 | 288 | glUseProgram(theProgram) 289 | glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE, cameraToClipMatrix.transpose()) 290 | glUseProgram(0) 291 | 292 | glViewport(0, 0, w, h) 293 | 294 | # The main function 295 | def main(): 296 | glutInit() 297 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 298 | glutInitDisplayMode (displayMode) 299 | 300 | glutInitContextVersion(3,3) 301 | glutInitContextProfile(GLUT_CORE_PROFILE) 302 | 303 | width = 500; 304 | height = 500; 305 | glutInitWindowSize (width, height) 306 | 307 | glutInitWindowPosition (300, 200) 308 | 309 | window = glutCreateWindow("Tutorial Window") 310 | 311 | init() 312 | glutDisplayFunc(display) 313 | glutReshapeFunc(reshape) 314 | glutKeyboardFunc(keyboard) 315 | 316 | glutMainLoop(); 317 | 318 | if __name__ == '__main__': 319 | main() 320 | -------------------------------------------------------------------------------- /Tut 06 Objects in Motion/Translation.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from Translation.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | 5 | from OpenGL.GLUT import * 6 | from OpenGL.GLUT.freeglut import * 7 | from OpenGL.GLU import * 8 | from OpenGL.GL import * 9 | import numpy as np 10 | from framework import * 11 | from math import tan, cos, sin 12 | 13 | # A 1-D array of 3 4-D vertices (X,Y,Z,W) 14 | # Note that this must be a numpy array, since as of 15 | # 170111 support for lists has not been implemented. 16 | vertexData = np.array([ 17 | +1.0, +1.0, +1.0, 18 | -1.0, -1.0, +1.0, 19 | -1.0, +1.0, -1.0, 20 | +1.0, -1.0, -1.0, 21 | 22 | -1.0, -1.0, -1.0, 23 | +1.0, +1.0, -1.0, 24 | +1.0, -1.0, +1.0, 25 | -1.0, +1.0, +1.0, 26 | 27 | # GREEN_COLOR 28 | 0.0, 1.0, 0.0, 1.0, 29 | # BLUE_COLOR 30 | 0.0, 0.0, 1.0, 1.0, 31 | # RED_COLOR 32 | 1.0, 0.0, 0.0, 1.0, 33 | # BROWN_COLOR 34 | 0.5, 0.5, 0.0, 1.0, 35 | 36 | # GREEN_COLOR 37 | 0.0, 1.0, 0.0, 1.0, 38 | # BLUE_COLOR 39 | 0.0, 0.0, 1.0, 1.0, 40 | # RED_COLOR 41 | 1.0, 0.0, 0.0, 1.0, 42 | # BROWN_COLOR 43 | 0.5, 0.5, 0.0, 1.0], 44 | dtype='float32' 45 | ) 46 | 47 | indexData = np.array([ 48 | 0, 1, 2, 49 | 1, 0, 3, 50 | 2, 3, 0, 51 | 3, 2, 1, 52 | 53 | 5, 4, 6, 54 | 4, 5, 7, 55 | 7, 6, 4, 56 | 6, 7, 5], 57 | dtype='uint16') 58 | 59 | vertexDim = 3 60 | colorDim = 4 61 | nVertices = 8 62 | 63 | # Helper function to calculate the frustum scale. 64 | # Accepts a field of view (in degrees) and returns the scale factor 65 | def calcFrustumScale(fFovDeg): 66 | degToRad = 3.14159 * 2.0 / 360.0 67 | fFovRad = fFovDeg * degToRad 68 | return 1.0 / tan(fFovRad / 2.0) 69 | 70 | # Global variable to represent the compiled shader program, written in GLSL 71 | theProgram = None 72 | 73 | # Global variable to represent the buffer that will hold the position vectors 74 | vertexBufferObject = None 75 | # Global variables to hold vertex array objects 76 | vao = None 77 | # Global variable to hold the position index buffer object 78 | indexBufferObject = None 79 | 80 | # Global variables to store the location of the shader's uniform variables 81 | modelToCameraMatrixUnif = None 82 | cameraToClipMatrixUnif = None 83 | 84 | # Global display variables 85 | cameraToClipMatrix = np.zeros((4,4), dtype='float32') 86 | fFrustumScale = calcFrustumScale(45.0) 87 | 88 | # Set up the list of shaders, and call functions to compile them 89 | def initializeProgram(): 90 | shaderList = [] 91 | 92 | shaderList.append(loadShader(GL_VERTEX_SHADER, "PosColorLocalTransform.vert")) 93 | shaderList.append(loadShader(GL_FRAGMENT_SHADER, "ColorPassthrough.frag")) 94 | 95 | global theProgram 96 | theProgram = createProgram(shaderList) 97 | 98 | for shader in shaderList: 99 | glDeleteShader(shader) 100 | 101 | global modelToCameraMatrixUnif, cameraToClipMatrixUnif 102 | modelToCameraMatrixUnif = glGetUniformLocation(theProgram, "modelToCameraMatrix") 103 | cameraToClipMatrixUnif = glGetUniformLocation(theProgram, "cameraToClipMatrix") 104 | 105 | fzNear = 1.0 106 | fzFar = 45.0 107 | 108 | global cameraToClipMatrix 109 | # Note that this and the transformation matrix below are both 110 | # ROW-MAJOR ordered. Thus, it is necessary to pass a transpose 111 | # of the matrix to the glUniform assignment function. 112 | cameraToClipMatrix[0][0] = fFrustumScale 113 | cameraToClipMatrix[1][1] = fFrustumScale 114 | cameraToClipMatrix[2][2] = (fzFar + fzNear) / (fzNear - fzFar) 115 | cameraToClipMatrix[2][3] = -1.0 116 | cameraToClipMatrix[3][2] = (2 * fzFar * fzNear) / (fzNear - fzFar) 117 | 118 | glUseProgram(theProgram) 119 | glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE, cameraToClipMatrix.transpose()) 120 | glUseProgram(0) 121 | 122 | # Set up the vertex buffer that will store our vertex coordinates for OpenGL's access 123 | def initializeVertexBuffer(): 124 | global vertexBufferObject, indexBufferObject 125 | vertexBufferObject = glGenBuffers(1) 126 | 127 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 128 | glBufferData( # PyOpenGL allows for the omission of the size parameter 129 | GL_ARRAY_BUFFER, 130 | vertexData, 131 | GL_STATIC_DRAW 132 | ) 133 | glBindBuffer(GL_ARRAY_BUFFER, 0) 134 | 135 | indexBufferObject = glGenBuffers(1) 136 | 137 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 138 | glBufferData( 139 | GL_ELEMENT_ARRAY_BUFFER, 140 | indexData, 141 | GL_STATIC_DRAW 142 | ) 143 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) 144 | 145 | # Helper functions to return various types of transformation arrays 146 | def stationaryOffset(fElapsedTime): 147 | newTransform = np.identity(4, dtype='float32') 148 | newTransform[2][3] = -20 149 | return newTransform 150 | 151 | def ovalOffset(fElapsedTime): 152 | fLoopDuration = 3.0 153 | fScale = 3.14159 * 2.0 / fLoopDuration 154 | 155 | fCurrTimeThroughLoop = fElapsedTime % fLoopDuration 156 | 157 | newTransform = np.identity(4, dtype='float32') 158 | newTransform[0][3] = cos(fCurrTimeThroughLoop * fScale) * 4.0 159 | newTransform[1][3] = sin(fCurrTimeThroughLoop * fScale) * 6.0 160 | newTransform[2][3] = -20 161 | return newTransform 162 | 163 | def bottomCircleOffset(fElapsedTime): 164 | fLoopDuration = 12.0 165 | fScale = 3.14159 * 2.0 / fLoopDuration 166 | 167 | fCurrTimeThroughLoop = fElapsedTime % fLoopDuration 168 | 169 | newTransform = np.identity(4, dtype='float32') 170 | newTransform[0][3] = cos(fCurrTimeThroughLoop * fScale) * 4.0 171 | newTransform[1][3] = -3.5 172 | newTransform[2][3] = sin(fCurrTimeThroughLoop * fScale) * 5.0 - 20.0 173 | return newTransform 174 | 175 | # A list of the helper offset functions. 176 | # Note that this does not require a structure def in python. 177 | # Each function is written to return the complete transform matrix. 178 | g_instanceList =[ 179 | stationaryOffset, 180 | ovalOffset, 181 | bottomCircleOffset] 182 | 183 | # Initialize the OpenGL environment 184 | def init(): 185 | initializeProgram() 186 | initializeVertexBuffer() 187 | 188 | global vao 189 | vao = glGenVertexArrays(1) 190 | glBindVertexArray(vao) 191 | 192 | sizeOfFloat = 4 # all our arrays are dtype='float32' 193 | colorDataOffset = c_void_p(vertexDim * nVertices * sizeOfFloat) 194 | glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject) 195 | glEnableVertexAttribArray(0) 196 | glEnableVertexAttribArray(1) 197 | glVertexAttribPointer(0, vertexDim, GL_FLOAT, GL_FALSE, 0, None) 198 | glVertexAttribPointer(1, colorDim, GL_FLOAT, GL_FALSE, 0, colorDataOffset) 199 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObject) 200 | 201 | glBindVertexArray(0) 202 | 203 | glEnable(GL_CULL_FACE) 204 | glCullFace(GL_BACK) 205 | glFrontFace(GL_CW) 206 | 207 | glEnable(GL_DEPTH_TEST) 208 | glDepthMask(GL_TRUE) 209 | glDepthFunc(GL_LEQUAL) 210 | glDepthRange(0.0, 1.0) 211 | 212 | # Called to update the display. 213 | # Because we are using double-buffering, glutSwapBuffers is called at the end 214 | # to write the rendered buffer to the display. 215 | def display(): 216 | glClearColor(0.0, 0.0, 0.0, 0.0) 217 | glClearDepth(1.0) 218 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 219 | 220 | glUseProgram(theProgram) 221 | 222 | glBindVertexArray(vao) 223 | 224 | fElapsedTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0 225 | for func in g_instanceList: 226 | transformMatrix = func(fElapsedTime) 227 | 228 | glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, transformMatrix.transpose()) 229 | glDrawElements(GL_TRIANGLES, len(indexData), GL_UNSIGNED_SHORT, None) 230 | 231 | glBindVertexArray(0) 232 | glUseProgram(0) 233 | 234 | glutSwapBuffers() 235 | glutPostRedisplay() 236 | 237 | # keyboard input handler: exits the program if 'esc' is pressed 238 | def keyboard(key, x, y): 239 | 240 | # ord() is needed to get the keycode 241 | keyval = ord(key) 242 | if keyval == 27: 243 | glutLeaveMainLoop() 244 | return 245 | 246 | # Called whenever the window's size changes (including once when the program starts) 247 | def reshape(w, h): 248 | global cameraToClipMatrix 249 | cameraToClipMatrix[0][0] = fFrustumScale * (h / float(w)) 250 | cameraToClipMatrix[1][1] = fFrustumScale 251 | 252 | glUseProgram(theProgram) 253 | glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE, cameraToClipMatrix.transpose()) 254 | glUseProgram(0) 255 | 256 | glViewport(0, 0, w, h) 257 | 258 | # The main function 259 | def main(): 260 | glutInit() 261 | displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL; 262 | glutInitDisplayMode (displayMode) 263 | 264 | glutInitContextVersion(3,3) 265 | glutInitContextProfile(GLUT_CORE_PROFILE) 266 | 267 | width = 500; 268 | height = 500; 269 | glutInitWindowSize (width, height) 270 | 271 | glutInitWindowPosition (300, 200) 272 | 273 | window = glutCreateWindow("Tutorial Window") 274 | 275 | init() 276 | glutDisplayFunc(display) 277 | glutReshapeFunc(reshape) 278 | glutKeyboardFunc(keyboard) 279 | 280 | glutMainLoop(); 281 | 282 | if __name__ == '__main__': 283 | main() 284 | -------------------------------------------------------------------------------- /Tut 06 Objects in Motion/data/ColorMultUniform.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | smooth in vec4 theColor; 4 | uniform vec4 baseColor; 5 | 6 | out vec4 outputColor; 7 | 8 | void main() 9 | { 10 | outputColor = theColor * baseColor; 11 | } 12 | -------------------------------------------------------------------------------- /Tut 06 Objects in Motion/data/ColorPassthrough.frag: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | smooth in vec4 theColor; 4 | 5 | out vec4 outputColor; 6 | 7 | void main() 8 | { 9 | outputColor = theColor; 10 | } 11 | -------------------------------------------------------------------------------- /Tut 06 Objects in Motion/data/PosColorLocalTransform.vert: -------------------------------------------------------------------------------- 1 | #version 330 2 | 3 | layout(location = 0) in vec4 position; 4 | layout(location = 1) in vec4 color; 5 | 6 | smooth out vec4 theColor; 7 | 8 | uniform mat4 cameraToClipMatrix; 9 | uniform mat4 modelToCameraMatrix; 10 | 11 | void main() 12 | { 13 | vec4 cameraPos = modelToCameraMatrix * position; 14 | gl_Position = cameraToClipMatrix * cameraPos; 15 | theColor = color; 16 | } 17 | -------------------------------------------------------------------------------- /Tut 06 Objects in Motion/framework.py: -------------------------------------------------------------------------------- 1 | # Mario Rosasco, 2016 2 | # adapted from framework.cpp, Copyright (C) 2010-2012 by Jason L. McKesson 3 | # This file is licensed under the MIT License. 4 | # 5 | # NB: Unlike in the framework.cpp organization, the main loop is contained 6 | # in the tutorial files, not in this framework file. Additionally, a copy of 7 | # this module file must exist in the same directory as the tutorial files 8 | # to be imported properly. 9 | 10 | from OpenGL.GLUT import * 11 | from OpenGL.GLU import * 12 | from OpenGL.GL import * 13 | import os 14 | import sys 15 | 16 | # Function that creates and compiles shaders according to the given type (a GL enum value) and 17 | # shader program (a file containing a GLSL program). 18 | def loadShader(shaderType, shaderFile): 19 | # check if file exists, get full path name 20 | strFilename = findFileOrThrow(shaderFile) 21 | shaderData = None 22 | with open(strFilename, 'r') as f: 23 | shaderData = f.read() 24 | 25 | shader = glCreateShader(shaderType) 26 | glShaderSource(shader, shaderData) # note that this is a simpler function call than in C 27 | 28 | # This shader compilation is more explicit than the one used in 29 | # framework.cpp, which relies on a glutil wrapper function. 30 | # This is made explicit here mainly to decrease dependence on pyOpenGL 31 | # utilities and wrappers, which docs caution may change in future versions. 32 | glCompileShader(shader) 33 | 34 | status = glGetShaderiv(shader, GL_COMPILE_STATUS) 35 | if status == GL_FALSE: 36 | # Note that getting the error log is much simpler in Python than in C/C++ 37 | # and does not require explicit handling of the string buffer 38 | strInfoLog = glGetShaderInforLog(shader) 39 | strShaderType = "" 40 | if shaderType is GL_VERTEX_SHADER: 41 | strShaderType = "vertex" 42 | elif shaderType is GL_GEOMETRY_SHADER: 43 | strShaderType = "geometry" 44 | elif shaderType is GL_FRAGMENT_SHADER: 45 | strShaderType = "fragment" 46 | 47 | print "Compilation failure for " + strShaderType + " shader:\n" + strInfoLog 48 | 49 | return shader 50 | 51 | # Function that accepts a list of shaders, compiles them, and returns a handle to the compiled program 52 | def createProgram(shaderList): 53 | program = glCreateProgram() 54 | 55 | for shader in shaderList: 56 | glAttachShader(program, shader) 57 | 58 | glLinkProgram(program) 59 | 60 | status = glGetProgramiv(program, GL_LINK_STATUS) 61 | if status == GL_FALSE: 62 | # Note that getting the error log is much simpler in Python than in C/C++ 63 | # and does not require explicit handling of the string buffer 64 | strInfoLog = glGetProgramInfoLog(program) 65 | print "Linker failure: \n" + strInfoLog 66 | 67 | for shader in shaderList: 68 | glDetachShader(program, shader) 69 | 70 | return program 71 | 72 | 73 | # Helper function to locate and open the target file (passed in as a string). 74 | # Returns the full path to the file as a string. 75 | def findFileOrThrow(strBasename): 76 | # Keep constant names in C-style convention, for readability 77 | # when comparing to C(/C++) code. 78 | LOCAL_FILE_DIR = "data" + os.sep 79 | GLOBAL_FILE_DIR = ".." + os.sep + "data" + os.sep 80 | 81 | strFilename = LOCAL_FILE_DIR + strBasename 82 | if os.path.isfile(strFilename): 83 | return strFilename 84 | 85 | strFilename = GLOBAL_FILE_DIR + strBasename 86 | if os.path.isfile(strFilename): 87 | return strFilename 88 | 89 | raise IOError('Could not find target file ' + strBasename) 90 | -------------------------------------------------------------------------------- /Tut 06 Objects in Motion/framework.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DrxMario/PyOpenGL-Tutorial/e91de55d7dbd856e0973b6c057ef6f95fc863585/Tut 06 Objects in Motion/framework.pyc --------------------------------------------------------------------------------