├── TutorialsComp.pdf ├── 03_OpenGLs_moving_triangle ├── data │ ├── standard.vert │ ├── positionOffset.vert │ ├── standard.frag │ ├── calcOffset.vert │ └── calcColor.frag ├── 03_vertCalcOffset.py ├── 03_fragChangeColor.py ├── 03_vertPositionOffset.py └── 03_cpuPositionOffset.py ├── 02_playing_with_colors ├── data │ ├── FragPosition.vert │ ├── VertexColors.frag │ ├── VertexColors.vert │ └── FragPosition.frag ├── 02_FragPosition.py └── 02_VertexColors.py ├── 05_objects_in_depth ├── data │ ├── Standard.frag │ ├── Standard.vert │ ├── fighting_data.py │ └── vertex_data.py ├── 05_BaseVertexOverlap.py ├── 05_DepthBuffer.py ├── 05_VertexClipping.py ├── 05_DepthClamping.py ├── 05_OverlapNoDepth.py └── 05_DepthFighting.py ├── 04_objects_at_rest ├── data │ ├── StandardColors.frag │ ├── OrthoWithOffset.vert │ ├── MatrixPerspective.vert │ ├── ManualPerspective.vert │ ├── vertices_perspective.py │ └── vertices_ortho.py ├── 04_OrthoCube.py ├── 04_ShaderPerspective.py ├── 04_MatrixPerspective.py ├── 04_AspectRatio.py └── 04_AspectRatio_interactive.py ├── 06_objects_in_motion ├── data │ ├── ColorPassthrough.frag │ ├── ColorMultUniform.frag │ ├── PosColorLocalTransform.vert │ ├── vertex_data.py │ └── hierarchy_data.py ├── 06_Translation.py ├── 06_Scale.py ├── 06_Rotations.py └── 06_Hierarchy.py ├── MIT License.txt ├── README.md ├── .gitignore ├── 01_hello_triangle ├── 01_hello_triangle.py └── 01_hello_triangle_manually.py └── myframework.py /TutorialsComp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mekire/gltut-pygame/HEAD/TutorialsComp.pdf -------------------------------------------------------------------------------- /03_OpenGLs_moving_triangle/data/standard.vert: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | in vec4 position; 4 | 5 | void main() 6 | { 7 | gl_Position = position; 8 | } 9 | -------------------------------------------------------------------------------- /02_playing_with_colors/data/FragPosition.vert: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | in vec4 position; 4 | 5 | void main() 6 | { 7 | gl_Position = position; 8 | } 9 | -------------------------------------------------------------------------------- /05_objects_in_depth/data/Standard.frag: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | smooth in vec4 theColor; 4 | 5 | out vec4 outputColor; 6 | 7 | void main() 8 | { 9 | outputColor = theColor; 10 | } 11 | -------------------------------------------------------------------------------- /04_objects_at_rest/data/StandardColors.frag: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | smooth in vec4 theColor; 4 | 5 | out vec4 outputColor; 6 | 7 | void main() 8 | { 9 | outputColor = theColor; 10 | } 11 | -------------------------------------------------------------------------------- /02_playing_with_colors/data/VertexColors.frag: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | smooth in vec4 theColor; 4 | 5 | out vec4 outputColor; 6 | 7 | void main() 8 | { 9 | outputColor = theColor; 10 | } 11 | -------------------------------------------------------------------------------- /06_objects_in_motion/data/ColorPassthrough.frag: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | smooth in vec4 theColor; 4 | 5 | out vec4 outputColor; 6 | 7 | void main() 8 | { 9 | outputColor = theColor; 10 | } 11 | -------------------------------------------------------------------------------- /02_playing_with_colors/data/VertexColors.vert: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | in vec4 position; 4 | in vec4 color; 5 | 6 | smooth out vec4 theColor; 7 | 8 | void main() 9 | { 10 | gl_Position = position; 11 | theColor = color; 12 | } 13 | -------------------------------------------------------------------------------- /06_objects_in_motion/data/ColorMultUniform.frag: -------------------------------------------------------------------------------- 1 | #version 130 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 | -------------------------------------------------------------------------------- /03_OpenGLs_moving_triangle/data/positionOffset.vert: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | in vec4 position; 4 | 5 | uniform vec2 offset; 6 | 7 | void main() 8 | { 9 | vec4 total_offset = vec4(offset.x, offset.y, 0.0, 0.0); 10 | gl_Position = position + total_offset; 11 | } 12 | -------------------------------------------------------------------------------- /02_playing_with_colors/data/FragPosition.frag: -------------------------------------------------------------------------------- 1 | #version 130 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, 0.0f, 0.0f, 1.0f), vec4(0.0f, 1.0f, 0.0f, 1.0f), lerpValue); 10 | } 11 | -------------------------------------------------------------------------------- /03_OpenGLs_moving_triangle/data/standard.frag: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | out vec4 outputColor; 4 | 5 | void main() 6 | { 7 | float lerp_value = gl_FragCoord.y / 500.0f; 8 | outputColor = mix(vec4(1.0f, 0.0f, 1.0f, 1.0f), vec4(0.0f, 1.0f, 0.0f, 1.0f), lerp_value); 9 | } 10 | -------------------------------------------------------------------------------- /04_objects_at_rest/data/OrthoWithOffset.vert: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | in vec4 position; 4 | 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 | -------------------------------------------------------------------------------- /04_objects_at_rest/data/MatrixPerspective.vert: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | in vec4 position; 4 | 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 | -------------------------------------------------------------------------------- /05_objects_in_depth/data/Standard.vert: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | in vec4 position; 4 | 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 | -------------------------------------------------------------------------------- /06_objects_in_motion/data/PosColorLocalTransform.vert: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | in vec4 position; 4 | 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 | -------------------------------------------------------------------------------- /03_OpenGLs_moving_triangle/data/calcOffset.vert: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | in vec4 position; 4 | 5 | uniform float period; 6 | uniform float time; 7 | 8 | void main() 9 | { 10 | float timeScale = 3.14159f * 2.0f / period; 11 | 12 | float currTime = mod(time, period); 13 | vec4 totalOffset = vec4( 14 | cos(currTime * timeScale) * 0.5f, 15 | sin(currTime * timeScale) * 0.5f, 16 | 0.0f, 17 | 0.0f); 18 | 19 | gl_Position = position + totalOffset; 20 | } 21 | -------------------------------------------------------------------------------- /03_OpenGLs_moving_triangle/data/calcColor.frag: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | out vec4 outputColor; 4 | 5 | uniform float frag_period; 6 | uniform float time; 7 | 8 | const vec4 firstColor = vec4(1.0f, 0.0f, 0.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, frag_period); 14 | float currLerp = currTime / frag_period; 15 | 16 | outputColor = mix(firstColor, secondColor, currLerp); 17 | } 18 | -------------------------------------------------------------------------------- /04_objects_at_rest/data/ManualPerspective.vert: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | in vec4 position; 4 | 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 | -------------------------------------------------------------------------------- /05_objects_in_depth/data/fighting_data.py: -------------------------------------------------------------------------------- 1 | NUMBER_OF_VERTICES = 8 2 | 3 | _Z_OFFSET = 1.5 4 | 5 | _COLOR = {"GREEN" : [0.0,1.0,0.0,1.0], 6 | "BLUE" : [0.0,0.0,1.0,1.0], 7 | "RED" : [1.0,0.0,0.0,1.0]} 8 | 9 | _POSITIONS = [#Front face positions 10 | -400.0, 400.0,0.0, 11 | 400.0, 400.0,0.0, 12 | 400.0,-400.0,0.0, 13 | -400.0,-400.0,0.0, 14 | #Rear face positions 15 | -200.0, 600.0,-_Z_OFFSET, 16 | 600.0, 600.0,-_Z_OFFSET, 17 | 600.0,-200.0,-_Z_OFFSET, 18 | -200.0,-200.0,-_Z_OFFSET] 19 | 20 | _COLORS = (#Object 1 colors 21 | _COLOR["GREEN"]*4+ 22 | _COLOR["RED" ]*4) 23 | 24 | VERTICES = _POSITIONS+_COLORS 25 | 26 | INDICES = [0,1,3, 27 | 1,2,3, 28 | 29 | 4,5,7, 30 | 5,6,7,] -------------------------------------------------------------------------------- /06_objects_in_motion/data/vertex_data.py: -------------------------------------------------------------------------------- 1 | NUMBER_OF_VERTICES = 8 2 | 3 | _COLOR = {"GREEN" : [0.0,1.0,0.0,1.0], 4 | "BLUE" : [0.0,0.0,1.0,1.0], 5 | "RED" : [1.0,0.0,0.0,1.0], 6 | "GREY" : [0.8,0.8,0.8,1.0], 7 | "BROWN" : [0.5,0.5,0.0,1.0]} 8 | 9 | _POSITIONS = [ 1.0, 1.0, 1.0, 10 | -1.0,-1.0, 1.0, 11 | -1.0, 1.0,-1.0, 12 | 1.0,-1.0,-1.0, 13 | 14 | -1.0,-1.0,-1.0, 15 | 1.0, 1.0,-1.0, 16 | 1.0,-1.0, 1.0, 17 | -1.0, 1.0, 1.0] 18 | 19 | _COLORS = (_COLOR["GREEN"]+_COLOR["BLUE"]+_COLOR["RED"]+_COLOR["BROWN"])*2 20 | 21 | VERTICES = _POSITIONS+_COLORS 22 | 23 | INDICES = [0,1,2, 24 | 1,0,3, 25 | 2,3,0, 26 | 3,2,1, 27 | 28 | 5,4,6, 29 | 4,5,7, 30 | 7,6,4, 31 | 6,7,5] -------------------------------------------------------------------------------- /MIT License.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2010-2012 by Jason L. McKesson 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is my effort to convert the C++ OpenGL tutorials written by Jason L. McKesson for his book "Learning Modern 3D Graphics Programming", into python. 2 | 3 | I use python 2.7, pyOpenGL, and pygame for this project. Dure to compatibility problems, GLSL 130 is used here rather than the GLSL 330 from the original tutorials. In order to make the code feel more like python I have changed variable names and program structure where I have deemed it appropriate. 4 | 5 | In the end this project is about me learning OpenGL, but, as I myself had considerable difficulty in finding adequate Python OpenGL examples that weren't hopelessly obsolete, I would like to share this. 6 | 7 | (I intend to translate the entire book into Python but this will likely take me some time.) 8 | 9 | The original tutorials and original C++ code can be found here: 10 | [arcsynthesis](http://arcsynthesis.org/gltut/) 11 | Note: The arcsynthesis site appears to have disappeared. 12 | Please refer to the [included pdf](https://github.com/Mekire/gltut-pygame/blob/master/TutorialsComp.pdf) for the original tutorial. 13 | 14 | Cheers, 15 | Sean J. McKiernan 16 | -Mek 17 | 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # project config files 2 | resources/*.json 3 | 4 | # local files related to pycharm 5 | .idea/ 6 | 7 | # Byte-compiled / optimized / DLL files 8 | __pycache__/ 9 | *.py[cod] 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | 45 | # Translations 46 | *.mo 47 | *.pot 48 | 49 | # Django stuff: 50 | *.log 51 | 52 | # Sphinx documentation 53 | docs/_build/ 54 | 55 | # PyBuilder 56 | target/ 57 | 58 | # ========================= 59 | # Operating System Files 60 | # ========================= 61 | 62 | # OSX 63 | # ========================= 64 | 65 | .DS_Store 66 | .AppleDouble 67 | .LSOverride 68 | 69 | # Icon must end with two \r 70 | Icon 71 | 72 | 73 | # Thumbnails 74 | ._* 75 | 76 | # Files that might appear on external disk 77 | .Spotlight-V100 78 | .Trashes 79 | 80 | # Directories potentially created on remote AFP share 81 | .AppleDB 82 | .AppleDesktop 83 | Network Trash Folder 84 | Temporary Items 85 | .apdisk 86 | 87 | # Windows 88 | # ========================= 89 | 90 | # Windows image file caches 91 | Thumbs.db 92 | ehthumbs.db 93 | 94 | # Folder config file 95 | Desktop.ini 96 | 97 | # Recycle Bin used on file shares 98 | $RECYCLE.BIN/ 99 | 100 | # Windows Installer files 101 | *.cab 102 | *.msi 103 | *.msm 104 | *.msp 105 | -------------------------------------------------------------------------------- /06_objects_in_motion/data/hierarchy_data.py: -------------------------------------------------------------------------------- 1 | NUMBER_OF_VERTICES = 24 2 | 3 | _COLOR = {"GREEN" : [0.0,1.0,0.0,1.0], 4 | "BLUE" : [0.0,0.0,1.0,1.0], 5 | "RED" : [1.0,0.0,0.0,1.0], 6 | "YELLOW" : [1.0,1.0,0.0,1.0], 7 | "GREY" : [0.8,0.8,0.8,1.0], 8 | "BROWN" : [0.5,0.5,0.0,1.0], 9 | "CYAN" : [0.0,1.0,1.0,1.0], 10 | "MAGENTA": [1.0,0.0,1.0,1.0]} 11 | 12 | _POSITIONS = [#Front 13 | 1.0, 1.0, 1.0, 14 | 1.0,-1.0, 1.0, 15 | -1.0,-1.0, 1.0, 16 | -1.0, 1.0, 1.0, 17 | #Top 18 | 1.0, 1.0, 1.0, 19 | -1.0, 1.0, 1.0, 20 | -1.0, 1.0,-1.0, 21 | 1.0, 1.0,-1.0, 22 | #Left 23 | 1.0, 1.0, 1.0, 24 | 1.0, 1.0,-1.0, 25 | 1.0,-1.0,-1.0, 26 | 1.0,-1.0, 1.0, 27 | #Back 28 | 1.0, 1.0,-1.0, 29 | -1.0, 1.0,-1.0, 30 | -1.0,-1.0,-1.0, 31 | 1.0,-1.0,-1.0, 32 | #Bottom 33 | 1.0,-1.0, 1.0, 34 | 1.0,-1.0,-1.0, 35 | -1.0,-1.0,-1.0, 36 | -1.0,-1.0, 1.0, 37 | #Right 38 | -1.0, 1.0, 1.0, 39 | -1.0,-1.0, 1.0, 40 | -1.0,-1.0,-1.0, 41 | -1.0, 1.0,-1.0] 42 | 43 | _COLORS = (_COLOR["GREEN" ]*4+ 44 | _COLOR["BLUE" ]*4+ 45 | _COLOR["RED" ]*4+ 46 | _COLOR["YELLOW" ]*4+ 47 | _COLOR["CYAN" ]*4+ 48 | _COLOR["MAGENTA"]*4) 49 | 50 | VERTICES = _POSITIONS+_COLORS 51 | 52 | INDICES = [ 0, 1, 2, 53 | 2, 3, 0, 54 | 55 | 4, 5, 6, 56 | 6, 7, 4, 57 | 58 | 8, 9,10, 59 | 10,11, 8, 60 | 61 | 12,13,14, 62 | 14,15,12, 63 | 64 | 16,17,18, 65 | 18,19,16, 66 | 67 | 20,21,22, 68 | 22,23,20] -------------------------------------------------------------------------------- /04_objects_at_rest/04_OrthoCube.py: -------------------------------------------------------------------------------- 1 | import sys,os,math 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | sys.path.append("..") 6 | sys.path.append("data") 7 | import myframework 8 | from vertices_ortho import VERTICES 9 | 10 | class Shader(myframework.BaseShader): 11 | def __init__(self,vertices,vert_file,frag_file): 12 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file) 13 | GL.glEnable(GL.GL_CULL_FACE) 14 | GL.glCullFace(GL.GL_BACK) 15 | GL.glFrontFace(GL.GL_CW) 16 | 17 | def setup_uniforms(self): 18 | self.offset_location = GL.glGetUniformLocation(self.shader,"offset") 19 | 20 | def display(self): 21 | GL.glClearColor(1,1,1,1) 22 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 23 | 24 | GL.glUseProgram(self.shader) 25 | GL.glUniform2f(self.offset_location,0.5,0.25) 26 | color_data = GL.GLvoidp((len(self.vertices)*self.size_float)/2) 27 | 28 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.vbo) 29 | GL.glEnableVertexAttribArray(0) 30 | GL.glEnableVertexAttribArray(1) 31 | GL.glVertexAttribPointer(0,self.vert_comp,GL.GL_FLOAT,GL.GL_FALSE,0,None) 32 | GL.glVertexAttribPointer(1,self.vert_comp,GL.GL_FLOAT,GL.GL_FALSE,0,color_data) 33 | 34 | GL.glDrawArrays(GL.GL_TRIANGLES,0,36) 35 | 36 | GL.glDisableVertexAttribArray(0) 37 | GL.glDisableVertexAttribArray(1) 38 | GL.glUseProgram(0) 39 | 40 | def main(): 41 | pg.init() 42 | os.environ['SDL_VIDEO_CENTERED'] = '1' 43 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 44 | MyClock = pg.time.Clock() 45 | MyGL = Shader(VERTICES[:],os.path.join("data","OrthoWithOffset.vert"),os.path.join("data","StandardColors.frag")) 46 | done = False 47 | while not done: 48 | for event in pg.event.get(): 49 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 50 | done = True 51 | elif event.type == pg.KEYDOWN: 52 | pass 53 | elif event.type == pg.VIDEORESIZE: 54 | MyGL.reshape(*event.size) 55 | MyGL.display() 56 | pg.display.flip() 57 | MyClock.tick(60) 58 | 59 | if __name__ == '__main__': 60 | main() 61 | pg.quit() 62 | sys.exit() 63 | -------------------------------------------------------------------------------- /04_objects_at_rest/data/vertices_perspective.py: -------------------------------------------------------------------------------- 1 | VERTICES = [0.25,0.25,-1.25,1.0, 2 | 0.25,-0.25,-1.25,1.0, 3 | -0.25,0.25,-1.25,1.0, 4 | 0.25,-0.25,-1.25,1.0, 5 | -0.25,-0.25,-1.25,1.0, 6 | -0.25,0.25,-1.25,1.0, 7 | 0.25,0.25,-2.75,1.0, 8 | -0.25,0.25,-2.75,1.0, 9 | 0.25,-0.25,-2.75,1.0, 10 | 0.25,-0.25,-2.75,1.0, 11 | -0.25,0.25,-2.75,1.0, 12 | -0.25,-0.25,-2.75,1.0, 13 | -0.25,0.25,-1.25,1.0, 14 | -0.25,-0.25,-1.25,1.0, 15 | -0.25,-0.25,-2.75,1.0, 16 | -0.25,0.25,-1.25,1.0, 17 | -0.25,-0.25,-2.75,1.0, 18 | -0.25,0.25,-2.75,1.0, 19 | 0.25,0.25,-1.25,1.0, 20 | 0.25,-0.25,-2.75,1.0, 21 | 0.25,-0.25,-1.25,1.0, 22 | 0.25,0.25,-1.25,1.0, 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 | 0.25,0.25,-1.25,1.0, 27 | -0.25,0.25,-1.25,1.0, 28 | 0.25,0.25,-2.75,1.0, 29 | -0.25,0.25,-1.25,1.0, 30 | -0.25,0.25,-2.75,1.0, 31 | 0.25,-0.25,-2.75,1.0, 32 | -0.25,-0.25,-1.25,1.0, 33 | 0.25,-0.25,-1.25,1.0, 34 | 0.25,-0.25,-2.75,1.0, 35 | -0.25,-0.25,-2.75,1.0, 36 | -0.25,-0.25,-1.25,1.0, 37 | 0.0,0.0,1.0,1.0, 38 | 0.0,0.0,1.0,1.0, 39 | 0.0,0.0,1.0,1.0, 40 | 0.0,0.0,1.0,1.0, 41 | 0.0,0.0,1.0,1.0, 42 | 0.0,0.0,1.0,1.0, 43 | 0.8,0.8,0.8,1.0, 44 | 0.8,0.8,0.8,1.0, 45 | 0.8,0.8,0.8,1.0, 46 | 0.8,0.8,0.8,1.0, 47 | 0.8,0.8,0.8,1.0, 48 | 0.8,0.8,0.8,1.0, 49 | 0.0,1.0,0.0,1.0, 50 | 0.0,1.0,0.0,1.0, 51 | 0.0,1.0,0.0,1.0, 52 | 0.0,1.0,0.0,1.0, 53 | 0.0,1.0,0.0,1.0, 54 | 0.0,1.0,0.0,1.0, 55 | 0.5,0.5,0.0,1.0, 56 | 0.5,0.5,0.0,1.0, 57 | 0.5,0.5,0.0,1.0, 58 | 0.5,0.5,0.0,1.0, 59 | 0.5,0.5,0.0,1.0, 60 | 0.5,0.5,0.0,1.0, 61 | 1.0,0.0,0.0,1.0, 62 | 1.0,0.0,0.0,1.0, 63 | 1.0,0.0,0.0,1.0, 64 | 1.0,0.0,0.0,1.0, 65 | 1.0,0.0,0.0,1.0, 66 | 1.0,0.0,0.0,1.0, 67 | 0.0,1.0,1.0,1.0, 68 | 0.0,1.0,1.0,1.0, 69 | 0.0,1.0,1.0,1.0, 70 | 0.0,1.0,1.0,1.0, 71 | 0.0,1.0,1.0,1.0, 72 | 0.0,1.0,1.0,1.0] -------------------------------------------------------------------------------- /04_objects_at_rest/data/vertices_ortho.py: -------------------------------------------------------------------------------- 1 | VERTICES = [0.25, 0.25, 0.75, 1.0, 2 | 0.25, -0.25, 0.75, 1.0, 3 | -0.25, 0.25, 0.75, 1.0, 4 | 0.25, -0.25, 0.75, 1.0, 5 | -0.25, -0.25, 0.75, 1.0, 6 | -0.25, 0.25, 0.75, 1.0, 7 | 0.25, 0.25, -0.75, 1.0, 8 | -0.25, 0.25, -0.75, 1.0, 9 | 0.25, -0.25, -0.75, 1.0, 10 | 0.25, -0.25, -0.75, 1.0, 11 | -0.25, 0.25, -0.75, 1.0, 12 | -0.25, -0.25, -0.75, 1.0, 13 | -0.25, 0.25, 0.75, 1.0, 14 | -0.25, -0.25, 0.75, 1.0, 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 | -0.25, 0.25, -0.75, 1.0, 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 | 0.25, 0.25, 0.75, 1.0, 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 | 0.25, 0.25, 0.75, 1.0, 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 | -0.25, 0.25, -0.75, 1.0, 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 | 0.25, -0.25, -0.75, 1.0, 35 | -0.25, -0.25, -0.75, 1.0, 36 | -0.25, -0.25, 0.75, 1.0, 37 | 38 | 0.0, 0.0, 1.0, 1.0, 39 | 0.0,0.0, 1.0, 1.0, 40 | 0.0, 0.0,1.0, 1.0, 41 | 0.0, 0.0, 1.0,1.0, 42 | 0.0, 0.0, 1.0, 1.0, 43 | 0.0, 0.0, 1.0, 1.0, 44 | 0.8,0.8, 0.8, 1.0, 45 | 0.8, 0.8,0.8, 1.0, 46 | 0.8, 0.8, 0.8,1.0, 47 | 0.8, 0.8, 0.8, 1.0, 48 | 0.8, 0.8, 0.8, 1.0, 49 | 0.8,0.8, 0.8, 1.0, 50 | 0.0, 1.0,0.0, 1.0, 51 | 0.0, 1.0, 0.0,1.0, 52 | 0.0, 1.0, 0.0, 1.0, 53 | 0.0, 1.0, 0.0, 1.0, 54 | 0.0,1.0, 0.0, 1.0, 55 | 0.0, 1.0,0.0, 1.0, 56 | 0.5, 0.5, 0.0,1.0, 57 | 0.5, 0.5, 0.0, 1.0, 58 | 0.5, 0.5, 0.0, 1.0, 59 | 0.5,0.5, 0.0, 1.0, 60 | 0.5, 0.5,0.0, 1.0, 61 | 0.5, 0.5, 0.0,1.0, 62 | 1.0, 0.0, 0.0, 1.0, 63 | 1.0, 0.0, 0.0, 1.0, 64 | 1.0,0.0, 0.0, 1.0, 65 | 1.0, 0.0,0.0, 1.0, 66 | 1.0, 0.0, 0.0,1.0, 67 | 1.0, 0.0, 0.0, 1.0, 68 | 0.0, 1.0, 1.0, 1.0, 69 | 0.0,1.0, 1.0, 1.0, 70 | 0.0, 1.0,1.0, 1.0, 71 | 0.0, 1.0, 1.0,1.0, 72 | 0.0, 1.0, 1.0, 1.0, 73 | 0.0, 1.0, 1.0, 1.0] -------------------------------------------------------------------------------- /04_objects_at_rest/04_ShaderPerspective.py: -------------------------------------------------------------------------------- 1 | import sys,os,math 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | sys.path.append("..") 6 | sys.path.append("data") 7 | import myframework 8 | from vertices_perspective import VERTICES 9 | 10 | class Shader(myframework.BaseShader): 11 | def __init__(self,vertices,vert_file,frag_file): 12 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file) 13 | GL.glEnable(GL.GL_CULL_FACE) 14 | GL.glCullFace(GL.GL_BACK) 15 | GL.glFrontFace(GL.GL_CW) 16 | 17 | def setup_uniforms(self): 18 | self.offset_location = GL.glGetUniformLocation(self.shader,"offset") 19 | self.frustum_scale_unif = GL.glGetUniformLocation(self.shader,"frustumScale") 20 | self.z_near_unif = GL.glGetUniformLocation(self.shader,"zNear") 21 | self.z_far_unif = GL.glGetUniformLocation(self.shader,"zFar") 22 | 23 | GL.glUseProgram(self.shader) 24 | GL.glUniform1f(self.frustum_scale_unif,1.0) 25 | GL.glUniform1f(self.z_near_unif,1.0) 26 | GL.glUniform1f(self.z_far_unif,3.0) 27 | GL.glUseProgram(0) 28 | 29 | def display(self): 30 | GL.glClearColor(0,0,0,0) 31 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 32 | 33 | GL.glUseProgram(self.shader) 34 | GL.glUniform2f(self.offset_location,0.5,0.5) 35 | color_data = GL.GLvoidp((len(self.vertices)*self.size_float)/2) 36 | 37 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.vbo) 38 | GL.glEnableVertexAttribArray(0) 39 | GL.glEnableVertexAttribArray(1) 40 | GL.glVertexAttribPointer(0,self.vert_comp,GL.GL_FLOAT,GL.GL_FALSE,0,None) 41 | GL.glVertexAttribPointer(1,self.vert_comp,GL.GL_FLOAT,GL.GL_FALSE,0,color_data) 42 | 43 | GL.glDrawArrays(GL.GL_TRIANGLES,0,36) 44 | 45 | GL.glDisableVertexAttribArray(0) 46 | GL.glDisableVertexAttribArray(1) 47 | GL.glUseProgram(0) 48 | 49 | def main(): 50 | pg.init() 51 | os.environ['SDL_VIDEO_CENTERED'] = '1' 52 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 53 | MyClock = pg.time.Clock() 54 | MyGL = Shader(VERTICES[:],os.path.join("data","ManualPerspective.vert"),os.path.join("data","StandardColors.frag")) 55 | done = False 56 | while not done: 57 | for event in pg.event.get(): 58 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 59 | done = True 60 | elif event.type == pg.KEYDOWN: 61 | pass 62 | elif event.type == pg.VIDEORESIZE: 63 | MyGL.reshape(*event.size) 64 | MyGL.display() 65 | pg.display.flip() 66 | MyClock.tick(60) 67 | 68 | if __name__ == '__main__': 69 | main() 70 | pg.quit() 71 | sys.exit() 72 | -------------------------------------------------------------------------------- /01_hello_triangle/01_hello_triangle.py: -------------------------------------------------------------------------------- 1 | """This version of "01_hello_triangle" makes use of compileProgram and 2 | compileShader from OpenGL.GL.shaders. This takes care of shader compilation, 3 | attachment and linking for us and is quite convenient. For a greater 4 | understanding of what is going on behind the scenes, see 5 | "01_hello_triangle_manually".""" 6 | from OpenGL import GL 7 | from OpenGL.GL.shaders import compileProgram,compileShader 8 | import pygame as pg,sys,os 9 | 10 | VERTICES = [ 0.75, 0.75, 0.0, 1.0, 11 | 0.75, -0.75, 0.0, 1.0, 12 | -0.75, -0.75, 0.0, 1.0] 13 | 14 | SIZE_FLOAT = VERT_COMPONENTS = 4 15 | 16 | #Shaders: 17 | VERT = """ 18 | #version 130 19 | in vec4 position; 20 | void main() 21 | { 22 | gl_Position = position; 23 | }""" 24 | 25 | FRAG = """ 26 | #version 130 27 | out vec4 outputColor; 28 | void main() 29 | { 30 | outputColor = vec4(0.0f, 1.0f, 0.0f, 1.0f); 31 | }""" 32 | 33 | class GLtests: 34 | def __init__(self): 35 | self.shader = compileProgram(compileShader(VERT,GL.GL_VERTEX_SHADER), 36 | compileShader(FRAG,GL.GL_FRAGMENT_SHADER)) 37 | self.vbo = None 38 | self.init_all() 39 | self.reshape(500,500) 40 | def init_all(self): 41 | self.init_vertex_buf() 42 | vao = GL.glGenVertexArrays(1) 43 | GL.glBindVertexArray(vao) 44 | def init_vertex_buf(self): 45 | self.vbo = GL.glGenBuffers(1) 46 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 47 | array_type = (GL.GLfloat*len(VERTICES)) 48 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(VERTICES)*SIZE_FLOAT, 49 | array_type(*VERTICES),GL.GL_STATIC_DRAW) 50 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 51 | 52 | def display(self): 53 | GL.glClearColor(1, 1, 1, 1) 54 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 55 | 56 | GL.glUseProgram(self.shader) 57 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 58 | GL.glEnableVertexAttribArray(0) 59 | GL.glVertexAttribPointer(0,VERT_COMPONENTS,GL.GL_FLOAT,False,0,None) 60 | GL.glDrawArrays(GL.GL_TRIANGLES, 0, len(VERTICES)//VERT_COMPONENTS) 61 | GL.glDisableVertexAttribArray(0) 62 | GL.glUseProgram(0) 63 | 64 | def reshape(self,width,height): 65 | GL.glViewport(0, 0, width, height) 66 | 67 | def main(): 68 | pg.init() 69 | os.environ['SDL_VIDEO_CENTERED'] = '1' 70 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF) 71 | MyClock = pg.time.Clock() 72 | MyGL = GLtests() 73 | while 1: 74 | for event in pg.event.get(): 75 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 76 | pg.quit();sys.exit() 77 | elif event.type == pg.KEYDOWN: 78 | pass 79 | MyGL.display() 80 | pg.display.flip() 81 | MyClock.tick(65) 82 | 83 | if __name__ == '__main__': 84 | main() 85 | -------------------------------------------------------------------------------- /04_objects_at_rest/04_MatrixPerspective.py: -------------------------------------------------------------------------------- 1 | import sys,os,math 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | sys.path.append("..") 6 | sys.path.append("data") 7 | import myframework 8 | from vertices_perspective import VERTICES 9 | 10 | class Shader(myframework.BaseShader): 11 | def __init__(self,vertices,vert_file,frag_file): 12 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file) 13 | GL.glEnable(GL.GL_CULL_FACE) 14 | GL.glCullFace(GL.GL_BACK) 15 | GL.glFrontFace(GL.GL_CW) 16 | 17 | def setup_uniforms(self): 18 | self.offset_location = GL.glGetUniformLocation(self.shader,"offset") 19 | self.perspective_matrix_unif = GL.glGetUniformLocation(self.shader,"perspectiveMatrix") 20 | self.frustum_scale = 1.0 21 | self.z_near,self.z_far = 0.5,3.0 22 | self.create_matrix() 23 | 24 | GL.glUseProgram(self.shader) 25 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 26 | GL.glUseProgram(0) 27 | 28 | def create_matrix(self): 29 | self.the_matrix = [0.0 for i in range(16)] 30 | self.the_matrix[0] = self.frustum_scale 31 | self.the_matrix[5] = self.frustum_scale 32 | self.the_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 33 | self.the_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 34 | self.the_matrix[11] = -1.0 35 | 36 | def display(self): 37 | GL.glClearColor(0,0,0,0) 38 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 39 | 40 | GL.glUseProgram(self.shader) 41 | GL.glUniform2f(self.offset_location,0.5,0.5) 42 | color_data = GL.GLvoidp((len(self.vertices)*self.size_float)/2) 43 | 44 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.vbo) 45 | GL.glEnableVertexAttribArray(0) 46 | GL.glEnableVertexAttribArray(1) 47 | GL.glVertexAttribPointer(0,self.vert_comp,GL.GL_FLOAT,GL.GL_FALSE,0,None) 48 | GL.glVertexAttribPointer(1,self.vert_comp,GL.GL_FLOAT,GL.GL_FALSE,0,color_data) 49 | 50 | GL.glDrawArrays(GL.GL_TRIANGLES,0,36) 51 | 52 | GL.glDisableVertexAttribArray(0) 53 | GL.glDisableVertexAttribArray(1) 54 | GL.glUseProgram(0) 55 | 56 | def main(): 57 | pg.init() 58 | os.environ['SDL_VIDEO_CENTERED'] = '1' 59 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 60 | MyClock = pg.time.Clock() 61 | MyGL = Shader(VERTICES[:],os.path.join("data","MatrixPerspective.vert"),os.path.join("data","StandardColors.frag")) 62 | done = False 63 | while not done: 64 | for event in pg.event.get(): 65 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 66 | done = True 67 | elif event.type == pg.KEYDOWN: 68 | pass 69 | elif event.type == pg.VIDEORESIZE: 70 | MyGL.reshape(*event.size) 71 | MyGL.display() 72 | pg.display.flip() 73 | MyClock.tick(60) 74 | 75 | if __name__ == '__main__': 76 | main() 77 | pg.quit() 78 | sys.exit() 79 | -------------------------------------------------------------------------------- /myframework.py: -------------------------------------------------------------------------------- 1 | from OpenGL import GL 2 | 3 | SHADER2STRING = {GL.GL_VERTEX_SHADER : "vertex", 4 | GL.GL_GEOMETRY_SHADER : "geometry", 5 | GL.GL_FRAGMENT_SHADER : "fragment"} 6 | 7 | class ShaderError(Exception): 8 | pass 9 | 10 | class BaseShader: 11 | def __init__(self,vertices,vert_file,frag_file,indices=None): 12 | self.vertices = vertices 13 | self.indices = indices 14 | self.shader = GL.glCreateProgram() 15 | self.size_float = self.vert_comp = 4 16 | self.size_short = 2 17 | self.vbo = None 18 | self.init_all(vert_file,frag_file) 19 | self.reshape(500,500) 20 | def init_all(self,vert_file,frag_file): 21 | self.attach_shaders(vert_file,frag_file) 22 | self.setup_attributes() 23 | self.setup_uniforms() 24 | self.init_vertex_buf() 25 | self.init_vao() 26 | def init_vao(self): 27 | self.vao = GL.glGenVertexArrays(1) 28 | GL.glBindVertexArray(self.vao) 29 | def init_vertex_buf(self): 30 | self.vbo = GL.glGenBuffers(1) 31 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 32 | ArrayType = (GL.GLfloat*len(self.vertices)) 33 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(self.vertices)*self.size_float, 34 | ArrayType(*self.vertices),GL.GL_STATIC_DRAW) 35 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 36 | def attach_shaders(self,vert_file,frag_file): 37 | vert,frag = self.load_shader_files(vert_file,frag_file) 38 | shade_list = [] 39 | shade_list.append(self.compile(GL.GL_VERTEX_SHADER,vert)) 40 | shade_list.append(self.compile(GL.GL_FRAGMENT_SHADER,frag)) 41 | for shade in shade_list: 42 | GL.glAttachShader(self.shader,shade) 43 | self.link() 44 | for shade in shade_list: 45 | GL.glDetachShader(self.shader,shade) 46 | GL.glDeleteShader(shade) 47 | def load_shader_files(self,vert_file,frag_file): 48 | with open(vert_file,'r') as myfile: 49 | vert = myfile.read() 50 | with open(frag_file,'r') as myfile: 51 | frag = myfile.read() 52 | return vert,frag 53 | def compile(self,shader_type,shader_str): 54 | shader = GL.glCreateShader(shader_type) 55 | GL.glShaderSource(shader,shader_str) 56 | GL.glCompileShader(shader) 57 | status = GL.glGetShaderiv(shader,GL.GL_COMPILE_STATUS) 58 | if not status: 59 | log = GL.glGetShaderInfoLog(shader) 60 | shader_name = SHADER2STRING[shader_type] 61 | raise ShaderError,"Compile failure in {} shader:\n{}\n".format(shader_name,log) 62 | return shader 63 | def link(self): 64 | GL.glLinkProgram(self.shader) 65 | status = GL.glGetProgramiv(self.shader,GL.GL_LINK_STATUS) 66 | if not status: 67 | log = GL.glGetProgramInfoLog(self.shader) 68 | raise ShaderError,"Linking failue:\n{}\n".format(log) 69 | def reshape(self,width,height): 70 | GL.glViewport(0,0,width,height) 71 | def setup_uniforms(self): 72 | pass 73 | def setup_attributes(self): 74 | pass -------------------------------------------------------------------------------- /04_objects_at_rest/04_AspectRatio.py: -------------------------------------------------------------------------------- 1 | import sys,os,math 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | sys.path.append("..") 6 | sys.path.append("data") 7 | import myframework 8 | from vertices_perspective import VERTICES 9 | 10 | class Shader(myframework.BaseShader): 11 | def __init__(self,vertices,vert_file,frag_file): 12 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file) 13 | GL.glEnable(GL.GL_CULL_FACE) 14 | GL.glCullFace(GL.GL_BACK) 15 | GL.glFrontFace(GL.GL_CW) 16 | 17 | def setup_uniforms(self): 18 | self.offset_location = GL.glGetUniformLocation(self.shader,"offset") 19 | self.perspective_matrix_unif = GL.glGetUniformLocation(self.shader,"perspectiveMatrix") 20 | self.frustum_scale = 1.0 21 | self.z_near,self.z_far = 0.5,3.0 22 | self.create_matrix() 23 | 24 | GL.glUseProgram(self.shader) 25 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 26 | GL.glUseProgram(0) 27 | 28 | def create_matrix(self): 29 | self.the_matrix = [0.0 for i in range(16)] 30 | self.the_matrix[0] = self.frustum_scale 31 | self.the_matrix[5] = self.frustum_scale 32 | self.the_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 33 | self.the_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 34 | self.the_matrix[11] = -1.0 35 | 36 | def display(self): 37 | GL.glClearColor(0,0,0,0) 38 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 39 | 40 | GL.glUseProgram(self.shader) 41 | GL.glUniform2f(self.offset_location,1.5,0.5) 42 | color_data = GL.GLvoidp((len(self.vertices)*self.size_float)/2) 43 | 44 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.vbo) 45 | GL.glEnableVertexAttribArray(0) 46 | GL.glEnableVertexAttribArray(1) 47 | GL.glVertexAttribPointer(0,self.vert_comp,GL.GL_FLOAT,GL.GL_FALSE,0,None) 48 | GL.glVertexAttribPointer(1,self.vert_comp,GL.GL_FLOAT,GL.GL_FALSE,0,color_data) 49 | 50 | GL.glDrawArrays(GL.GL_TRIANGLES,0,36) 51 | 52 | GL.glDisableVertexAttribArray(0) 53 | GL.glDisableVertexAttribArray(1) 54 | GL.glUseProgram(0) 55 | 56 | def reshape(self,width,height): 57 | self.the_matrix[0] = self.frustum_scale/(width/float(height)) 58 | self.the_matrix[5] = self.frustum_scale 59 | GL.glUseProgram(self.shader) 60 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 61 | GL.glUseProgram(0) 62 | GL.glViewport(0,0,width,height) 63 | 64 | def main(): 65 | pg.init() 66 | os.environ['SDL_VIDEO_CENTERED'] = '1' 67 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 68 | MyClock = pg.time.Clock() 69 | MyGL = Shader(VERTICES[:],os.path.join("data","MatrixPerspective.vert"),os.path.join("data","StandardColors.frag")) 70 | done = False 71 | while not done: 72 | for event in pg.event.get(): 73 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 74 | done = True 75 | elif event.type == pg.KEYDOWN: 76 | pass 77 | elif event.type == pg.VIDEORESIZE: 78 | MyGL.reshape(*event.size) 79 | MyGL.display() 80 | pg.display.flip() 81 | MyClock.tick(60) 82 | 83 | if __name__ == '__main__': 84 | main() 85 | pg.quit() 86 | sys.exit() 87 | -------------------------------------------------------------------------------- /05_objects_in_depth/data/vertex_data.py: -------------------------------------------------------------------------------- 1 | NUMBER_OF_VERTICES = 36 2 | 3 | _EXTENT = {"RIGHT" : 0.8, 4 | "TOP" : 0.2, 5 | "MIDDLE": 0.0, 6 | "FRONT" :-1.25, 7 | "REAR" :-1.75} 8 | 9 | _EXTENT["LEFT"] = -_EXTENT["RIGHT"] 10 | _EXTENT["BOTTOM"] = -_EXTENT["TOP"] 11 | 12 | #Colors are defined as follows in the original tutorial. 13 | #Don't blame me if BLUE is green and GREEN is blueish-grey. 14 | _COLOR = {"GREEN" : [0.75,0.75,1.0,1.0], 15 | "BLUE" : [0.0 ,0.5 ,0.0,1.0], 16 | "RED" : [1.0 ,0.0 ,0.0,1.0], 17 | "GREY" : [0.8 ,0.8 ,0.8,1.0], 18 | "BROWN" : [0.5 ,0.5 ,0.0,1.0]} 19 | 20 | _POSITIONS = [#Object 1 positions 21 | _EXTENT["LEFT"], _EXTENT["TOP"], _EXTENT["REAR"], 22 | _EXTENT["LEFT"], _EXTENT["MIDDLE"],_EXTENT["FRONT"], 23 | _EXTENT["RIGHT"],_EXTENT["MIDDLE"],_EXTENT["FRONT"], 24 | _EXTENT["RIGHT"],_EXTENT["TOP"], _EXTENT["REAR"], 25 | 26 | _EXTENT["LEFT"], _EXTENT["BOTTOM"],_EXTENT["REAR"], 27 | _EXTENT["LEFT"], _EXTENT["MIDDLE"],_EXTENT["FRONT"], 28 | _EXTENT["RIGHT"],_EXTENT["MIDDLE"],_EXTENT["FRONT"], 29 | _EXTENT["RIGHT"],_EXTENT["BOTTOM"],_EXTENT["REAR"], 30 | 31 | _EXTENT["LEFT"], _EXTENT["TOP"], _EXTENT["REAR"], 32 | _EXTENT["LEFT"], _EXTENT["MIDDLE"],_EXTENT["FRONT"], 33 | _EXTENT["LEFT"], _EXTENT["BOTTOM"],_EXTENT["REAR"], 34 | 35 | _EXTENT["RIGHT"],_EXTENT["TOP"], _EXTENT["REAR"], 36 | _EXTENT["RIGHT"],_EXTENT["MIDDLE"],_EXTENT["FRONT"], 37 | _EXTENT["RIGHT"],_EXTENT["BOTTOM"],_EXTENT["REAR"], 38 | 39 | _EXTENT["LEFT"], _EXTENT["BOTTOM"],_EXTENT["REAR"], 40 | _EXTENT["LEFT"], _EXTENT["TOP"], _EXTENT["REAR"], 41 | _EXTENT["RIGHT"],_EXTENT["TOP"], _EXTENT["REAR"], 42 | _EXTENT["RIGHT"],_EXTENT["BOTTOM"],_EXTENT["REAR"], 43 | 44 | #Object 2 positions 45 | _EXTENT["TOP"], _EXTENT["RIGHT"],_EXTENT["REAR"], 46 | _EXTENT["MIDDLE"],_EXTENT["RIGHT"],_EXTENT["FRONT"], 47 | _EXTENT["MIDDLE"],_EXTENT["LEFT"], _EXTENT["FRONT"], 48 | _EXTENT["TOP"], _EXTENT["LEFT"], _EXTENT["REAR"], 49 | 50 | _EXTENT["BOTTOM"],_EXTENT["RIGHT"],_EXTENT["REAR"], 51 | _EXTENT["MIDDLE"],_EXTENT["RIGHT"],_EXTENT["FRONT"], 52 | _EXTENT["MIDDLE"],_EXTENT["LEFT"], _EXTENT["FRONT"], 53 | _EXTENT["BOTTOM"],_EXTENT["LEFT"], _EXTENT["REAR"], 54 | 55 | _EXTENT["TOP"], _EXTENT["RIGHT"],_EXTENT["REAR"], 56 | _EXTENT["MIDDLE"],_EXTENT["RIGHT"],_EXTENT["FRONT"], 57 | _EXTENT["BOTTOM"],_EXTENT["RIGHT"],_EXTENT["REAR"], 58 | 59 | _EXTENT["TOP"], _EXTENT["LEFT"],_EXTENT["REAR"], 60 | _EXTENT["MIDDLE"],_EXTENT["LEFT"],_EXTENT["FRONT"], 61 | _EXTENT["BOTTOM"],_EXTENT["LEFT"],_EXTENT["REAR"], 62 | 63 | _EXTENT["BOTTOM"],_EXTENT["RIGHT"],_EXTENT["REAR"], 64 | _EXTENT["TOP"], _EXTENT["RIGHT"],_EXTENT["REAR"], 65 | _EXTENT["TOP"], _EXTENT["LEFT"], _EXTENT["REAR"], 66 | _EXTENT["BOTTOM"],_EXTENT["LEFT"], _EXTENT["REAR"]] 67 | 68 | _COLORS = (#Object 1 colors 69 | _COLOR["GREEN"]*4+ 70 | _COLOR["BLUE" ]*4+ 71 | _COLOR["RED" ]*3+ 72 | _COLOR["GREY" ]*3+ 73 | _COLOR["BROWN"]*4+ 74 | 75 | #Object 2 colors 76 | _COLOR["RED" ]*4+ 77 | _COLOR["BROWN"]*4+ 78 | _COLOR["BLUE" ]*3+ 79 | _COLOR["GREEN"]*3+ 80 | _COLOR["GREY" ]*4) 81 | 82 | VERTICES = _POSITIONS+_COLORS 83 | 84 | INDICES = [ 0, 2, 1, 85 | 3, 2, 0, 86 | 87 | 4, 5, 6, 88 | 6, 7, 4, 89 | 90 | 8, 9,10, 91 | 11,13,12, 92 | 93 | 14,16,15, 94 | 17,16,14] -------------------------------------------------------------------------------- /02_playing_with_colors/02_FragPosition.py: -------------------------------------------------------------------------------- 1 | import sys,os 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | VERTICES = [ 0.75, 0.75, 0.0, 1.0, 6 | 0.75,-0.75, 0.0, 1.0, 7 | -0.75,-0.75, 0.0, 1.0] 8 | 9 | SIZE_FLOAT = VERT_COMPONENTS = 4 10 | 11 | SHADER2STRING = {GL.GL_VERTEX_SHADER : "vertex", 12 | GL.GL_GEOMETRY_SHADER : "geometry", 13 | GL.GL_FRAGMENT_SHADER : "fragment"} 14 | 15 | #Load shaders from files. 16 | with open(os.path.join("data","FragPosition.vert"),'r') as myfile: 17 | VERT = myfile.read() 18 | with open(os.path.join("data","FragPosition.frag"),'r') as myfile: 19 | FRAG = myfile.read() 20 | 21 | class GLtests: 22 | def __init__(self): 23 | self.shader = GL.glCreateProgram() 24 | self.vbo = None 25 | self.init_all() 26 | self.reshape(500,500) 27 | def init_all(self): 28 | self.attach_shaders() 29 | self.init_vertex_buf() 30 | vao = GL.glGenVertexArrays(1) 31 | GL.glBindVertexArray(vao) 32 | def init_vertex_buf(self): 33 | self.vbo = GL.glGenBuffers(1) 34 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 35 | array_type = (GL.GLfloat*len(VERTICES)) 36 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(VERTICES)*SIZE_FLOAT, 37 | array_type(*VERTICES),GL.GL_STATIC_DRAW) 38 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 39 | 40 | def attach_shaders(self): 41 | shade_list = [] 42 | shade_list.append(self.compile(GL.GL_VERTEX_SHADER,VERT)) 43 | shade_list.append(self.compile(GL.GL_FRAGMENT_SHADER,FRAG)) 44 | for shade in shade_list: 45 | GL.glAttachShader(self.shader,shade) 46 | self.link() 47 | for shade in shade_list: 48 | GL.glDetachShader(self.shader,shade) 49 | GL.glDeleteShader(shade) 50 | def compile(self,shader_type,shader_str): 51 | shader = GL.glCreateShader(shader_type) 52 | GL.glShaderSource(shader,shader_str) 53 | GL.glCompileShader(shader) 54 | status = GL.glGetShaderiv(shader,GL.GL_COMPILE_STATUS) 55 | if not status: 56 | log = GL.glGetShaderInfoLog(shader) 57 | shader_name = SHADER2STRING[shader_type] 58 | raise ShaderException,"Compile failure in {} shader:\n{}\n".format(shader_name,log) 59 | return shader 60 | 61 | def link(self): 62 | GL.glLinkProgram(self.shader) 63 | status = GL.glGetProgramiv(self.shader,GL.GL_LINK_STATUS) 64 | if not status: 65 | log = GL.glGetProgramInfoLog(self.shader) 66 | raise ShaderException,"Linking failue:\n{}\n".format(log) 67 | 68 | def display(self): 69 | GL.glClearColor(1,1,1,1) 70 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 71 | 72 | GL.glUseProgram(self.shader) 73 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 74 | GL.glEnableVertexAttribArray(0) 75 | GL.glVertexAttribPointer(0,VERT_COMPONENTS,GL.GL_FLOAT,False,0,None) 76 | GL.glDrawArrays(GL.GL_TRIANGLES, 0, len(VERTICES)//VERT_COMPONENTS) 77 | GL.glDisableVertexAttribArray(0) 78 | GL.glUseProgram(0) 79 | 80 | def reshape(self,width,height): 81 | GL.glViewport(0,0,width,height) 82 | 83 | class ShaderException(Exception): 84 | pass 85 | 86 | def main(): 87 | pg.init() 88 | os.environ['SDL_VIDEO_CENTERED'] = '1' 89 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF) 90 | MyClock = pg.time.Clock() 91 | MyGL = GLtests() 92 | while 1: 93 | for event in pg.event.get(): 94 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 95 | pg.quit();sys.exit() 96 | elif event.type == pg.KEYDOWN: 97 | pass 98 | MyGL.display() 99 | pg.display.flip() 100 | MyClock.tick(65) 101 | 102 | if __name__ == '__main__': 103 | main() -------------------------------------------------------------------------------- /01_hello_triangle/01_hello_triangle_manually.py: -------------------------------------------------------------------------------- 1 | import sys,os 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | VERTICES = [ 0.75, 0.75, 0.0, 1.0, 6 | 0.75, -0.75, 0.0, 1.0, 7 | -0.75, -0.75, 0.0, 1.0] 8 | 9 | SIZE_FLOAT = VERT_COMPONENTS = 4 10 | 11 | SHADER2STRING = {GL.GL_VERTEX_SHADER : "vertex", 12 | GL.GL_GEOMETRY_SHADER : "geometry", 13 | GL.GL_FRAGMENT_SHADER : "fragment"} 14 | 15 | #Shaders: 16 | VERT = """ 17 | #version 130 18 | in vec4 position; 19 | void main() 20 | { 21 | gl_Position = position; 22 | }""" 23 | 24 | FRAG = """ 25 | #version 130 26 | out vec4 outputColor; 27 | void main() 28 | { 29 | outputColor = vec4(0.0f, 1.0f, 0.0f, 1.0f); 30 | }""" 31 | 32 | class GLtests: 33 | def __init__(self): 34 | self.shader = GL.glCreateProgram() 35 | self.vbo = None 36 | self.init_all() 37 | self.reshape(500,500) 38 | def init_all(self): 39 | self.attach_shaders() 40 | self.init_vertex_buf() 41 | vao = GL.glGenVertexArrays(1) 42 | GL.glBindVertexArray(vao) 43 | def init_vertex_buf(self): 44 | self.vbo = GL.glGenBuffers(1) 45 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 46 | array_type = (GL.GLfloat*len(VERTICES)) 47 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(VERTICES)*SIZE_FLOAT, 48 | array_type(*VERTICES),GL.GL_STATIC_DRAW) 49 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 50 | 51 | def attach_shaders(self): 52 | shade_list = [] 53 | shade_list.append(self.compile(GL.GL_VERTEX_SHADER,VERT)) 54 | shade_list.append(self.compile(GL.GL_FRAGMENT_SHADER,FRAG)) 55 | for shade in shade_list: 56 | GL.glAttachShader(self.shader,shade) 57 | self.link() 58 | for shade in shade_list: 59 | GL.glDetachShader(self.shader,shade) 60 | GL.glDeleteShader(shade) 61 | def compile(self,shader_type,shader_str): 62 | shader = GL.glCreateShader(shader_type) 63 | GL.glShaderSource(shader,shader_str) 64 | GL.glCompileShader(shader) 65 | status = GL.glGetShaderiv(shader,GL.GL_COMPILE_STATUS) 66 | if not status: 67 | log = GL.glGetShaderInfoLog(shader) 68 | shader_name = SHADER2STRING[shader_type] 69 | raise ShaderException,"Compile failure in {} shader:\n{}\n".format(shader_name,log) 70 | return shader 71 | 72 | def link(self): 73 | GL.glLinkProgram(self.shader) 74 | status = GL.glGetProgramiv(self.shader,GL.GL_LINK_STATUS) 75 | if not status: 76 | log = GL.glGetProgramInfoLog(self.shader) 77 | raise ShaderException,"Linking failue:\n{}\n".format(log) 78 | 79 | def display(self): 80 | GL.glClearColor(1,1,1,1) 81 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 82 | 83 | GL.glUseProgram(self.shader) 84 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 85 | GL.glEnableVertexAttribArray(0) 86 | GL.glVertexAttribPointer(0,VERT_COMPONENTS,GL.GL_FLOAT,False,0,None) 87 | GL.glDrawArrays(GL.GL_TRIANGLES, 0, len(VERTICES)//VERT_COMPONENTS) 88 | GL.glDisableVertexAttribArray(0) 89 | GL.glUseProgram(0) 90 | 91 | def reshape(self,width,height): 92 | GL.glViewport(0,0,width,height) 93 | 94 | class ShaderException(Exception): 95 | pass 96 | 97 | def main(): 98 | pg.init() 99 | os.environ['SDL_VIDEO_CENTERED'] = '1' 100 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF) 101 | MyClock = pg.time.Clock() 102 | MyGL = GLtests() 103 | while 1: 104 | for event in pg.event.get(): 105 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 106 | pg.quit();sys.exit() 107 | elif event.type == pg.KEYDOWN: 108 | pass 109 | MyGL.display() 110 | pg.display.flip() 111 | MyClock.tick(65) 112 | 113 | if __name__ == '__main__': 114 | main() 115 | -------------------------------------------------------------------------------- /04_objects_at_rest/04_AspectRatio_interactive.py: -------------------------------------------------------------------------------- 1 | """Added simple movement in the x-y plane with arrow keys. 2 | This is just independent experimentation and not part of the original tutorial.""" 3 | import sys,os,math 4 | import pygame as pg 5 | from OpenGL import GL 6 | 7 | sys.path.append("..") 8 | sys.path.append("data") 9 | import myframework 10 | from vertices_perspective import VERTICES 11 | 12 | KEYDICT = {pg.K_UP : ( 0,-1), 13 | pg.K_DOWN : ( 0, 1), 14 | pg.K_RIGHT : (-1, 0), 15 | pg.K_LEFT : ( 1, 0)} 16 | 17 | class Shader(myframework.BaseShader): 18 | def __init__(self,vertices,vert_file,frag_file): 19 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file) 20 | GL.glEnable(GL.GL_CULL_FACE) 21 | GL.glCullFace(GL.GL_BACK) 22 | GL.glFrontFace(GL.GL_CW) 23 | self.offset = [-0.5,-0.5] 24 | self.speed = 0.03 25 | 26 | def setup_uniforms(self): 27 | self.offset_location = GL.glGetUniformLocation(self.shader,"offset") 28 | self.perspective_matrix_unif = GL.glGetUniformLocation(self.shader,"perspectiveMatrix") 29 | self.frustum_scale = 1.0 30 | self.z_near,self.z_far = 0.5,3.0 31 | self.create_matrix() 32 | 33 | GL.glUseProgram(self.shader) 34 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 35 | GL.glUseProgram(0) 36 | 37 | def create_matrix(self): 38 | self.the_matrix = [0.0 for i in range(16)] 39 | self.the_matrix[0] = self.frustum_scale 40 | self.the_matrix[5] = self.frustum_scale 41 | self.the_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 42 | self.the_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 43 | self.the_matrix[11] = -1.0 44 | 45 | def display(self): 46 | GL.glClearColor(0,0,0,0) 47 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 48 | 49 | GL.glUseProgram(self.shader) 50 | GL.glUniform2f(self.offset_location,*self.offset) 51 | color_data = GL.GLvoidp((len(self.vertices)*self.size_float)/2) 52 | 53 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.vbo) 54 | GL.glEnableVertexAttribArray(0) 55 | GL.glEnableVertexAttribArray(1) 56 | GL.glVertexAttribPointer(0,self.vert_comp,GL.GL_FLOAT,GL.GL_FALSE,0,None) 57 | GL.glVertexAttribPointer(1,self.vert_comp,GL.GL_FLOAT,GL.GL_FALSE,0,color_data) 58 | 59 | GL.glDrawArrays(GL.GL_TRIANGLES,0,36) 60 | 61 | GL.glDisableVertexAttribArray(0) 62 | GL.glDisableVertexAttribArray(1) 63 | GL.glUseProgram(0) 64 | 65 | def reshape(self,width,height): 66 | self.the_matrix[0] = self.frustum_scale/(width/float(height)) 67 | self.the_matrix[5] = self.frustum_scale 68 | GL.glUseProgram(self.shader) 69 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 70 | GL.glUseProgram(0) 71 | GL.glViewport(0,0,width,height) 72 | 73 | def main(): 74 | pg.init() 75 | os.environ['SDL_VIDEO_CENTERED'] = '1' 76 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 77 | MyClock = pg.time.Clock() 78 | MyGL = Shader(VERTICES[:],os.path.join("data","MatrixPerspective.vert"),os.path.join("data","StandardColors.frag")) 79 | done = False 80 | while not done: 81 | for event in pg.event.get(): 82 | keys = pg.key.get_pressed() 83 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 84 | done = True 85 | elif event.type == pg.KEYDOWN: 86 | pass 87 | elif event.type == pg.VIDEORESIZE: 88 | MyGL.reshape(*event.size) 89 | 90 | for key in KEYDICT: 91 | if keys[key]: 92 | for i in (0,1): 93 | MyGL.offset[i] = MyGL.offset[i]+KEYDICT[key][i]*MyGL.speed 94 | 95 | MyGL.display() 96 | pg.display.flip() 97 | MyClock.tick(60) 98 | 99 | if __name__ == '__main__': 100 | main() 101 | pg.quit() 102 | sys.exit() 103 | -------------------------------------------------------------------------------- /02_playing_with_colors/02_VertexColors.py: -------------------------------------------------------------------------------- 1 | import sys,os 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | VERTICES = [ 0.0, 0.5, 0.0, 1.0, 6 | 0.5,-0.366, 0.0, 1.0, 7 | -0.5,-0.366, 0.0, 1.0, 8 | 1.0, 0.0, 0.0, 1.0, 9 | 0.0, 1.0, 0.0, 1.0, 10 | 0.0, 0.0, 1.0, 1.0] 11 | 12 | SIZE_FLOAT = VERT_COMPONENTS = 4 13 | 14 | SHADER2STRING = {GL.GL_VERTEX_SHADER : "vertex", 15 | GL.GL_GEOMETRY_SHADER : "geometry", 16 | GL.GL_FRAGMENT_SHADER : "fragment"} 17 | 18 | #Load shaders from files. 19 | with open(os.path.join("data","VertexColors.vert"),'r') as myfile: 20 | VERT = myfile.read() 21 | with open(os.path.join("data","VertexColors.frag"),'r') as myfile: 22 | FRAG = myfile.read() 23 | 24 | class GLtests: 25 | def __init__(self): 26 | self.shader = GL.glCreateProgram() 27 | self.vbo = None 28 | self.init_all() 29 | self.reshape(500,500) 30 | def init_all(self): 31 | self.attach_shaders() 32 | self.init_vertex_buf() 33 | vao = GL.glGenVertexArrays(1) 34 | GL.glBindVertexArray(vao) 35 | def init_vertex_buf(self): 36 | self.vbo = GL.glGenBuffers(1) 37 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 38 | array_type = (GL.GLfloat*len(VERTICES)) 39 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(VERTICES)*SIZE_FLOAT, 40 | array_type(*VERTICES),GL.GL_STATIC_DRAW) 41 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 42 | 43 | def attach_shaders(self): 44 | shade_list = [] 45 | shade_list.append(self.compile(GL.GL_VERTEX_SHADER,VERT)) 46 | shade_list.append(self.compile(GL.GL_FRAGMENT_SHADER,FRAG)) 47 | for shade in shade_list: 48 | GL.glAttachShader(self.shader,shade) 49 | self.link() 50 | for shade in shade_list: 51 | GL.glDetachShader(self.shader,shade) 52 | GL.glDeleteShader(shade) 53 | def compile(self,shader_type,shader_str): 54 | shader = GL.glCreateShader(shader_type) 55 | GL.glShaderSource(shader,shader_str) 56 | GL.glCompileShader(shader) 57 | status = GL.glGetShaderiv(shader,GL.GL_COMPILE_STATUS) 58 | if not status: 59 | log = GL.glGetShaderInfoLog(shader) 60 | shader_name = SHADER2STRING[shader_type] 61 | raise ShaderException,"Compile failure in {} shader:\n{}\n".format(shader_name,log) 62 | return shader 63 | 64 | def link(self): 65 | GL.glLinkProgram(self.shader) 66 | status = GL.glGetProgramiv(self.shader,GL.GL_LINK_STATUS) 67 | if not status: 68 | log = GL.glGetProgramInfoLog(self.shader) 69 | raise ShaderException,"Linking failue:\n{}\n".format(log) 70 | 71 | def display(self): 72 | GL.glClearColor(0,0,0,0) 73 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 74 | 75 | GL.glUseProgram(self.shader) 76 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 77 | GL.glEnableVertexAttribArray(0) 78 | GL.glEnableVertexAttribArray(1) 79 | GL.glVertexAttribPointer(0,VERT_COMPONENTS,GL.GL_FLOAT,False,0,None) 80 | GL.glVertexAttribPointer(1,VERT_COMPONENTS,GL.GL_FLOAT,False,0,GL.GLvoidp(48)) 81 | GL.glDrawArrays(GL.GL_TRIANGLES,0,3) 82 | 83 | GL.glDisableVertexAttribArray(0) 84 | GL.glDisableVertexAttribArray(1) 85 | GL.glUseProgram(0) 86 | 87 | def reshape(self,width,height): 88 | GL.glViewport(0,0,width,height) 89 | 90 | class ShaderException(Exception): 91 | pass 92 | 93 | def main(): 94 | pg.init() 95 | os.environ['SDL_VIDEO_CENTERED'] = '1' 96 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF) 97 | MyClock = pg.time.Clock() 98 | MyGL = GLtests() 99 | done = False 100 | while not done: 101 | for event in pg.event.get(): 102 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 103 | done = True 104 | elif event.type == pg.KEYDOWN: 105 | pass 106 | MyGL.display() 107 | pg.display.flip() 108 | MyClock.tick(65) 109 | 110 | if __name__ == '__main__': 111 | main() 112 | pg.quit() 113 | sys.exit() 114 | -------------------------------------------------------------------------------- /03_OpenGLs_moving_triangle/03_vertCalcOffset.py: -------------------------------------------------------------------------------- 1 | import sys,os,math 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | VERTICES = [ 0.25, 0.25, 0.0, 1.0, 6 | 0.25,-0.25, 0.0, 1.0, 7 | -0.25,-0.25, 0.0, 1.0] 8 | 9 | SIZE_FLOAT = VERT_COMPONENTS = 4 10 | 11 | SHADER2STRING = {GL.GL_VERTEX_SHADER : "vertex", 12 | GL.GL_GEOMETRY_SHADER : "geometry", 13 | GL.GL_FRAGMENT_SHADER : "fragment"} 14 | 15 | class Shader: 16 | def __init__(self,vert_file,frag_file): 17 | self.shader = GL.glCreateProgram() 18 | self.vbo = None 19 | self.init_all(vert_file,frag_file) 20 | self.reshape(500,500) 21 | self.setup_uniforms() 22 | def init_all(self,vert_file,frag_file): 23 | self.attach_shaders(vert_file,frag_file) 24 | self.init_vertex_buf() 25 | vao = GL.glGenVertexArrays(1) 26 | GL.glBindVertexArray(vao) 27 | def init_vertex_buf(self): 28 | self.vbo = GL.glGenBuffers(1) 29 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 30 | ArrayType = (GL.GLfloat*len(VERTICES)) 31 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(VERTICES)*SIZE_FLOAT, 32 | ArrayType(*VERTICES),GL.GL_STATIC_DRAW) 33 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 34 | 35 | def attach_shaders(self,vert_file,frag_file): 36 | vert,frag = self.load_shader_files(vert_file,frag_file) 37 | shade_list = [] 38 | shade_list.append(self.compile(GL.GL_VERTEX_SHADER,vert)) 39 | shade_list.append(self.compile(GL.GL_FRAGMENT_SHADER,frag)) 40 | for shade in shade_list: 41 | GL.glAttachShader(self.shader,shade) 42 | self.link() 43 | for shade in shade_list: 44 | GL.glDetachShader(self.shader,shade) 45 | GL.glDeleteShader(shade) 46 | def load_shader_files(self,vert_file,frag_file): 47 | with open(vert_file,'r') as myfile: 48 | vert = myfile.read() 49 | with open(frag_file,'r') as myfile: 50 | frag = myfile.read() 51 | return vert,frag 52 | def compile(self,shader_type,shader_str): 53 | shader = GL.glCreateShader(shader_type) 54 | GL.glShaderSource(shader,shader_str) 55 | GL.glCompileShader(shader) 56 | status = GL.glGetShaderiv(shader,GL.GL_COMPILE_STATUS) 57 | if not status: 58 | log = GL.glGetShaderInfoLog(shader) 59 | shader_name = SHADER2STRING[shader_type] 60 | raise ShaderException,"Compile failure in {} shader:\n{}\n".format(shader_name,log) 61 | return shader 62 | 63 | def link(self): 64 | GL.glLinkProgram(self.shader) 65 | status = GL.glGetProgramiv(self.shader,GL.GL_LINK_STATUS) 66 | if not status: 67 | log = GL.glGetProgramInfoLog(self.shader) 68 | raise ShaderException,"Linking failue:\n{}\n".format(log) 69 | 70 | def setup_uniforms(self): 71 | self.elapsed_time_uniform = GL.glGetUniformLocation(self.shader,"time") 72 | self.period = GL.glGetUniformLocation(self.shader,"period") 73 | GL.glUseProgram(self.shader) 74 | GL.glUniform1f(self.period,5.0) 75 | GL.glUseProgram(0) 76 | 77 | def display(self): 78 | GL.glClearColor(1,1,1,1) 79 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 80 | GL.glUseProgram(self.shader) 81 | 82 | GL.glUniform1f(self.elapsed_time_uniform,pg.time.get_ticks()/1000.0) 83 | 84 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 85 | GL.glEnableVertexAttribArray(0) 86 | GL.glVertexAttribPointer(0,VERT_COMPONENTS,GL.GL_FLOAT,False,0,None) 87 | GL.glDrawArrays(GL.GL_TRIANGLES,0,3) 88 | GL.glDisableVertexAttribArray(0) 89 | GL.glUseProgram(0) 90 | 91 | def reshape(self,width,height): 92 | GL.glViewport(0,0,width,height) 93 | 94 | class ShaderException(Exception): 95 | pass 96 | 97 | def main(): 98 | pg.init() 99 | os.environ['SDL_VIDEO_CENTERED'] = '1' 100 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 101 | MyClock = pg.time.Clock() 102 | MyGL = Shader(os.path.join("data","calcOffset.vert"),os.path.join("data","standard.frag")) 103 | done = False 104 | while not done: 105 | for event in pg.event.get(): 106 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 107 | done = True 108 | elif event.type == pg.KEYDOWN: 109 | pass 110 | elif event.type == pg.VIDEORESIZE: 111 | MyGL.reshape(*event.size) 112 | MyGL.display() 113 | pg.display.flip() 114 | MyClock.tick(65) 115 | 116 | if __name__ == '__main__': 117 | main() 118 | pg.quit() 119 | sys.exit() 120 | -------------------------------------------------------------------------------- /05_objects_in_depth/05_BaseVertexOverlap.py: -------------------------------------------------------------------------------- 1 | import sys,os,math 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | sys.path.append("..") 6 | sys.path.append("data") 7 | import myframework 8 | from vertex_data import VERTICES,INDICES,NUMBER_OF_VERTICES 9 | 10 | class Shader(myframework.BaseShader): 11 | def __init__(self,vertices,vert_file,frag_file,indices=None): 12 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file,indices) 13 | GL.glEnable(GL.GL_CULL_FACE) 14 | GL.glCullFace(GL.GL_BACK) 15 | GL.glFrontFace(GL.GL_CW) 16 | 17 | def init_vertex_buf(self): 18 | self.vbo = GL.glGenBuffers(1) 19 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 20 | ArrayType = GL.GLfloat*len(self.vertices) 21 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(self.vertices)*self.size_float, 22 | ArrayType(*self.vertices),GL.GL_STATIC_DRAW) 23 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 24 | 25 | self.ibo = GL.glGenBuffers(1) 26 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 27 | ArrayType = (GL.GLushort*len(self.indices)) 28 | GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,len(self.indices)*self.size_short, 29 | ArrayType(*self.indices),GL.GL_STATIC_DRAW) 30 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,0) 31 | 32 | def init_vao(self): 33 | self.vao = GL.glGenVertexArrays(1) 34 | GL.glBindVertexArray(self.vao) 35 | color_data_offset = 3*self.size_float*NUMBER_OF_VERTICES 36 | 37 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 38 | GL.glEnableVertexAttribArray(0) 39 | GL.glEnableVertexAttribArray(1) 40 | GL.glVertexAttribPointer(0,3,GL.GL_FLOAT,GL.GL_FALSE,0,None) 41 | GL.glVertexAttribPointer(1,4,GL.GL_FLOAT,GL.GL_FALSE,0,GL.GLvoidp(color_data_offset)) 42 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 43 | GL.glBindVertexArray(0) 44 | 45 | def setup_uniforms(self): 46 | self.offset_location = GL.glGetUniformLocation(self.shader,"offset") 47 | self.perspective_matrix_unif = GL.glGetUniformLocation(self.shader,"perspectiveMatrix") 48 | self.frustum_scale = 1.0 49 | self.z_near,self.z_far = 1.0,3.0 50 | self.create_matrix() 51 | 52 | GL.glUseProgram(self.shader) 53 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 54 | GL.glUseProgram(0) 55 | 56 | def create_matrix(self): 57 | self.the_matrix = [0.0 for i in range(16)] 58 | self.the_matrix[0] = self.frustum_scale 59 | self.the_matrix[5] = self.frustum_scale 60 | self.the_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 61 | self.the_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 62 | self.the_matrix[11] = -1.0 63 | 64 | def display(self): 65 | GL.glClearColor(0,0,0,0) 66 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 67 | 68 | GL.glUseProgram(self.shader) 69 | GL.glBindVertexArray(self.vao) 70 | GL.glUniform3f(self.offset_location,0.0,0.0,0.0) 71 | GL.glDrawElements(GL.GL_TRIANGLES,len(self.indices),GL.GL_UNSIGNED_SHORT,None) 72 | 73 | GL.glUniform3f(self.offset_location,0.0,0.0,-1.0) 74 | GL.glDrawElementsBaseVertex(GL.GL_TRIANGLES,len(self.indices), 75 | GL.GL_UNSIGNED_SHORT,None,NUMBER_OF_VERTICES/2) 76 | GL.glBindVertexArray(0) 77 | GL.glUseProgram(0) 78 | 79 | def reshape(self,width,height): 80 | self.the_matrix[0] = self.frustum_scale/(width/float(height)) 81 | self.the_matrix[5] = self.frustum_scale 82 | GL.glUseProgram(self.shader) 83 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 84 | GL.glUseProgram(0) 85 | GL.glViewport(0,0,width,height) 86 | 87 | def main(): 88 | pg.init() 89 | os.environ['SDL_VIDEO_CENTERED'] = '1' 90 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 91 | MyClock = pg.time.Clock() 92 | MyGL = Shader(VERTICES[:],os.path.join("data","Standard.vert"), 93 | os.path.join("data","Standard.frag"),INDICES[:]) 94 | done = False 95 | while not done: 96 | for event in pg.event.get(): 97 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 98 | done = True 99 | elif event.type == pg.KEYDOWN: 100 | pass 101 | elif event.type == pg.VIDEORESIZE: 102 | MyGL.reshape(*event.size) 103 | MyGL.display() 104 | pg.display.flip() 105 | MyClock.tick(60) 106 | 107 | if __name__ == '__main__': 108 | main() 109 | pg.quit() 110 | sys.exit() -------------------------------------------------------------------------------- /03_OpenGLs_moving_triangle/03_fragChangeColor.py: -------------------------------------------------------------------------------- 1 | import sys,os,math 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | VERTICES = [ 0.25, 0.25, 0.0, 1.0, 6 | 0.25,-0.25, 0.0, 1.0, 7 | -0.25,-0.25, 0.0, 1.0] 8 | 9 | SIZE_FLOAT = VERT_COMPONENTS = 4 10 | 11 | SHADER2STRING = {GL.GL_VERTEX_SHADER : "vertex", 12 | GL.GL_GEOMETRY_SHADER : "geometry", 13 | GL.GL_FRAGMENT_SHADER : "fragment"} 14 | 15 | class Shader: 16 | def __init__(self,vert_file,frag_file): 17 | self.shader = GL.glCreateProgram() 18 | self.vbo = None 19 | self.init_all(vert_file,frag_file) 20 | self.reshape(500,500) 21 | self.setup_uniforms() 22 | def init_all(self,vert_file,frag_file): 23 | self.attach_shaders(vert_file,frag_file) 24 | self.init_vertex_buf() 25 | vao = GL.glGenVertexArrays(1) 26 | GL.glBindVertexArray(vao) 27 | def init_vertex_buf(self): 28 | self.vbo = GL.glGenBuffers(1) 29 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 30 | ArrayType = (GL.GLfloat*len(VERTICES)) 31 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(VERTICES)*SIZE_FLOAT, 32 | ArrayType(*VERTICES),GL.GL_STATIC_DRAW) 33 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 34 | 35 | def attach_shaders(self,vert_file,frag_file): 36 | vert,frag = self.load_shader_files(vert_file,frag_file) 37 | shade_list = [] 38 | shade_list.append(self.compile(GL.GL_VERTEX_SHADER,vert)) 39 | shade_list.append(self.compile(GL.GL_FRAGMENT_SHADER,frag)) 40 | for shade in shade_list: 41 | GL.glAttachShader(self.shader,shade) 42 | self.link() 43 | for shade in shade_list: 44 | GL.glDetachShader(self.shader,shade) 45 | GL.glDeleteShader(shade) 46 | def load_shader_files(self,vert_file,frag_file): 47 | with open(vert_file,'r') as myfile: 48 | vert = myfile.read() 49 | with open(frag_file,'r') as myfile: 50 | frag = myfile.read() 51 | return vert,frag 52 | def compile(self,shader_type,shader_str): 53 | shader = GL.glCreateShader(shader_type) 54 | GL.glShaderSource(shader,shader_str) 55 | GL.glCompileShader(shader) 56 | status = GL.glGetShaderiv(shader,GL.GL_COMPILE_STATUS) 57 | if not status: 58 | log = GL.glGetShaderInfoLog(shader) 59 | shader_name = SHADER2STRING[shader_type] 60 | raise ShaderError,"Compile failure in {} shader:\n{}\n".format(shader_name,log) 61 | return shader 62 | 63 | def link(self): 64 | GL.glLinkProgram(self.shader) 65 | status = GL.glGetProgramiv(self.shader,GL.GL_LINK_STATUS) 66 | if not status: 67 | log = GL.glGetProgramInfoLog(self.shader) 68 | raise ShaderError,"Linking failue:\n{}\n".format(log) 69 | 70 | def setup_uniforms(self): 71 | self.elapsed_time_uniform = GL.glGetUniformLocation(self.shader,"time") 72 | self.period = GL.glGetUniformLocation(self.shader,"period") 73 | self.frag_period = GL.glGetUniformLocation(self.shader,"frag_period"); 74 | GL.glUseProgram(self.shader) 75 | GL.glUniform1f(self.period,5.0) 76 | GL.glUniform1f(self.frag_period,10.0) 77 | GL.glUseProgram(0) 78 | 79 | def display(self): 80 | GL.glClearColor(0,0,0,0) 81 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 82 | GL.glUseProgram(self.shader) 83 | 84 | GL.glUniform1f(self.elapsed_time_uniform,pg.time.get_ticks()/1000.0) 85 | 86 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 87 | GL.glEnableVertexAttribArray(0) 88 | GL.glVertexAttribPointer(0,VERT_COMPONENTS,GL.GL_FLOAT,False,0,None) 89 | GL.glDrawArrays(GL.GL_TRIANGLES,0,3) 90 | GL.glDisableVertexAttribArray(0) 91 | GL.glUseProgram(0) 92 | 93 | def reshape(self,width,height): 94 | GL.glViewport(0,0,width,height) 95 | 96 | class ShaderError(Exception): 97 | pass 98 | 99 | def main(): 100 | pg.init() 101 | os.environ['SDL_VIDEO_CENTERED'] = '1' 102 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 103 | MyClock = pg.time.Clock() 104 | MyGL = Shader(os.path.join("data","calcOffset.vert"),os.path.join("data","calcColor.frag")) 105 | done = False 106 | while not done: 107 | for event in pg.event.get(): 108 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 109 | done = True 110 | elif event.type == pg.KEYDOWN: 111 | pass 112 | elif event.type == pg.VIDEORESIZE: 113 | MyGL.reshape(*event.size) 114 | MyGL.display() 115 | pg.display.flip() 116 | MyClock.tick(65) 117 | 118 | if __name__ == '__main__': 119 | main() 120 | pg.quit() 121 | sys.exit() 122 | -------------------------------------------------------------------------------- /03_OpenGLs_moving_triangle/03_vertPositionOffset.py: -------------------------------------------------------------------------------- 1 | import sys,os,math 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | VERTICES = [ 0.25, 0.25, 0.0, 1.0, 6 | 0.25,-0.25, 0.0, 1.0, 7 | -0.25,-0.25, 0.0, 1.0] 8 | 9 | SIZE_FLOAT = VERT_COMPONENTS = 4 10 | 11 | SHADER2STRING = {GL.GL_VERTEX_SHADER : "vertex", 12 | GL.GL_GEOMETRY_SHADER : "geometry", 13 | GL.GL_FRAGMENT_SHADER : "fragment"} 14 | 15 | class Shader: 16 | def __init__(self,vert_file,frag_file): 17 | self.shader = GL.glCreateProgram() 18 | self.vbo = None 19 | self.init_all(vert_file,frag_file) 20 | self.reshape(500,500) 21 | self.offset_location = GL.glGetUniformLocation(self.shader,"offset") 22 | def init_all(self,vert_file,frag_file): 23 | self.attach_shaders(vert_file,frag_file) 24 | self.init_vertex_buf() 25 | vao = GL.glGenVertexArrays(1) 26 | GL.glBindVertexArray(vao) 27 | def init_vertex_buf(self): 28 | self.vbo = GL.glGenBuffers(1) 29 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 30 | ArrayType = (GL.GLfloat*len(VERTICES)) 31 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(VERTICES)*SIZE_FLOAT, 32 | ArrayType(*VERTICES),GL.GL_STATIC_DRAW) 33 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 34 | 35 | def attach_shaders(self,vert_file,frag_file): 36 | vert,frag = self.load_shader_files(vert_file,frag_file) 37 | shade_list = [] 38 | shade_list.append(self.compile(GL.GL_VERTEX_SHADER,vert)) 39 | shade_list.append(self.compile(GL.GL_FRAGMENT_SHADER,frag)) 40 | for shade in shade_list: 41 | GL.glAttachShader(self.shader,shade) 42 | self.link() 43 | for shade in shade_list: 44 | GL.glDetachShader(self.shader,shade) 45 | GL.glDeleteShader(shade) 46 | def load_shader_files(self,vert_file,frag_file): 47 | with open(vert_file,'r') as myfile: 48 | vert = myfile.read() 49 | with open(frag_file,'r') as myfile: 50 | frag = myfile.read() 51 | return vert,frag 52 | def compile(self,shader_type,shader_str): 53 | shader = GL.glCreateShader(shader_type) 54 | GL.glShaderSource(shader,shader_str) 55 | GL.glCompileShader(shader) 56 | status = GL.glGetShaderiv(shader,GL.GL_COMPILE_STATUS) 57 | if not status: 58 | log = GL.glGetShaderInfoLog(shader) 59 | shader_name = SHADER2STRING[shader_type] 60 | raise ShaderException,"Compile failure in {} shader:\n{}\n".format(shader_name,log) 61 | return shader 62 | 63 | def link(self): 64 | GL.glLinkProgram(self.shader) 65 | status = GL.glGetProgramiv(self.shader,GL.GL_LINK_STATUS) 66 | if not status: 67 | log = GL.glGetProgramInfoLog(self.shader) 68 | raise ShaderException,"Linking failue:\n{}\n".format(log) 69 | 70 | def display(self): 71 | offset = self.calc_position() 72 | GL.glClearColor(0,1,1,1) 73 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 74 | GL.glUseProgram(self.shader) 75 | 76 | GL.glUniform2f(self.offset_location,*offset) 77 | 78 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 79 | GL.glEnableVertexAttribArray(0) 80 | GL.glVertexAttribPointer(0,VERT_COMPONENTS,GL.GL_FLOAT,False,0,None) 81 | GL.glDrawArrays(GL.GL_TRIANGLES,0,3) 82 | GL.glDisableVertexAttribArray(0) 83 | GL.glUseProgram(0) 84 | 85 | def reshape(self,width,height): 86 | GL.glViewport(0,0,width,height) 87 | 88 | def calc_position(self): 89 | period = 5.0 90 | angular_s = (2*math.pi)/period 91 | magnitude = 0.5 92 | elapsed_time = pg.time.get_ticks()/1000.0 93 | times_through_loop = elapsed_time%period 94 | x_offset = math.cos(times_through_loop*angular_s)*magnitude 95 | y_offset = math.sin(times_through_loop*angular_s)*magnitude 96 | return x_offset,y_offset 97 | 98 | class ShaderException(Exception): 99 | pass 100 | 101 | def main(): 102 | pg.init() 103 | os.environ['SDL_VIDEO_CENTERED'] = '1' 104 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 105 | MyClock = pg.time.Clock() 106 | MyGL = Shader(os.path.join("data","positionOffset.vert"),os.path.join("data","standard.frag")) 107 | done = False 108 | while not done: 109 | for event in pg.event.get(): 110 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 111 | done = True 112 | elif event.type == pg.KEYDOWN: 113 | pass 114 | elif event.type == pg.VIDEORESIZE: 115 | MyGL.reshape(*event.size) 116 | MyGL.display() 117 | pg.display.flip() 118 | MyClock.tick(65) 119 | 120 | if __name__ == '__main__': 121 | main() 122 | pg.quit() 123 | sys.exit() 124 | -------------------------------------------------------------------------------- /05_objects_in_depth/05_DepthBuffer.py: -------------------------------------------------------------------------------- 1 | import sys,os,math 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | sys.path.append("..") 6 | sys.path.append("data") 7 | import myframework 8 | from vertex_data import VERTICES,INDICES,NUMBER_OF_VERTICES 9 | 10 | class Shader(myframework.BaseShader): 11 | def __init__(self,vertices,vert_file,frag_file,indices=None): 12 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file,indices) 13 | GL.glEnable(GL.GL_CULL_FACE) 14 | GL.glCullFace(GL.GL_BACK) 15 | GL.glFrontFace(GL.GL_CW) 16 | 17 | GL.glEnable(GL.GL_DEPTH_TEST) 18 | GL.glDepthMask(GL.GL_TRUE) 19 | GL.glDepthFunc(GL.GL_LEQUAL) 20 | GL.glDepthRange(0.0,1.0) 21 | 22 | def init_vertex_buf(self): 23 | self.vbo = GL.glGenBuffers(1) 24 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 25 | ArrayType = GL.GLfloat*len(self.vertices) 26 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(self.vertices)*self.size_float, 27 | ArrayType(*self.vertices),GL.GL_STATIC_DRAW) 28 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 29 | 30 | self.ibo = GL.glGenBuffers(1) 31 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 32 | ArrayType = (GL.GLushort*len(self.indices)) 33 | GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,len(self.indices)*self.size_short, 34 | ArrayType(*self.indices),GL.GL_STATIC_DRAW) 35 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,0) 36 | 37 | def init_vao(self): 38 | self.vao = GL.glGenVertexArrays(1) 39 | GL.glBindVertexArray(self.vao) 40 | color_data_offset = 3*self.size_float*NUMBER_OF_VERTICES 41 | 42 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 43 | GL.glEnableVertexAttribArray(0) 44 | GL.glEnableVertexAttribArray(1) 45 | GL.glVertexAttribPointer(0,3,GL.GL_FLOAT,GL.GL_FALSE,0,None) 46 | GL.glVertexAttribPointer(1,4,GL.GL_FLOAT,GL.GL_FALSE,0,GL.GLvoidp(color_data_offset)) 47 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 48 | GL.glBindVertexArray(0) 49 | 50 | def setup_uniforms(self): 51 | self.offset_location = GL.glGetUniformLocation(self.shader,"offset") 52 | self.perspective_matrix_unif = GL.glGetUniformLocation(self.shader,"perspectiveMatrix") 53 | self.frustum_scale = 1.0 54 | self.z_near,self.z_far = 1.0,3.0 55 | self.create_matrix() 56 | 57 | GL.glUseProgram(self.shader) 58 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 59 | GL.glUseProgram(0) 60 | 61 | def create_matrix(self): 62 | self.the_matrix = [0.0 for i in range(16)] 63 | self.the_matrix[0] = self.frustum_scale 64 | self.the_matrix[5] = self.frustum_scale 65 | self.the_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 66 | self.the_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 67 | self.the_matrix[11] = -1.0 68 | 69 | def display(self): 70 | GL.glClearColor(0,0,0,0) 71 | GL.glClearDepth(1.0) 72 | GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 73 | 74 | GL.glUseProgram(self.shader) 75 | GL.glBindVertexArray(self.vao) 76 | GL.glUniform3f(self.offset_location,0.0,0.0,0.0) 77 | GL.glDrawElements(GL.GL_TRIANGLES,len(self.indices),GL.GL_UNSIGNED_SHORT,None) 78 | 79 | GL.glUniform3f(self.offset_location,0.0,0.0,-1.0) 80 | GL.glDrawElementsBaseVertex(GL.GL_TRIANGLES,len(self.indices), 81 | GL.GL_UNSIGNED_SHORT,None,NUMBER_OF_VERTICES/2) 82 | GL.glBindVertexArray(0) 83 | GL.glUseProgram(0) 84 | 85 | def reshape(self,width,height): 86 | self.the_matrix[0] = self.frustum_scale/(width/float(height)) 87 | self.the_matrix[5] = self.frustum_scale 88 | GL.glUseProgram(self.shader) 89 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 90 | GL.glUseProgram(0) 91 | GL.glViewport(0,0,width,height) 92 | 93 | def main(): 94 | pg.init() 95 | os.environ['SDL_VIDEO_CENTERED'] = '1' 96 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 97 | MyClock = pg.time.Clock() 98 | MyGL = Shader(VERTICES[:],os.path.join("data","Standard.vert"), 99 | os.path.join("data","Standard.frag"),INDICES[:]) 100 | done = False 101 | while not done: 102 | for event in pg.event.get(): 103 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 104 | done = True 105 | elif event.type == pg.KEYDOWN: 106 | pass 107 | elif event.type == pg.VIDEORESIZE: 108 | MyGL.reshape(*event.size) 109 | MyGL.display() 110 | pg.display.flip() 111 | MyClock.tick(60) 112 | 113 | if __name__ == '__main__': 114 | main() 115 | pg.quit() 116 | sys.exit() -------------------------------------------------------------------------------- /05_objects_in_depth/05_VertexClipping.py: -------------------------------------------------------------------------------- 1 | import sys,os,math 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | sys.path.append("..") 6 | sys.path.append("data") 7 | import myframework 8 | from vertex_data import VERTICES,INDICES,NUMBER_OF_VERTICES 9 | 10 | class Shader(myframework.BaseShader): 11 | def __init__(self,vertices,vert_file,frag_file,indices=None): 12 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file,indices) 13 | GL.glEnable(GL.GL_CULL_FACE) 14 | GL.glCullFace(GL.GL_BACK) 15 | GL.glFrontFace(GL.GL_CW) 16 | 17 | GL.glEnable(GL.GL_DEPTH_TEST) 18 | GL.glDepthMask(GL.GL_TRUE) 19 | GL.glDepthFunc(GL.GL_LEQUAL) 20 | GL.glDepthRange(0.0,1.0) 21 | 22 | def init_vertex_buf(self): 23 | self.vbo = GL.glGenBuffers(1) 24 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 25 | ArrayType = GL.GLfloat*len(self.vertices) 26 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(self.vertices)*self.size_float, 27 | ArrayType(*self.vertices),GL.GL_STATIC_DRAW) 28 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 29 | 30 | self.ibo = GL.glGenBuffers(1) 31 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 32 | ArrayType = (GL.GLushort*len(self.indices)) 33 | GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,len(self.indices)*self.size_short, 34 | ArrayType(*self.indices),GL.GL_STATIC_DRAW) 35 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,0) 36 | 37 | def init_vao(self): 38 | self.vao = GL.glGenVertexArrays(1) 39 | GL.glBindVertexArray(self.vao) 40 | color_data_offset = 3*self.size_float*NUMBER_OF_VERTICES 41 | 42 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 43 | GL.glEnableVertexAttribArray(0) 44 | GL.glEnableVertexAttribArray(1) 45 | GL.glVertexAttribPointer(0,3,GL.GL_FLOAT,GL.GL_FALSE,0,None) 46 | GL.glVertexAttribPointer(1,4,GL.GL_FLOAT,GL.GL_FALSE,0,GL.GLvoidp(color_data_offset)) 47 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 48 | GL.glBindVertexArray(0) 49 | 50 | def setup_uniforms(self): 51 | self.offset_location = GL.glGetUniformLocation(self.shader,"offset") 52 | self.perspective_matrix_unif = GL.glGetUniformLocation(self.shader,"perspectiveMatrix") 53 | self.frustum_scale = 1.0 54 | self.z_near,self.z_far = 1.0,3.0 55 | self.create_matrix() 56 | 57 | GL.glUseProgram(self.shader) 58 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 59 | GL.glUseProgram(0) 60 | 61 | def create_matrix(self): 62 | self.the_matrix = [0.0 for i in range(16)] 63 | self.the_matrix[0] = self.frustum_scale 64 | self.the_matrix[5] = self.frustum_scale 65 | self.the_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 66 | self.the_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 67 | self.the_matrix[11] = -1.0 68 | 69 | def display(self): 70 | GL.glClearColor(0,0,0,0) 71 | GL.glClearDepth(1.0) 72 | GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 73 | 74 | GL.glUseProgram(self.shader) 75 | GL.glBindVertexArray(self.vao) 76 | GL.glUniform3f(self.offset_location,0.0,0.0,0.5) 77 | GL.glDrawElements(GL.GL_TRIANGLES,len(self.indices),GL.GL_UNSIGNED_SHORT,None) 78 | 79 | GL.glUniform3f(self.offset_location,0.0,0.0,-1.0) 80 | GL.glDrawElementsBaseVertex(GL.GL_TRIANGLES,len(self.indices), 81 | GL.GL_UNSIGNED_SHORT,None,NUMBER_OF_VERTICES/2) 82 | GL.glBindVertexArray(0) 83 | GL.glUseProgram(0) 84 | 85 | def reshape(self,width,height): 86 | self.the_matrix[0] = self.frustum_scale/(width/float(height)) 87 | self.the_matrix[5] = self.frustum_scale 88 | GL.glUseProgram(self.shader) 89 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 90 | GL.glUseProgram(0) 91 | GL.glViewport(0,0,width,height) 92 | 93 | def main(): 94 | pg.init() 95 | os.environ['SDL_VIDEO_CENTERED'] = '1' 96 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 97 | MyClock = pg.time.Clock() 98 | MyGL = Shader(VERTICES[:],os.path.join("data","Standard.vert"), 99 | os.path.join("data","Standard.frag"),INDICES[:]) 100 | done = False 101 | while not done: 102 | for event in pg.event.get(): 103 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 104 | done = True 105 | elif event.type == pg.KEYDOWN: 106 | pass 107 | elif event.type == pg.VIDEORESIZE: 108 | MyGL.reshape(*event.size) 109 | MyGL.display() 110 | pg.display.flip() 111 | MyClock.tick(60) 112 | 113 | if __name__ == '__main__': 114 | main() 115 | pg.quit() 116 | sys.exit() -------------------------------------------------------------------------------- /03_OpenGLs_moving_triangle/03_cpuPositionOffset.py: -------------------------------------------------------------------------------- 1 | import sys,os,math 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | VERTICES = [ 0.25, 0.25, 0.0, 1.0, 6 | 0.25,-0.25, 0.0, 1.0, 7 | -0.25,-0.25, 0.0, 1.0] 8 | 9 | SIZE_FLOAT = VERT_COMPONENTS = 4 10 | 11 | SHADER2STRING = {GL.GL_VERTEX_SHADER : "vertex", 12 | GL.GL_GEOMETRY_SHADER : "geometry", 13 | GL.GL_FRAGMENT_SHADER : "fragment"} 14 | 15 | class Shader: 16 | def __init__(self,vert_file,frag_file): 17 | self.shader = GL.glCreateProgram() 18 | self.vbo = None 19 | self.offset = [0,0] 20 | self.init_all(vert_file,frag_file) 21 | self.reshape(500,500) 22 | def init_all(self,vert_file,frag_file): 23 | self.attach_shaders(vert_file,frag_file) 24 | self.init_vertex_buf() 25 | vao = GL.glGenVertexArrays(1) 26 | GL.glBindVertexArray(vao) 27 | def init_vertex_buf(self): 28 | self.vbo = GL.glGenBuffers(1) 29 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 30 | ArrayType = (GL.GLfloat*len(VERTICES)) 31 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(VERTICES)*SIZE_FLOAT, 32 | ArrayType(*VERTICES),GL.GL_STREAM_DRAW) 33 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 34 | 35 | def attach_shaders(self,vert_file,frag_file): 36 | vert,frag = self.load_shader_files(vert_file,frag_file) 37 | shade_list = [] 38 | shade_list.append(self.compile(GL.GL_VERTEX_SHADER,vert)) 39 | shade_list.append(self.compile(GL.GL_FRAGMENT_SHADER,frag)) 40 | for shade in shade_list: 41 | GL.glAttachShader(self.shader,shade) 42 | self.link() 43 | for shade in shade_list: 44 | GL.glDetachShader(self.shader,shade) 45 | GL.glDeleteShader(shade) 46 | def load_shader_files(self,vert_file,frag_file): 47 | with open(vert_file,'r') as myfile: 48 | vert = myfile.read() 49 | with open(frag_file,'r') as myfile: 50 | frag = myfile.read() 51 | return vert,frag 52 | def compile(self,shader_type,shader_str): 53 | shader = GL.glCreateShader(shader_type) 54 | GL.glShaderSource(shader,shader_str) 55 | GL.glCompileShader(shader) 56 | status = GL.glGetShaderiv(shader,GL.GL_COMPILE_STATUS) 57 | if not status: 58 | log = GL.glGetShaderInfoLog(shader) 59 | shader_name = SHADER2STRING[shader_type] 60 | raise ShaderException,"Compile failure in {} shader:\n{}\n".format(shader_name,log) 61 | return shader 62 | 63 | def link(self): 64 | GL.glLinkProgram(self.shader) 65 | status = GL.glGetProgramiv(self.shader,GL.GL_LINK_STATUS) 66 | if not status: 67 | log = GL.glGetProgramInfoLog(self.shader) 68 | raise ShaderException,"Linking failue:\n{}\n".format(log) 69 | 70 | def display(self): 71 | self.calc_position() 72 | self.adjust_vert_data() 73 | GL.glClearColor(0,0,0,0) 74 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 75 | 76 | GL.glUseProgram(self.shader) 77 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 78 | GL.glEnableVertexAttribArray(0) 79 | GL.glVertexAttribPointer(0,VERT_COMPONENTS,GL.GL_FLOAT,False,0,None) 80 | GL.glDrawArrays(GL.GL_TRIANGLES,0,3) 81 | GL.glDisableVertexAttribArray(0) 82 | GL.glUseProgram(0) 83 | 84 | def reshape(self,width,height): 85 | GL.glViewport(0,0,width,height) 86 | 87 | def calc_position(self): 88 | period = 5.0 89 | angular_s = (2*math.pi)/period 90 | magnitude = 0.5 91 | elapsed_time = pg.time.get_ticks()/1000.0 92 | times_through_loop = elapsed_time%period 93 | x_offset = math.cos(times_through_loop*angular_s)*magnitude 94 | y_offset = math.sin(times_through_loop*angular_s)*magnitude 95 | self.offset = [x_offset,y_offset] 96 | def adjust_vert_data(self): 97 | moveit = VERTICES[:] 98 | for i in range(0,len(VERTICES),4): 99 | moveit[i] += self.offset[0] 100 | moveit[i+1] += self.offset[1] 101 | 102 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER, self.vbo) 103 | ArrayType = (GL.GLfloat*len(VERTICES)) 104 | Array = ArrayType(*moveit) 105 | GL.glBufferSubData(GL.GL_ARRAY_BUFFER,0,len(VERTICES)*SIZE_FLOAT,Array) 106 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 107 | 108 | class ShaderException(Exception): 109 | pass 110 | 111 | def main(): 112 | pg.init() 113 | os.environ['SDL_VIDEO_CENTERED'] = '1' 114 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 115 | MyClock = pg.time.Clock() 116 | MyGL = Shader(os.path.join("data","standard.vert"),os.path.join("data","standard.frag")) 117 | done = False 118 | while not done: 119 | for event in pg.event.get(): 120 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 121 | done = True 122 | elif event.type == pg.KEYDOWN: 123 | pass 124 | elif event.type == pg.VIDEORESIZE: 125 | MyGL.reshape(*event.size) 126 | MyGL.display() 127 | pg.display.flip() 128 | MyClock.tick(65) 129 | 130 | if __name__ == '__main__': 131 | main() 132 | pg.quit() 133 | sys.exit() 134 | -------------------------------------------------------------------------------- /05_objects_in_depth/05_DepthClamping.py: -------------------------------------------------------------------------------- 1 | """I had to import depth_clamp as an ARB extension to make this work. 2 | OpenGL.GL should include GL_DEPTH_CLAMP, but it doesn't.""" 3 | import sys,os,math 4 | import pygame as pg 5 | from OpenGL import GL 6 | from OpenGL.GL.ARB import depth_clamp as dc 7 | 8 | sys.path.append("..") 9 | sys.path.append("data") 10 | import myframework 11 | from vertex_data import VERTICES,INDICES,NUMBER_OF_VERTICES 12 | 13 | class Shader(myframework.BaseShader): 14 | def __init__(self,vertices,vert_file,frag_file,indices=None): 15 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file,indices) 16 | GL.glEnable(GL.GL_CULL_FACE) 17 | GL.glCullFace(GL.GL_BACK) 18 | GL.glFrontFace(GL.GL_CW) 19 | 20 | GL.glEnable(GL.GL_DEPTH_TEST) 21 | GL.glDepthMask(GL.GL_TRUE) 22 | GL.glDepthFunc(GL.GL_LEQUAL) 23 | GL.glDepthRange(0.0,1.0) 24 | 25 | def init_vertex_buf(self): 26 | self.vbo = GL.glGenBuffers(1) 27 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 28 | ArrayType = GL.GLfloat*len(self.vertices) 29 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(self.vertices)*self.size_float, 30 | ArrayType(*self.vertices),GL.GL_STATIC_DRAW) 31 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 32 | 33 | self.ibo = GL.glGenBuffers(1) 34 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 35 | ArrayType = (GL.GLushort*len(self.indices)) 36 | GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,len(self.indices)*self.size_short, 37 | ArrayType(*self.indices),GL.GL_STATIC_DRAW) 38 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,0) 39 | 40 | def init_vao(self): 41 | self.vao = GL.glGenVertexArrays(1) 42 | GL.glBindVertexArray(self.vao) 43 | color_data_offset = 3*self.size_float*NUMBER_OF_VERTICES 44 | 45 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 46 | GL.glEnableVertexAttribArray(0) 47 | GL.glEnableVertexAttribArray(1) 48 | GL.glVertexAttribPointer(0,3,GL.GL_FLOAT,GL.GL_FALSE,0,None) 49 | GL.glVertexAttribPointer(1,4,GL.GL_FLOAT,GL.GL_FALSE,0,GL.GLvoidp(color_data_offset)) 50 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 51 | GL.glBindVertexArray(0) 52 | 53 | def setup_uniforms(self): 54 | self.offset_location = GL.glGetUniformLocation(self.shader,"offset") 55 | self.perspective_matrix_unif = GL.glGetUniformLocation(self.shader,"perspectiveMatrix") 56 | self.frustum_scale = 1.0 57 | self.z_near,self.z_far = 1.0,3.0 58 | self.create_matrix() 59 | 60 | GL.glUseProgram(self.shader) 61 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 62 | GL.glUseProgram(0) 63 | 64 | def create_matrix(self): 65 | self.the_matrix = [0.0 for i in range(16)] 66 | self.the_matrix[0] = self.frustum_scale 67 | self.the_matrix[5] = self.frustum_scale 68 | self.the_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 69 | self.the_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 70 | self.the_matrix[11] = -1.0 71 | 72 | def display(self): 73 | GL.glClearColor(0,0,0,0) 74 | GL.glClearDepth(1.0) 75 | GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 76 | 77 | GL.glUseProgram(self.shader) 78 | GL.glBindVertexArray(self.vao) 79 | GL.glUniform3f(self.offset_location,0.0,0.0,0.5) 80 | GL.glDrawElements(GL.GL_TRIANGLES,len(self.indices),GL.GL_UNSIGNED_SHORT,None) 81 | 82 | GL.glUniform3f(self.offset_location,0.0,0.0,-1.0) 83 | GL.glDrawElementsBaseVertex(GL.GL_TRIANGLES,len(self.indices), 84 | GL.GL_UNSIGNED_SHORT,None,NUMBER_OF_VERTICES/2) 85 | GL.glBindVertexArray(0) 86 | GL.glUseProgram(0) 87 | 88 | def reshape(self,width,height): 89 | self.the_matrix[0] = self.frustum_scale/(width/float(height)) 90 | self.the_matrix[5] = self.frustum_scale 91 | GL.glUseProgram(self.shader) 92 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 93 | GL.glUseProgram(0) 94 | GL.glViewport(0,0,width,height) 95 | 96 | def main(): 97 | pg.init() 98 | os.environ['SDL_VIDEO_CENTERED'] = '1' 99 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 100 | MyClock = pg.time.Clock() 101 | MyGL = Shader(VERTICES[:],os.path.join("data","Standard.vert"), 102 | os.path.join("data","Standard.frag"),INDICES[:]) 103 | depth_clamped = False 104 | done = False 105 | while not done: 106 | for event in pg.event.get(): 107 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 108 | done = True 109 | elif event.type == pg.KEYDOWN: 110 | if event.key == pg.K_SPACE: 111 | GL.glDisable(dc.GL_DEPTH_CLAMP) if depth_clamped else GL.glEnable(dc.GL_DEPTH_CLAMP) 112 | depth_clamped = not depth_clamped 113 | elif event.type == pg.VIDEORESIZE: 114 | MyGL.reshape(*event.size) 115 | MyGL.display() 116 | pg.display.flip() 117 | MyClock.tick(60) 118 | 119 | if __name__ == '__main__': 120 | main() 121 | pg.quit() 122 | sys.exit() -------------------------------------------------------------------------------- /05_objects_in_depth/05_OverlapNoDepth.py: -------------------------------------------------------------------------------- 1 | import sys,os,math 2 | import pygame as pg 3 | from OpenGL import GL 4 | 5 | sys.path.append("..") 6 | sys.path.append("data") 7 | import myframework 8 | from vertex_data import VERTICES,INDICES,NUMBER_OF_VERTICES 9 | 10 | class Shader(myframework.BaseShader): 11 | def __init__(self,vertices,vert_file,frag_file,indices=None): 12 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file,indices) 13 | GL.glEnable(GL.GL_CULL_FACE) 14 | GL.glCullFace(GL.GL_BACK) 15 | GL.glFrontFace(GL.GL_CW) 16 | 17 | def init_vertex_buf(self): 18 | self.vbo = GL.glGenBuffers(1) 19 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 20 | ArrayType = GL.GLfloat*len(self.vertices) 21 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(self.vertices)*self.size_float, 22 | ArrayType(*self.vertices),GL.GL_STATIC_DRAW) 23 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 24 | 25 | self.ibo = GL.glGenBuffers(1) 26 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 27 | ArrayType = (GL.GLushort*len(self.indices)) 28 | GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,len(self.indices)*self.size_short, 29 | ArrayType(*self.indices),GL.GL_STATIC_DRAW) 30 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,0) 31 | 32 | def init_vao(self): 33 | self.vao1 = GL.glGenVertexArrays(1) 34 | GL.glBindVertexArray(self.vao1) 35 | color_data_offset = 3*self.size_float*NUMBER_OF_VERTICES 36 | 37 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 38 | GL.glEnableVertexAttribArray(0) 39 | GL.glEnableVertexAttribArray(1) 40 | GL.glVertexAttribPointer(0,3,GL.GL_FLOAT,GL.GL_FALSE,0,None) 41 | GL.glVertexAttribPointer(1,4,GL.GL_FLOAT,GL.GL_FALSE,0,GL.GLvoidp(color_data_offset)) 42 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 43 | GL.glBindVertexArray(0) 44 | 45 | self.vao2 = GL.glGenVertexArrays(1) 46 | GL.glBindVertexArray(self.vao2) 47 | 48 | pos_data_offset = 3*self.size_float*(NUMBER_OF_VERTICES/2) 49 | color_data_offset += 4*self.size_float*(NUMBER_OF_VERTICES/2) 50 | 51 | #Use the same buffer object previously bound to GL_ARRAY_BUFFER. 52 | GL.glEnableVertexAttribArray(0) 53 | GL.glEnableVertexAttribArray(1) 54 | GL.glVertexAttribPointer(0,3,GL.GL_FLOAT,GL.GL_FALSE,0,GL.GLvoidp(pos_data_offset)) 55 | GL.glVertexAttribPointer(1,4,GL.GL_FLOAT,GL.GL_FALSE,0,GL.GLvoidp(color_data_offset)) 56 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 57 | GL.glBindVertexArray(0) 58 | 59 | def setup_uniforms(self): 60 | self.offset_location = GL.glGetUniformLocation(self.shader,"offset") 61 | self.perspective_matrix_unif = GL.glGetUniformLocation(self.shader,"perspectiveMatrix") 62 | self.frustum_scale = 1.0 63 | self.z_near,self.z_far = 1.0,3.0 64 | self.create_matrix() 65 | 66 | GL.glUseProgram(self.shader) 67 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 68 | GL.glUseProgram(0) 69 | 70 | def create_matrix(self): 71 | self.the_matrix = [0.0 for i in range(16)] 72 | self.the_matrix[0] = self.frustum_scale 73 | self.the_matrix[5] = self.frustum_scale 74 | self.the_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 75 | self.the_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 76 | self.the_matrix[11] = -1.0 77 | 78 | def display(self): 79 | GL.glClearColor(0,0,0,0) 80 | GL.glClear(GL.GL_COLOR_BUFFER_BIT) 81 | 82 | GL.glUseProgram(self.shader) 83 | 84 | GL.glBindVertexArray(self.vao1) 85 | GL.glUniform3f(self.offset_location,0.0,0.0,0.0) 86 | GL.glDrawElements(GL.GL_TRIANGLES,len(self.indices),GL.GL_UNSIGNED_SHORT,None) 87 | 88 | GL.glBindVertexArray(self.vao2) 89 | GL.glUniform3f(self.offset_location,0.0,0.0,-1.0) 90 | GL.glDrawElements(GL.GL_TRIANGLES,len(self.indices),GL.GL_UNSIGNED_SHORT,None) 91 | 92 | GL.glBindVertexArray(0) 93 | GL.glUseProgram(0) 94 | 95 | def reshape(self,width,height): 96 | self.the_matrix[0] = self.frustum_scale/(width/float(height)) 97 | self.the_matrix[5] = self.frustum_scale 98 | GL.glUseProgram(self.shader) 99 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 100 | GL.glUseProgram(0) 101 | GL.glViewport(0,0,width,height) 102 | 103 | def main(): 104 | pg.init() 105 | os.environ['SDL_VIDEO_CENTERED'] = '1' 106 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 107 | MyClock = pg.time.Clock() 108 | MyGL = Shader(VERTICES[:],os.path.join("data","Standard.vert"), 109 | os.path.join("data","Standard.frag"),INDICES[:]) 110 | done = False 111 | while not done: 112 | for event in pg.event.get(): 113 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 114 | done = True 115 | elif event.type == pg.KEYDOWN: 116 | pass 117 | elif event.type == pg.VIDEORESIZE: 118 | MyGL.reshape(*event.size) 119 | MyGL.display() 120 | pg.display.flip() 121 | MyClock.tick(60) 122 | 123 | if __name__ == '__main__': 124 | main() 125 | pg.quit() 126 | sys.exit() -------------------------------------------------------------------------------- /05_objects_in_depth/05_DepthFighting.py: -------------------------------------------------------------------------------- 1 | """The author doesn't actually mention this file in his tutorial. 2 | It seems it may not have been finished; I'm not sure. I've done my best to 3 | make it functional. It appears to be intended to show how, when two surfaces 4 | are very close to each other, they can't decide which surface should be on top. 5 | Controls are 'qwer' and 'asdf'. I have thusfar not gotten the pixel buffer 6 | section to work, nor am I quite sure what it was meant to do.""" 7 | import sys,os,math 8 | import pygame as pg 9 | from OpenGL import GL 10 | 11 | sys.path.append("..") 12 | sys.path.append("data") 13 | import myframework 14 | from fighting_data import VERTICES,INDICES,NUMBER_OF_VERTICES 15 | 16 | KEYDICT = {pg.K_q:100 ,pg.K_a:-100, 17 | pg.K_w:10 ,pg.K_s:-10, 18 | pg.K_e:1 ,pg.K_d:-1, 19 | pg.K_r:0.1 ,pg.K_f:-0.1, 20 | pg.K_t:0.01,pg.K_g:-0.01} 21 | 22 | class Shader(myframework.BaseShader): 23 | def __init__(self,vertices,vert_file,frag_file,indices=None): 24 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file,indices) 25 | GL.glEnable(GL.GL_CULL_FACE) 26 | GL.glCullFace(GL.GL_BACK) 27 | GL.glFrontFace(GL.GL_CW) 28 | 29 | GL.glEnable(GL.GL_DEPTH_TEST) 30 | GL.glDepthMask(GL.GL_TRUE) 31 | GL.glDepthFunc(GL.GL_LEQUAL) 32 | GL.glDepthRange(0.0,1.0) 33 | 34 | self.read_buffer = False 35 | self.delta = 0.0 36 | 37 | def init_vertex_buf(self): 38 | self.vbo = GL.glGenBuffers(1) 39 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 40 | ArrayType = GL.GLfloat*len(self.vertices) 41 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(self.vertices)*self.size_float, 42 | ArrayType(*self.vertices),GL.GL_STATIC_DRAW) 43 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 44 | 45 | self.ibo = GL.glGenBuffers(1) 46 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 47 | ArrayType = (GL.GLushort*len(self.indices)) 48 | GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,len(self.indices)*self.size_short, 49 | ArrayType(*self.indices),GL.GL_STATIC_DRAW) 50 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,0) 51 | 52 | def init_vao(self): 53 | self.vao = GL.glGenVertexArrays(1) 54 | GL.glBindVertexArray(self.vao) 55 | color_data_offset = 3*self.size_float*NUMBER_OF_VERTICES 56 | 57 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 58 | GL.glEnableVertexAttribArray(0) 59 | GL.glEnableVertexAttribArray(1) 60 | GL.glVertexAttribPointer(0,3,GL.GL_FLOAT,GL.GL_FALSE,0,None) 61 | GL.glVertexAttribPointer(1,4,GL.GL_FLOAT,GL.GL_FALSE,0,GL.GLvoidp(color_data_offset)) 62 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 63 | GL.glBindVertexArray(0) 64 | 65 | def setup_uniforms(self): 66 | self.offset_location = GL.glGetUniformLocation(self.shader,"offset") 67 | self.perspective_matrix_unif = GL.glGetUniformLocation(self.shader,"perspectiveMatrix") 68 | self.frustum_scale = 1.0 69 | self.z_near,self.z_far = 1.0,100000.0 70 | self.create_matrix() 71 | 72 | GL.glUseProgram(self.shader) 73 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 74 | GL.glUseProgram(0) 75 | 76 | def create_matrix(self): 77 | self.the_matrix = [0.0 for i in range(16)] 78 | self.the_matrix[0] = self.frustum_scale 79 | self.the_matrix[5] = self.frustum_scale 80 | self.the_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 81 | self.the_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 82 | self.the_matrix[11] = -1.0 83 | 84 | def display(self): 85 | GL.glClearColor(0,0,0,0) 86 | GL.glClearDepth(1.0) 87 | GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 88 | 89 | GL.glUseProgram(self.shader) 90 | GL.glBindVertexArray(self.vao) 91 | z_offset = self.calc_z_offset() 92 | GL.glUniform3f(self.offset_location,0.0,0.0,z_offset) 93 | GL.glDrawElements(GL.GL_TRIANGLES,len(self.indices),GL.GL_UNSIGNED_SHORT,None) 94 | 95 | GL.glBindVertexArray(0) 96 | GL.glUseProgram(0) 97 | 98 | ## self.check_pixel_buffer() 99 | 100 | ## def check_pixel_buffer(self): 101 | ## if self.read_buffer: 102 | ## self.read_buffer = False 103 | ## ArrayType = (GL.GLuint*(500*500)) 104 | ## GL.glReadPixels(0,0,500,500,GL.GL_DEPTH_STENCIL,GL.GL_UNSIGNED_INT_24_8,ArrayType()) 105 | 106 | def calc_z_offset(self): 107 | start = 2534.0 108 | period = 5.0 109 | angular_speed = 2*math.pi/period 110 | elapsed_time = pg.time.get_ticks()/1000.0 111 | times_through_loop = elapsed_time%period 112 | ## result = math.cos(times_through_loop*angular_speed)*500.0-start 113 | result = self.delta-start 114 | return result 115 | 116 | def reshape(self,width,height): 117 | self.the_matrix[0] = self.frustum_scale/(width/float(height)) 118 | self.the_matrix[5] = self.frustum_scale 119 | GL.glUseProgram(self.shader) 120 | GL.glUniformMatrix4fv(self.perspective_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 121 | GL.glUseProgram(0) 122 | GL.glViewport(0,0,width,height) 123 | 124 | def main(): 125 | pg.init() 126 | os.environ['SDL_VIDEO_CENTERED'] = '1' 127 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 128 | MyClock = pg.time.Clock() 129 | MyGL = Shader(VERTICES[:],os.path.join("data","Standard.vert"), 130 | os.path.join("data","Standard.frag"),INDICES[:]) 131 | done = False 132 | while not done: 133 | for event in pg.event.get(): 134 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 135 | done = True 136 | elif event.type == pg.KEYDOWN: 137 | if event.key == pg.K_SPACE: 138 | MyGL.read_buffer = True 139 | elif event.type == pg.VIDEORESIZE: 140 | MyGL.reshape(*event.size) 141 | pressed = pg.key.get_pressed() 142 | for key in KEYDICT: 143 | if pressed[key]: 144 | MyGL.delta += KEYDICT[key] 145 | MyGL.display() 146 | pg.display.flip() 147 | MyClock.tick(60) 148 | 149 | if __name__ == '__main__': 150 | main() 151 | pg.quit() 152 | sys.exit() -------------------------------------------------------------------------------- /06_objects_in_motion/06_Translation.py: -------------------------------------------------------------------------------- 1 | """Just using regular lists and tuples for the things taken care of using 2 | GLM in the original tutorial. Nothing here is complex enough to require resorting 3 | to numpy or another library yet.""" 4 | import sys,os,math 5 | import pygame as pg 6 | ##import numpy as np 7 | from OpenGL import GL 8 | 9 | sys.path.append("..") 10 | sys.path.append("data") 11 | import myframework 12 | from vertex_data import VERTICES,INDICES,NUMBER_OF_VERTICES 13 | 14 | class Shader(myframework.BaseShader): 15 | def __init__(self,vertices,vert_file,frag_file,indices=None): 16 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file,indices) 17 | GL.glEnable(GL.GL_CULL_FACE) 18 | GL.glCullFace(GL.GL_BACK) 19 | GL.glFrontFace(GL.GL_CW) 20 | 21 | GL.glEnable(GL.GL_DEPTH_TEST) 22 | GL.glDepthMask(GL.GL_TRUE) 23 | GL.glDepthFunc(GL.GL_LEQUAL) 24 | GL.glDepthRange(0.0,1.0) 25 | 26 | self.Objects = (Stationary(),Oval(),Circular()) 27 | 28 | def init_vertex_buf(self): 29 | self.vbo = GL.glGenBuffers(1) 30 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 31 | ArrayType = GL.GLfloat*len(self.vertices) 32 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(self.vertices)*self.size_float, 33 | ArrayType(*self.vertices),GL.GL_STATIC_DRAW) 34 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 35 | 36 | self.ibo = GL.glGenBuffers(1) 37 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 38 | ArrayType = (GL.GLushort*len(self.indices)) 39 | GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,len(self.indices)*self.size_short, 40 | ArrayType(*self.indices),GL.GL_STATIC_DRAW) 41 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,0) 42 | 43 | def init_vao(self): 44 | self.vao = GL.glGenVertexArrays(1) 45 | GL.glBindVertexArray(self.vao) 46 | color_data_offset = 3*self.size_float*NUMBER_OF_VERTICES 47 | 48 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 49 | GL.glEnableVertexAttribArray(0) 50 | GL.glEnableVertexAttribArray(1) 51 | GL.glVertexAttribPointer(0,3,GL.GL_FLOAT,GL.GL_FALSE,0,None) 52 | GL.glVertexAttribPointer(1,4,GL.GL_FLOAT,GL.GL_FALSE,0,GL.GLvoidp(color_data_offset)) 53 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 54 | GL.glBindVertexArray(0) 55 | 56 | def setup_uniforms(self): 57 | self.model2cam_matrix_unif = GL.glGetUniformLocation(self.shader,"modelToCameraMatrix") 58 | self.cam2clip_matrix_unif = GL.glGetUniformLocation(self.shader,"cameraToClipMatrix") 59 | self.frustum_scale = self.calc_frust_scale(45.0) 60 | self.z_near,self.z_far = 1.0,45.0 61 | self.create_matrix() 62 | 63 | GL.glUseProgram(self.shader) 64 | GL.glUniformMatrix4fv(self.cam2clip_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 65 | GL.glUseProgram(0) 66 | 67 | def calc_frust_scale(self,angle): 68 | rads = math.radians(angle) 69 | return 1.0/math.tan(rads/2.0) 70 | 71 | def create_matrix(self): 72 | self.the_matrix = [0.0 for i in range(16)] 73 | self.the_matrix[0] = self.frustum_scale 74 | self.the_matrix[5] = self.frustum_scale 75 | self.the_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 76 | self.the_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 77 | self.the_matrix[11] = -1.0 78 | 79 | def display(self): 80 | GL.glClearColor(0,0,0,0) 81 | GL.glClearDepth(1.0) 82 | GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 83 | 84 | GL.glUseProgram(self.shader) 85 | GL.glBindVertexArray(self.vao) 86 | 87 | elapsed_time = pg.time.get_ticks()/1000.0 88 | for Obj in self.Objects: 89 | matrix = Obj.construct_matrix(elapsed_time) 90 | GL.glUniformMatrix4fv(self.model2cam_matrix_unif,1,GL.GL_FALSE,matrix) 91 | GL.glDrawElements(GL.GL_TRIANGLES,len(self.indices),GL.GL_UNSIGNED_SHORT,None) 92 | 93 | GL.glBindVertexArray(0) 94 | GL.glUseProgram(0) 95 | 96 | def reshape(self,width,height): 97 | self.the_matrix[0] = self.frustum_scale/(width/float(height)) 98 | self.the_matrix[5] = self.frustum_scale 99 | GL.glUseProgram(self.shader) 100 | GL.glUniformMatrix4fv(self.cam2clip_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 101 | GL.glUseProgram(0) 102 | GL.glViewport(0,0,width,height) 103 | 104 | class Generic: 105 | def construct_matrix(self,time): 106 | ## mat = np.identity(4,'f') #Use a numpy array instead. 107 | mat = [[0.0 for i in range(4)] for j in range(4)] 108 | for i,stuff in enumerate(mat): 109 | mat[i][i] = 1.0 110 | mat[3] = self.calc_offset(time)+(1.0,) 111 | return mat 112 | 113 | class Stationary(Generic): 114 | def calc_offset(self,time): 115 | return (0.0,0.0,-20.0) 116 | 117 | class Oval(Generic): 118 | def calc_offset(self,time): 119 | period = 3.0 120 | angular_speed = 2*math.pi/period 121 | time_through_loop = time%period 122 | return (math.cos(time_through_loop*angular_speed)*4.0, 123 | math.sin(time_through_loop*angular_speed)*6.0, 124 | -20.0) 125 | 126 | class Circular(Generic): 127 | def calc_offset(self,time): 128 | period = 12.0 129 | angular_speed = 2*math.pi/period 130 | time_through_loop = time%period 131 | return (math.cos(time_through_loop*angular_speed)*5.0, 132 | 0.0, 133 | math.sin(time_through_loop*angular_speed)*5.0-20.0) 134 | 135 | def main(): 136 | pg.init() 137 | os.environ['SDL_VIDEO_CENTERED'] = '1' 138 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 139 | MyClock = pg.time.Clock() 140 | MyGL = Shader(VERTICES[:],os.path.join("data","PosColorLocalTransform.vert"), 141 | os.path.join("data","ColorPassthrough.frag"),INDICES[:]) 142 | done = False 143 | while not done: 144 | for event in pg.event.get(): 145 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 146 | done = True 147 | elif event.type == pg.KEYDOWN: 148 | if event.key == pg.K_SPACE: 149 | pass 150 | elif event.type == pg.VIDEORESIZE: 151 | MyGL.reshape(*event.size) 152 | MyGL.display() 153 | pg.display.flip() 154 | MyClock.tick(60) 155 | 156 | if __name__ == '__main__': 157 | main() 158 | pg.quit();sys.exit() -------------------------------------------------------------------------------- /06_objects_in_motion/06_Scale.py: -------------------------------------------------------------------------------- 1 | """Just using regular lists and tuples for the things taken care of using 2 | GLM in the original tutorial. Nothing here is complex enough to require resorting 3 | to numpy or another library yet.""" 4 | import sys,os,math 5 | import pygame as pg 6 | from OpenGL import GL 7 | 8 | sys.path.append("..") 9 | sys.path.append("data") 10 | import myframework 11 | from vertex_data import VERTICES,INDICES,NUMBER_OF_VERTICES 12 | 13 | class Shader(myframework.BaseShader): 14 | def __init__(self,vertices,vert_file,frag_file,indices=None): 15 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file,indices) 16 | GL.glEnable(GL.GL_CULL_FACE) 17 | GL.glCullFace(GL.GL_BACK) 18 | GL.glFrontFace(GL.GL_CW) 19 | 20 | GL.glEnable(GL.GL_DEPTH_TEST) 21 | GL.glDepthMask(GL.GL_TRUE) 22 | GL.glDepthFunc(GL.GL_LEQUAL) 23 | GL.glDepthRange(0.0,1.0) 24 | 25 | self.Objects = (NullScale((0.0,0.0,-45.0)), 26 | StaticUniformScale((-10.0,-10.0,-45.0)), 27 | StaticNonUniformScale((-10.0,10.0,-45.0)), 28 | DynamicUniformScale((10.0,10.0,-45.0)), 29 | DynamicNonUniformScale((10.0,-10.0,-45.0))) 30 | 31 | def init_vertex_buf(self): 32 | self.vbo = GL.glGenBuffers(1) 33 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 34 | ArrayType = GL.GLfloat*len(self.vertices) 35 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(self.vertices)*self.size_float, 36 | ArrayType(*self.vertices),GL.GL_STATIC_DRAW) 37 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 38 | 39 | self.ibo = GL.glGenBuffers(1) 40 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 41 | ArrayType = (GL.GLushort*len(self.indices)) 42 | GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,len(self.indices)*self.size_short, 43 | ArrayType(*self.indices),GL.GL_STATIC_DRAW) 44 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,0) 45 | 46 | def init_vao(self): 47 | self.vao = GL.glGenVertexArrays(1) 48 | GL.glBindVertexArray(self.vao) 49 | color_data_offset = 3*self.size_float*NUMBER_OF_VERTICES 50 | 51 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 52 | GL.glEnableVertexAttribArray(0) 53 | GL.glEnableVertexAttribArray(1) 54 | GL.glVertexAttribPointer(0,3,GL.GL_FLOAT,GL.GL_FALSE,0,None) 55 | GL.glVertexAttribPointer(1,4,GL.GL_FLOAT,GL.GL_FALSE,0,GL.GLvoidp(color_data_offset)) 56 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 57 | GL.glBindVertexArray(0) 58 | 59 | def setup_uniforms(self): 60 | self.model2cam_matrix_unif = GL.glGetUniformLocation(self.shader,"modelToCameraMatrix") 61 | self.cam2clip_matrix_unif = GL.glGetUniformLocation(self.shader,"cameraToClipMatrix") 62 | self.frustum_scale = self.calc_frust_scale(45.0) 63 | self.z_near,self.z_far = 1.0,61.0 64 | self.create_matrix() 65 | 66 | GL.glUseProgram(self.shader) 67 | GL.glUniformMatrix4fv(self.cam2clip_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 68 | GL.glUseProgram(0) 69 | 70 | def calc_frust_scale(self,angle): 71 | rads = math.radians(angle) 72 | return 1.0/math.tan(rads/2.0) 73 | 74 | def create_matrix(self): 75 | self.the_matrix = [0.0 for i in range(16)] 76 | self.the_matrix[0] = self.frustum_scale 77 | self.the_matrix[5] = self.frustum_scale 78 | self.the_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 79 | self.the_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 80 | self.the_matrix[11] = -1.0 81 | 82 | def display(self): 83 | GL.glClearColor(0,0,0,0) 84 | GL.glClearDepth(1.0) 85 | GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 86 | 87 | GL.glUseProgram(self.shader) 88 | GL.glBindVertexArray(self.vao) 89 | 90 | elapsed_time = pg.time.get_ticks()/1000.0 91 | for Obj in self.Objects: 92 | matrix = Obj.construct_matrix(elapsed_time) 93 | GL.glUniformMatrix4fv(self.model2cam_matrix_unif,1,GL.GL_FALSE,matrix) 94 | GL.glDrawElements(GL.GL_TRIANGLES,len(self.indices),GL.GL_UNSIGNED_SHORT,None) 95 | 96 | GL.glBindVertexArray(0) 97 | GL.glUseProgram(0) 98 | 99 | def reshape(self,width,height): 100 | self.the_matrix[0] = self.frustum_scale/(width/float(height)) 101 | self.the_matrix[5] = self.frustum_scale 102 | GL.glUseProgram(self.shader) 103 | GL.glUniformMatrix4fv(self.cam2clip_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 104 | GL.glUseProgram(0) 105 | GL.glViewport(0,0,width,height) 106 | 107 | class Generic: 108 | def __init__(self,offset): 109 | self.offset = offset 110 | def construct_matrix(self,time): 111 | mat = [[0.0 for i in range(4)] for j in range(4)] 112 | scale = self.calc_scale(time) 113 | for i in range(3): 114 | mat[i][i] = scale[i] 115 | mat[3] = self.offset+(1.0,) 116 | return mat 117 | def calc_lerp(self,time,period): 118 | value = time%period/period 119 | if value > 0.5: 120 | value = 1.0-value 121 | return value*2.0 122 | 123 | class NullScale(Generic): 124 | def calc_scale(self,time): 125 | return (1.0,1.0,1.0) 126 | class StaticUniformScale(Generic): 127 | def calc_scale(self,time): 128 | return (4.0,4.0,4.0) 129 | class StaticNonUniformScale(Generic): 130 | def calc_scale(self,time): 131 | return (0.5,1.0,10.0) 132 | class DynamicUniformScale(Generic): 133 | def calc_scale(self,time): 134 | period = 3.0 135 | lerp = self.calc_lerp(time,period) 136 | return (1+3*lerp,)*3 137 | class DynamicNonUniformScale(Generic): 138 | def calc_scale(self,time): 139 | period_x = 3.0 140 | period_z = 5.0 141 | lerp_x = self.calc_lerp(time,period_x) 142 | lerp_z = self.calc_lerp(time,period_z) 143 | return ((1-0.5*lerp_x),1.0,(1+9*lerp_z)) 144 | 145 | def main(): 146 | pg.init() 147 | os.environ['SDL_VIDEO_CENTERED'] = '1' 148 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 149 | MyClock = pg.time.Clock() 150 | MyGL = Shader(VERTICES[:],os.path.join("data","PosColorLocalTransform.vert"), 151 | os.path.join("data","ColorPassthrough.frag"),INDICES[:]) 152 | done = False 153 | while not done: 154 | for event in pg.event.get(): 155 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 156 | done = True 157 | elif event.type == pg.KEYDOWN: 158 | if event.key == pg.K_SPACE: 159 | pass 160 | elif event.type == pg.VIDEORESIZE: 161 | MyGL.reshape(*event.size) 162 | MyGL.display() 163 | pg.display.flip() 164 | MyClock.tick(60) 165 | 166 | if __name__ == '__main__': 167 | main() 168 | pg.quit();sys.exit() -------------------------------------------------------------------------------- /06_objects_in_motion/06_Rotations.py: -------------------------------------------------------------------------------- 1 | """I used Numpy arrays and functions in this tutorial. It is still pretty 2 | easy to get by without doing so if necessary however.""" 3 | import sys,os,math 4 | import pygame as pg,numpy as np 5 | from OpenGL import GL 6 | 7 | sys.path.append("..") 8 | sys.path.append("data") 9 | import myframework 10 | from vertex_data import VERTICES,INDICES,NUMBER_OF_VERTICES 11 | 12 | class Shader(myframework.BaseShader): 13 | def __init__(self,vertices,vert_file,frag_file,indices=None): 14 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file,indices) 15 | GL.glEnable(GL.GL_CULL_FACE) 16 | GL.glCullFace(GL.GL_BACK) 17 | GL.glFrontFace(GL.GL_CW) 18 | 19 | GL.glEnable(GL.GL_DEPTH_TEST) 20 | GL.glDepthMask(GL.GL_TRUE) 21 | GL.glDepthFunc(GL.GL_LEQUAL) 22 | GL.glDepthRange(0.0,1.0) 23 | 24 | self.Objects = (NullRotation((0.0,0.0,-10.0)), 25 | Rotate_X((-5.0,-5.0,-25.0)), 26 | Rotate_Y((-5.0,5.0,-25.0)), 27 | Rotate_Z((5.0,5.0,-25.0)), 28 | RotateAxis((5.0,-5.0,-25.0))) 29 | 30 | def init_vertex_buf(self): 31 | self.vbo = GL.glGenBuffers(1) 32 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 33 | ArrayType = GL.GLfloat*len(self.vertices) 34 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(self.vertices)*self.size_float, 35 | ArrayType(*self.vertices),GL.GL_STATIC_DRAW) 36 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 37 | 38 | self.ibo = GL.glGenBuffers(1) 39 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 40 | ArrayType = (GL.GLushort*len(self.indices)) 41 | GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,len(self.indices)*self.size_short, 42 | ArrayType(*self.indices),GL.GL_STATIC_DRAW) 43 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,0) 44 | 45 | def init_vao(self): 46 | self.vao = GL.glGenVertexArrays(1) 47 | GL.glBindVertexArray(self.vao) 48 | color_data_offset = 3*self.size_float*NUMBER_OF_VERTICES 49 | 50 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 51 | GL.glEnableVertexAttribArray(0) 52 | GL.glEnableVertexAttribArray(1) 53 | GL.glVertexAttribPointer(0,3,GL.GL_FLOAT,GL.GL_FALSE,0,None) 54 | GL.glVertexAttribPointer(1,4,GL.GL_FLOAT,GL.GL_FALSE,0,GL.GLvoidp(color_data_offset)) 55 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 56 | GL.glBindVertexArray(0) 57 | 58 | def setup_uniforms(self): 59 | self.model2cam_matrix_unif = GL.glGetUniformLocation(self.shader,"modelToCameraMatrix") 60 | self.cam2clip_matrix_unif = GL.glGetUniformLocation(self.shader,"cameraToClipMatrix") 61 | self.frustum_scale = self.calc_frust_scale(45.0) 62 | self.z_near,self.z_far = 1.0,61.0 63 | self.create_matrix() 64 | 65 | GL.glUseProgram(self.shader) 66 | GL.glUniformMatrix4fv(self.cam2clip_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 67 | GL.glUseProgram(0) 68 | 69 | def calc_frust_scale(self,angle): 70 | rads = math.radians(angle) 71 | return 1.0/math.tan(rads/2.0) 72 | 73 | def create_matrix(self): 74 | self.the_matrix = [0.0 for i in range(16)] 75 | self.the_matrix[0] = self.frustum_scale 76 | self.the_matrix[5] = self.frustum_scale 77 | self.the_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 78 | self.the_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 79 | self.the_matrix[11] = -1.0 80 | 81 | def display(self): 82 | GL.glClearColor(0,0,0,0) 83 | GL.glClearDepth(1.0) 84 | GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 85 | 86 | GL.glUseProgram(self.shader) 87 | GL.glBindVertexArray(self.vao) 88 | 89 | elapsed_time = pg.time.get_ticks()/1000.0 90 | for Obj in self.Objects: 91 | matrix = Obj.construct_matrix(elapsed_time) 92 | GL.glUniformMatrix4fv(self.model2cam_matrix_unif,1,GL.GL_FALSE,matrix) 93 | GL.glDrawElements(GL.GL_TRIANGLES,len(self.indices),GL.GL_UNSIGNED_SHORT,None) 94 | 95 | GL.glBindVertexArray(0) 96 | GL.glUseProgram(0) 97 | 98 | def reshape(self,width,height): 99 | self.the_matrix[0] = self.frustum_scale/(width/float(height)) 100 | self.the_matrix[5] = self.frustum_scale 101 | GL.glUseProgram(self.shader) 102 | GL.glUniformMatrix4fv(self.cam2clip_matrix_unif,1,GL.GL_FALSE,self.the_matrix) 103 | GL.glUseProgram(0) 104 | GL.glViewport(0,0,width,height) 105 | 106 | class Generic: 107 | def __init__(self,offset): 108 | self.offset = offset 109 | def construct_matrix(self,time): 110 | mat = np.identity(4,'f') 111 | mat = self.calc_rotation(mat,time) 112 | mat[3] = self.offset+(1.0,) 113 | return mat 114 | 115 | def get_rad_angle(self,time,period): 116 | angular_speed = 2*math.pi/period 117 | time_through_loop = time%period 118 | return time_through_loop*angular_speed 119 | 120 | class NullRotation(Generic): 121 | def calc_rotation(self,mat,time): 122 | return mat 123 | class Rotate_X(Generic): 124 | def calc_rotation(self,mat,time): 125 | rad_ang = self.get_rad_angle(time,3.0) 126 | mat[1][1] = math.cos(rad_ang) 127 | mat[1][2] = math.sin(rad_ang) 128 | mat[2][1] = -mat[1][2] 129 | mat[2][2] = mat[1][1] 130 | return mat 131 | class Rotate_Y(Generic): 132 | def calc_rotation(self,mat,time): 133 | rad_ang = self.get_rad_angle(time,2.0) 134 | mat[0][0] = math.cos(rad_ang) 135 | mat[0][2] = -math.sin(rad_ang) 136 | mat[2][0] = -mat[0][2] 137 | mat[2][2] = mat[0][0] 138 | return mat 139 | class Rotate_Z(Generic): 140 | def calc_rotation(self,mat,time): 141 | rad_ang = self.get_rad_angle(time,2.0) 142 | mat[0][0] = math.cos(rad_ang) 143 | mat[0][1] = math.sin(rad_ang) 144 | mat[1][0] = -mat[0][1] 145 | mat[1][1] = mat[0][0] 146 | return mat 147 | class RotateAxis(Generic): 148 | def calc_rotation(self,mat,time): 149 | rad_ang = self.get_rad_angle(time,2.0) 150 | cos = math.cos(rad_ang); icos = 1.0-cos 151 | sin = math.sin(rad_ang); isin = 1.0-sin 152 | rot_axis = np.array([1.0,1.0,1.0]) 153 | rot_axis /= np.linalg.norm(rot_axis) 154 | 155 | mat[0][0] = (rot_axis[0]**2) + ((1-rot_axis[0]**2)*cos) 156 | mat[1][0] = (rot_axis[0]*rot_axis[1]*icos) - (rot_axis[2]*sin) 157 | mat[2][0] = (rot_axis[0]*rot_axis[2]*icos) + (rot_axis[1]*sin) 158 | 159 | mat[0][1] = (rot_axis[0]*rot_axis[1]*icos) + (rot_axis[2]*sin) 160 | mat[1][1] = (rot_axis[1]**2) + ((1-rot_axis[1]**2)*cos) 161 | mat[2][1] = (rot_axis[1]*rot_axis[2]*icos) - (rot_axis[0]*sin) 162 | 163 | mat[0][2] = (rot_axis[0]*rot_axis[2]*icos) - (rot_axis[1]*sin) 164 | mat[1][2] = (rot_axis[1]*rot_axis[2]*icos) + (rot_axis[0]*sin) 165 | mat[2][2] = (rot_axis[2]**2) + ((1-rot_axis[2]**2)*cos) 166 | return mat 167 | 168 | def main(): 169 | pg.init() 170 | os.environ['SDL_VIDEO_CENTERED'] = '1' 171 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 172 | MyClock = pg.time.Clock() 173 | MyGL = Shader(VERTICES[:],os.path.join("data","PosColorLocalTransform.vert"), 174 | os.path.join("data","ColorPassthrough.frag"),INDICES[:]) 175 | done = False 176 | while not done: 177 | for event in pg.event.get(): 178 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 179 | done = True 180 | elif event.type == pg.KEYDOWN: 181 | if event.key == pg.K_SPACE: 182 | pass 183 | elif event.type == pg.VIDEORESIZE: 184 | MyGL.reshape(*event.size) 185 | MyGL.display() 186 | pg.display.flip() 187 | MyClock.tick(60) 188 | 189 | if __name__ == '__main__': 190 | main() 191 | pg.quit();sys.exit() -------------------------------------------------------------------------------- /06_objects_in_motion/06_Hierarchy.py: -------------------------------------------------------------------------------- 1 | """I fought a while trying to get this one to work. Firstly I thought that * 2 | did matrix multiplication when using numpy arrays; it doesn't (you need to use 3 | numpy.dot instead). Then I had a series of issues which ended up being a result 4 | of the tutorial using the column-major convention, and numpy arrays using the 5 | row-major convention. The solution to this was to do matrix multiplications 6 | in the oposite order indictated in the original. Anyway, the final product is 7 | quite amusing and I'm glad I got it to work. 8 | 9 | This program is interactive. The controls are: 10 | Base Spin : A/D 11 | Arm Raise/Lower : W/S 12 | Elbow Raise/Lower : R/F 13 | Wrist Raise/Lower : T/G 14 | Wrist Spin : Z/C 15 | Finger Open/Close : Q/E 16 | Space-Bar : Print the current state of the armature.""" 17 | 18 | import sys,os,math 19 | import pygame as pg,numpy as np 20 | from OpenGL import GL 21 | 22 | sys.path.append("..") 23 | sys.path.append("data") 24 | import myframework 25 | from hierarchy_data import VERTICES,INDICES,NUMBER_OF_VERTICES 26 | 27 | class Shader(myframework.BaseShader): 28 | def __init__(self,vertices,vert_file,frag_file,indices=None): 29 | myframework.BaseShader.__init__(self,vertices,vert_file,frag_file,indices) 30 | GL.glEnable(GL.GL_CULL_FACE) 31 | GL.glCullFace(GL.GL_BACK) 32 | GL.glFrontFace(GL.GL_CW) 33 | 34 | GL.glEnable(GL.GL_DEPTH_TEST) 35 | GL.glDepthMask(GL.GL_TRUE) 36 | GL.glDepthFunc(GL.GL_LEQUAL) 37 | GL.glDepthRange(0.0,1.0) 38 | 39 | self.Armature = Hierarchy() 40 | 41 | def init_vertex_buf(self): 42 | self.vbo = GL.glGenBuffers(1) 43 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 44 | ArrayType = GL.GLfloat*len(self.vertices) 45 | GL.glBufferData(GL.GL_ARRAY_BUFFER,len(self.vertices)*self.size_float, 46 | ArrayType(*self.vertices),GL.GL_STATIC_DRAW) 47 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,0) 48 | 49 | self.ibo = GL.glGenBuffers(1) 50 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 51 | ArrayType = (GL.GLushort*len(self.indices)) 52 | GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER,len(self.indices)*self.size_short, 53 | ArrayType(*self.indices),GL.GL_STATIC_DRAW) 54 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,0) 55 | 56 | def init_vao(self): 57 | self.vao = GL.glGenVertexArrays(1) 58 | GL.glBindVertexArray(self.vao) 59 | color_data_offset = 3*self.size_float*NUMBER_OF_VERTICES 60 | 61 | GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo) 62 | GL.glEnableVertexAttribArray(self.pos_attrib) 63 | GL.glEnableVertexAttribArray(self.col_attrib) 64 | GL.glVertexAttribPointer(self.pos_attrib,3,GL.GL_FLOAT,GL.GL_FALSE,0,None) 65 | GL.glVertexAttribPointer(self.col_attrib,4,GL.GL_FLOAT,GL.GL_FALSE,0,GL.GLvoidp(color_data_offset)) 66 | GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.ibo) 67 | GL.glBindVertexArray(0) 68 | 69 | def setup_attributes(self): 70 | self.pos_attrib = GL.glGetAttribLocation(self.shader,"position") 71 | self.col_attrib = GL.glGetAttribLocation(self.shader,"color") 72 | def setup_uniforms(self): 73 | self.model2cam_matrix_unif = GL.glGetUniformLocation(self.shader,"modelToCameraMatrix") 74 | self.cam2clip_matrix_unif = GL.glGetUniformLocation(self.shader,"cameraToClipMatrix") 75 | self.frustum_scale = self.calc_frust_scale(45.0) 76 | self.z_near,self.z_far = 1.0,100.0 77 | self.create_matrix() 78 | 79 | GL.glUseProgram(self.shader) 80 | GL.glUniformMatrix4fv(self.cam2clip_matrix_unif,1,GL.GL_FALSE,self.persp_matrix) 81 | GL.glUseProgram(0) 82 | 83 | def calc_frust_scale(self,angle): 84 | rads = math.radians(angle) 85 | return 1.0/math.tan(rads/2.0) 86 | 87 | def create_matrix(self): 88 | self.persp_matrix = [0.0 for i in range(16)] 89 | self.persp_matrix[0] = self.frustum_scale 90 | self.persp_matrix[5] = self.frustum_scale 91 | self.persp_matrix[10] = (self.z_far+self.z_near)/(self.z_near-self.z_far) 92 | self.persp_matrix[14] = (2*self.z_far*self.z_near)/(self.z_near-self.z_far) 93 | self.persp_matrix[11] = -1.0 94 | 95 | def display(self): 96 | GL.glClearColor(0,0,0,0) 97 | GL.glClearDepth(1.0) 98 | GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 99 | self.Armature.draw(self) 100 | 101 | def reshape(self,width,height): 102 | self.persp_matrix[0] = self.frustum_scale/(width/float(height)) 103 | self.persp_matrix[5] = self.frustum_scale 104 | GL.glUseProgram(self.shader) 105 | GL.glUniformMatrix4fv(self.cam2clip_matrix_unif,1,GL.GL_FALSE,self.persp_matrix) 106 | GL.glUseProgram(0) 107 | GL.glViewport(0,0,width,height) 108 | 109 | class MatrixStack: 110 | def __init__(self): 111 | self.current_matrix = np.identity(4,'f') 112 | self.matrices = [] 113 | def rotate_X(self,ang): 114 | rad_ang = math.radians(ang) 115 | mat = np.identity(4,'f') 116 | mat[1][1] = math.cos(rad_ang) 117 | mat[1][2] = math.sin(rad_ang) 118 | mat[2][1] = -mat[1][2] 119 | mat[2][2] = mat[1][1] 120 | self.current_matrix = np.dot(mat,self.current_matrix) 121 | def rotate_Y(self,ang): 122 | rad_ang = math.radians(ang) 123 | mat = np.identity(4,'f') 124 | mat[0][0] = math.cos(rad_ang) 125 | mat[0][2] = -math.sin(rad_ang) 126 | mat[2][0] = -mat[0][2] 127 | mat[2][2] = mat[0][0] 128 | self.current_matrix = np.dot(mat,self.current_matrix) 129 | def rotate_Z(self,ang): 130 | rad_ang = math.radians(ang) 131 | mat = np.identity(4,'f') 132 | mat[0][0] = math.cos(rad_ang) 133 | mat[0][1] = math.sin(rad_ang) 134 | mat[1][0] = -mat[0][1] 135 | mat[1][1] = mat[0][0] 136 | self.current_matrix = np.dot(mat,self.current_matrix) 137 | def scale(self,scale_vec): 138 | scale_mat = np.identity(4,'f') 139 | for i in range(3): 140 | scale_mat[i][i] = scale_vec[i] 141 | self.current_matrix = np.dot(scale_mat,self.current_matrix) 142 | def translate(self,offset): 143 | translate_mat = np.identity(4,'f') 144 | translate_mat[3] = offset+(1.0,) 145 | self.current_matrix = np.dot(translate_mat,self.current_matrix) 146 | 147 | def push(self): 148 | self.matrices.append(self.current_matrix[:]) 149 | def pop(self): 150 | self.current_matrix = self.matrices.pop() 151 | 152 | class Hierarchy: 153 | def __init__(self): 154 | self.make_part_dict() 155 | self.Stack = None 156 | self.STAND_ANG_INC = 2.0 157 | def make_part_dict(self): 158 | self.base = {"pos" : (3.0,-5.0,-40.0), 159 | "ang" : -45.0, 160 | "pos_L" : (2.0,0.0,0.0), 161 | "pos_R" : (-2.0,0.0,0.0), 162 | "scale_Z": 3.0} 163 | self.arm = {"up_ang" : -33.75, 164 | "up_size" : 9.0, 165 | "low_pos" : (0.0,0.0,8.0), 166 | "low_ang" : 146.25, 167 | "low_len" : 5.0, 168 | "low_width": 1.5} 169 | self.wrist = {"pos" : (0.0,0.0,5.0), 170 | "roll_ang" : 0.0, 171 | "pitch_ang": 67.5, 172 | "len" : 2.0, 173 | "width" : 2.0} 174 | self.finger = {"pos_L" : (1.0, 0.0, 1.0), 175 | "pos_R" : (-1.0,0.0,1.0), 176 | "open_ang": 180.0, 177 | "len" : 2.0, 178 | "width" : 0.5, 179 | "low_ang" : 45.0} 180 | 181 | def draw(self,Shader): 182 | self.Stack = MatrixStack() 183 | GL.glUseProgram(Shader.shader) 184 | GL.glBindVertexArray(Shader.vao) 185 | 186 | self.Stack.translate(self.base["pos"]) 187 | self.Stack.rotate_Y(self.base["ang"]) 188 | self.draw_base(Shader) 189 | self.draw_arm(Shader) 190 | 191 | GL.glBindVertexArray(0) 192 | GL.glUseProgram(0) 193 | 194 | def draw_and_pop(self,Shader): 195 | GL.glUniformMatrix4fv(Shader.model2cam_matrix_unif,1,GL.GL_FALSE,self.Stack.current_matrix) 196 | GL.glDrawElements(GL.GL_TRIANGLES,len(Shader.indices),GL.GL_UNSIGNED_SHORT,None) 197 | self.Stack.pop() 198 | 199 | def draw_base(self,Shader): 200 | for part in ("pos_L","pos_R"): 201 | self.Stack.push() 202 | self.Stack.translate(self.base[part]) 203 | self.Stack.scale((1.0,1.0,self.base["scale_Z"])) 204 | self.draw_and_pop(Shader) 205 | def draw_arm(self,Shader): 206 | self.draw_up_arm(Shader) 207 | 208 | def draw_fingers(self,Shader): 209 | for pos,angle in (("pos_L",1),("pos_R",-1)): 210 | self.Stack.push() 211 | self.Stack.translate(self.finger[pos]) 212 | self.Stack.rotate_Y(self.finger["open_ang"]*angle) 213 | 214 | self.Stack.push() 215 | self.Stack.translate((0.0,0.0,self.finger["len"]/2.0)) 216 | self.Stack.scale((self.finger["width"]/2.0,self.finger["width"]/2.0,self.finger["len"]/2.0)) 217 | self.draw_and_pop(Shader) 218 | self.draw_low_finger(Shader,angle) 219 | 220 | self.Stack.pop();self.Stack.pop() 221 | 222 | def draw_low_finger(self,Shader,angle): 223 | self.Stack.push() 224 | self.Stack.translate((0.0,0.0,self.finger["len"])) 225 | self.Stack.rotate_Y(-self.finger["low_ang"]*angle) 226 | 227 | self.Stack.push() 228 | self.Stack.translate((0.0,0.0,self.finger["len"]/2.0)) 229 | self.Stack.scale((self.finger["width"]/2.0,self.finger["width"]/2.0,self.finger["len"]/2.0)) 230 | self.draw_and_pop(Shader) 231 | 232 | def draw_wrist(self,Shader): 233 | self.Stack.push() 234 | self.Stack.translate(self.wrist["pos"]) 235 | self.Stack.rotate_Z(self.wrist["roll_ang"]) 236 | self.Stack.rotate_X(self.wrist["pitch_ang"]) 237 | 238 | self.Stack.push() 239 | self.Stack.scale((self.wrist["width"]/2.0,self.wrist["width"]/2.0,self.wrist["len"]/2.0)) 240 | self.draw_and_pop(Shader) 241 | 242 | self.draw_fingers(Shader) 243 | self.Stack.pop() 244 | 245 | def draw_low_arm(self,Shader): 246 | self.Stack.push() 247 | self.Stack.translate(self.arm["low_pos"]) 248 | self.Stack.rotate_X(self.arm["low_ang"]) 249 | 250 | self.Stack.push() 251 | self.Stack.translate((0.0,0.0,self.arm["low_len"]/2.0)) 252 | self.Stack.scale((self.arm["low_width"]/2.0,self.arm["low_width"]/2.0,self.arm["low_len"]/2.0)) 253 | self.draw_and_pop(Shader) 254 | 255 | self.draw_wrist(Shader) 256 | self.Stack.pop() 257 | 258 | def draw_up_arm(self,Shader): 259 | self.Stack.push() 260 | self.Stack.rotate_X(self.arm["up_ang"]) 261 | 262 | self.Stack.push() 263 | self.Stack.translate((0.0,0.0,(self.arm["up_size"]/2.0)-1.0)) 264 | self.Stack.scale((1.0,1.0,self.arm["up_size"]/2.0)) 265 | self.draw_and_pop(Shader) 266 | 267 | self.draw_low_arm(Shader) 268 | self.Stack.pop() 269 | 270 | def clamp(self,value,low,high): 271 | return max(low,min(high,value)) 272 | 273 | def adj_ang(self,pos,attrib,feat,clamp=None): 274 | value = getattr(self,attrib)[feat] 275 | value += (self.STAND_ANG_INC if pos else -self.STAND_ANG_INC) 276 | if clamp: 277 | getattr(self,attrib)[feat] = self.clamp(value,*clamp) 278 | else: 279 | getattr(self,attrib)[feat] = value%360.0 280 | 281 | def print_state(self): 282 | print("{:<17} : {}".format("Base Angle",self.base["ang"])) 283 | print("{:<17} : {}".format("Upper-Arm Angle",self.arm["up_ang"])) 284 | print("{:<17} : {}".format("Lower-Arm Angle",self.arm["low_ang"])) 285 | print("{:<17} : {}".format("Wrist Pitch Angle",self.wrist["pitch_ang"])) 286 | print("{:<17} : {}".format("Wrist Roll Angle",self.wrist["roll_ang"])) 287 | print("{:<17} : {}\n".format("Finger Open Angle",self.finger["open_ang"])) 288 | 289 | def main(): 290 | pg.init() 291 | os.environ['SDL_VIDEO_CENTERED'] = '1' 292 | SCREEN = pg.display.set_mode((500,500),pg.HWSURFACE|pg.OPENGL|pg.DOUBLEBUF|pg.RESIZABLE) 293 | MyClock = pg.time.Clock() 294 | MyGL = Shader(VERTICES[:],os.path.join("data","PosColorLocalTransform.vert"), 295 | os.path.join("data","ColorPassthrough.frag"),INDICES[:]) 296 | 297 | KEY_DICT = {(pg.K_d,pg.K_a) : ("base","ang"), 298 | (pg.K_w,pg.K_s) : ("arm","up_ang",(-90.0,0)), 299 | (pg.K_r,pg.K_f) : ("arm","low_ang",(0.0,146.25)), 300 | (pg.K_t,pg.K_g) : ("wrist","pitch_ang",(0.0,90.0)), 301 | (pg.K_c,pg.K_z) : ("wrist","roll_ang"), 302 | (pg.K_e,pg.K_q) : ("finger","open_ang",(9.0,180.0))} 303 | 304 | done = False 305 | while not done: 306 | keys = pg.key.get_pressed() 307 | for event in pg.event.get(): 308 | if event.type==pg.QUIT or (event.type==pg.KEYDOWN and event.key==pg.K_ESCAPE): 309 | done = True 310 | elif event.type == pg.KEYDOWN: 311 | if event.key == pg.K_SPACE: 312 | MyGL.Armature.print_state() 313 | elif event.type == pg.VIDEORESIZE: 314 | MyGL.reshape(*event.size) 315 | for pair in KEY_DICT: 316 | for i,key in enumerate(pair): 317 | if keys[key]: 318 | MyGL.Armature.adj_ang(i,*KEY_DICT[pair]) 319 | MyGL.display() 320 | pg.display.flip() 321 | MyClock.tick(60) 322 | 323 | if __name__ == '__main__': 324 | main() 325 | pg.quit();sys.exit() --------------------------------------------------------------------------------