├── .gitignore ├── CocoaOpenGL-Swift.png ├── CocoaOpenGL-Swift.xcodeproj └── project.pbxproj ├── Common ├── Cylinder.swift ├── Matrix4.swift ├── Renderable.swift ├── Scene.swift ├── ShaderProgram.swift ├── Texture.swift └── normalmap.png ├── LICENSE ├── README.md ├── iOS ├── AppDelegate.swift ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── LaunchScreen.storyboard ├── Main.storyboard ├── MyGLKViewController.swift ├── shader.fs └── shader.vs ├── macOS ├── AppDelegate.swift ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── MainMenu.xib ├── MyNSOpenGLView.swift ├── shader.fs └── shader.vs └── tvOS ├── Assets.xcassets ├── App Icon & Top Shelf Image.brandassets │ ├── App Icon - App Store.imagestack │ │ ├── Back.imagestacklayer │ │ │ ├── Content.imageset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Front.imagestacklayer │ │ │ ├── Content.imageset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ └── Middle.imagestacklayer │ │ │ ├── Content.imageset │ │ │ └── Contents.json │ │ │ └── Contents.json │ ├── App Icon.imagestack │ │ ├── Back.imagestacklayer │ │ │ ├── Content.imageset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── Front.imagestacklayer │ │ │ ├── Content.imageset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ └── Middle.imagestacklayer │ │ │ ├── Content.imageset │ │ │ └── Contents.json │ │ │ └── Contents.json │ ├── Contents.json │ ├── Top Shelf Image Wide.imageset │ │ └── Contents.json │ └── Top Shelf Image.imageset │ │ └── Contents.json ├── Contents.json └── LaunchImage.launchimage │ └── Contents.json ├── Base.lproj └── Main.storyboard └── Info.plist /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .DS_Store 3 | project.xcworkspace 4 | xcuserdata 5 | CocoaOpenGL-Swift.app 6 | -------------------------------------------------------------------------------- /CocoaOpenGL-Swift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshb/CocoaOpenGL-Swift/3bf42fcb09d046613b3d2428fbf2a9eb1daf5fe4/CocoaOpenGL-Swift.png -------------------------------------------------------------------------------- /CocoaOpenGL-Swift.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0D64549E1F814EBD007C0286 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0D64549C1F814EBD007C0286 /* Main.storyboard */; }; 11 | 0D6454A01F814EBD007C0286 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0D64549F1F814EBD007C0286 /* Assets.xcassets */; }; 12 | 0D6454A51F814FC6007C0286 /* Cylinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE685881E4FD3CC0089BF2F /* Cylinder.swift */; }; 13 | 0D6454A61F814FC6007C0286 /* Matrix4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE685891E4FD3CC0089BF2F /* Matrix4.swift */; }; 14 | 0D6454A71F814FC6007C0286 /* Renderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6858B1E4FD3CC0089BF2F /* Renderable.swift */; }; 15 | 0D6454A81F814FC6007C0286 /* Scene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6858C1E4FD3CC0089BF2F /* Scene.swift */; }; 16 | 0D6454A91F814FC6007C0286 /* ShaderProgram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6858D1E4FD3CC0089BF2F /* ShaderProgram.swift */; }; 17 | 0D6454AA1F814FC6007C0286 /* Texture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6858E1E4FD3CC0089BF2F /* Texture.swift */; }; 18 | 0D6454AB1F814FC6007C0286 /* MyGLKViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6859B1E4FD3E10089BF2F /* MyGLKViewController.swift */; }; 19 | 0D6454AD1F816FCB007C0286 /* shader.fs in Resources */ = {isa = PBXBuildFile; fileRef = 0DE6859C1E4FD3E10089BF2F /* shader.fs */; }; 20 | 0D6454AE1F816FCB007C0286 /* shader.vs in Resources */ = {isa = PBXBuildFile; fileRef = 0DE6859D1E4FD3E10089BF2F /* shader.vs */; }; 21 | 0D6454AF1F816FE0007C0286 /* normalmap.png in Resources */ = {isa = PBXBuildFile; fileRef = 0DE6858A1E4FD3CC0089BF2F /* normalmap.png */; }; 22 | 0D6454B01F817014007C0286 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE685961E4FD3E10089BF2F /* AppDelegate.swift */; }; 23 | 0DE6858F1E4FD3CC0089BF2F /* Cylinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE685881E4FD3CC0089BF2F /* Cylinder.swift */; }; 24 | 0DE685901E4FD3CC0089BF2F /* Matrix4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE685891E4FD3CC0089BF2F /* Matrix4.swift */; }; 25 | 0DE685911E4FD3CC0089BF2F /* normalmap.png in Resources */ = {isa = PBXBuildFile; fileRef = 0DE6858A1E4FD3CC0089BF2F /* normalmap.png */; }; 26 | 0DE685921E4FD3CC0089BF2F /* Renderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6858B1E4FD3CC0089BF2F /* Renderable.swift */; }; 27 | 0DE685931E4FD3CC0089BF2F /* Scene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6858C1E4FD3CC0089BF2F /* Scene.swift */; }; 28 | 0DE685941E4FD3CC0089BF2F /* ShaderProgram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6858D1E4FD3CC0089BF2F /* ShaderProgram.swift */; }; 29 | 0DE685951E4FD3CC0089BF2F /* Texture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6858E1E4FD3CC0089BF2F /* Texture.swift */; }; 30 | 0DE685AD1E4FD3EF0089BF2F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE685A61E4FD3EF0089BF2F /* AppDelegate.swift */; }; 31 | 0DE685AE1E4FD3EF0089BF2F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0DE685A71E4FD3EF0089BF2F /* Images.xcassets */; }; 32 | 0DE685B01E4FD3EF0089BF2F /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0DE685A91E4FD3EF0089BF2F /* MainMenu.xib */; }; 33 | 0DE685B11E4FD3EF0089BF2F /* MyNSOpenGLView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE685AA1E4FD3EF0089BF2F /* MyNSOpenGLView.swift */; }; 34 | 0DE685B21E4FD3EF0089BF2F /* shader.fs in Resources */ = {isa = PBXBuildFile; fileRef = 0DE685AB1E4FD3EF0089BF2F /* shader.fs */; }; 35 | 0DE685B31E4FD3EF0089BF2F /* shader.vs in Resources */ = {isa = PBXBuildFile; fileRef = 0DE685AC1E4FD3EF0089BF2F /* shader.vs */; }; 36 | 0DE685CE1E4FD5400089BF2F /* Cylinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE685881E4FD3CC0089BF2F /* Cylinder.swift */; }; 37 | 0DE685CF1E4FD5400089BF2F /* Matrix4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE685891E4FD3CC0089BF2F /* Matrix4.swift */; }; 38 | 0DE685D01E4FD5400089BF2F /* Renderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6858B1E4FD3CC0089BF2F /* Renderable.swift */; }; 39 | 0DE685D11E4FD5400089BF2F /* Scene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6858C1E4FD3CC0089BF2F /* Scene.swift */; }; 40 | 0DE685D21E4FD5400089BF2F /* ShaderProgram.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6858D1E4FD3CC0089BF2F /* ShaderProgram.swift */; }; 41 | 0DE685D31E4FD5400089BF2F /* Texture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6858E1E4FD3CC0089BF2F /* Texture.swift */; }; 42 | 0DE685D41E4FD5400089BF2F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE685961E4FD3E10089BF2F /* AppDelegate.swift */; }; 43 | 0DE685D51E4FD5400089BF2F /* MyGLKViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE6859B1E4FD3E10089BF2F /* MyGLKViewController.swift */; }; 44 | 0DE685D61E4FD54C0089BF2F /* normalmap.png in Resources */ = {isa = PBXBuildFile; fileRef = 0DE6858A1E4FD3CC0089BF2F /* normalmap.png */; }; 45 | 0DE685D71E4FD54C0089BF2F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0DE685971E4FD3E10089BF2F /* Assets.xcassets */; }; 46 | 0DE685D81E4FD54C0089BF2F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0DE685991E4FD3E10089BF2F /* LaunchScreen.storyboard */; }; 47 | 0DE685D91E4FD54C0089BF2F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0DE6859A1E4FD3E10089BF2F /* Main.storyboard */; }; 48 | 0DE685DA1E4FD54C0089BF2F /* shader.fs in Resources */ = {isa = PBXBuildFile; fileRef = 0DE6859C1E4FD3E10089BF2F /* shader.fs */; }; 49 | 0DE685DB1E4FD54C0089BF2F /* shader.vs in Resources */ = {isa = PBXBuildFile; fileRef = 0DE6859D1E4FD3E10089BF2F /* shader.vs */; }; 50 | /* End PBXBuildFile section */ 51 | 52 | /* Begin PBXFileReference section */ 53 | 0D6454961F814EBD007C0286 /* CocoaOpenGL-Swift-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "CocoaOpenGL-Swift-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 0D64549D1F814EBD007C0286 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 55 | 0D64549F1F814EBD007C0286 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 56 | 0D6454A11F814EBD007C0286 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 0D9AFA3A1F74BCA400CA5FF4 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 58 | 0DE685721E4FD31E0089BF2F /* CocoaOpenGL-Swift-macOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "CocoaOpenGL-Swift-macOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | 0DE685881E4FD3CC0089BF2F /* Cylinder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cylinder.swift; sourceTree = ""; }; 60 | 0DE685891E4FD3CC0089BF2F /* Matrix4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Matrix4.swift; sourceTree = ""; }; 61 | 0DE6858A1E4FD3CC0089BF2F /* normalmap.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = normalmap.png; sourceTree = ""; }; 62 | 0DE6858B1E4FD3CC0089BF2F /* Renderable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Renderable.swift; sourceTree = ""; }; 63 | 0DE6858C1E4FD3CC0089BF2F /* Scene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scene.swift; sourceTree = ""; }; 64 | 0DE6858D1E4FD3CC0089BF2F /* ShaderProgram.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShaderProgram.swift; sourceTree = ""; }; 65 | 0DE6858E1E4FD3CC0089BF2F /* Texture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Texture.swift; sourceTree = ""; }; 66 | 0DE685961E4FD3E10089BF2F /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 67 | 0DE685971E4FD3E10089BF2F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 68 | 0DE685981E4FD3E10089BF2F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 69 | 0DE685991E4FD3E10089BF2F /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 70 | 0DE6859A1E4FD3E10089BF2F /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; 71 | 0DE6859B1E4FD3E10089BF2F /* MyGLKViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyGLKViewController.swift; sourceTree = ""; }; 72 | 0DE6859C1E4FD3E10089BF2F /* shader.fs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = shader.fs; sourceTree = ""; }; 73 | 0DE6859D1E4FD3E10089BF2F /* shader.vs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = shader.vs; sourceTree = ""; }; 74 | 0DE685A61E4FD3EF0089BF2F /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 75 | 0DE685A71E4FD3EF0089BF2F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 76 | 0DE685A81E4FD3EF0089BF2F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 77 | 0DE685A91E4FD3EF0089BF2F /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; 78 | 0DE685AA1E4FD3EF0089BF2F /* MyNSOpenGLView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyNSOpenGLView.swift; sourceTree = ""; }; 79 | 0DE685AB1E4FD3EF0089BF2F /* shader.fs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = shader.fs; sourceTree = ""; }; 80 | 0DE685AC1E4FD3EF0089BF2F /* shader.vs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = shader.vs; sourceTree = ""; }; 81 | 0DE685B81E4FD4BC0089BF2F /* CocoaOpenGL-Swift-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "CocoaOpenGL-Swift-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 82 | /* End PBXFileReference section */ 83 | 84 | /* Begin PBXFrameworksBuildPhase section */ 85 | 0D6454931F814EBD007C0286 /* Frameworks */ = { 86 | isa = PBXFrameworksBuildPhase; 87 | buildActionMask = 2147483647; 88 | files = ( 89 | ); 90 | runOnlyForDeploymentPostprocessing = 0; 91 | }; 92 | 0DE6856F1E4FD31E0089BF2F /* Frameworks */ = { 93 | isa = PBXFrameworksBuildPhase; 94 | buildActionMask = 2147483647; 95 | files = ( 96 | ); 97 | runOnlyForDeploymentPostprocessing = 0; 98 | }; 99 | 0DE685B51E4FD4BC0089BF2F /* Frameworks */ = { 100 | isa = PBXFrameworksBuildPhase; 101 | buildActionMask = 2147483647; 102 | files = ( 103 | ); 104 | runOnlyForDeploymentPostprocessing = 0; 105 | }; 106 | /* End PBXFrameworksBuildPhase section */ 107 | 108 | /* Begin PBXGroup section */ 109 | 0D6454971F814EBD007C0286 /* tvOS */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 0D64549C1F814EBD007C0286 /* Main.storyboard */, 113 | 0D64549F1F814EBD007C0286 /* Assets.xcassets */, 114 | 0D6454A11F814EBD007C0286 /* Info.plist */, 115 | ); 116 | path = tvOS; 117 | sourceTree = ""; 118 | }; 119 | 0DE685631E4FD28A0089BF2F = { 120 | isa = PBXGroup; 121 | children = ( 122 | 0D9AFA3A1F74BCA400CA5FF4 /* README.md */, 123 | 0DE685851E4FD3A20089BF2F /* Common */, 124 | 0DE685861E4FD3A70089BF2F /* iOS */, 125 | 0DE685871E4FD3B00089BF2F /* macOS */, 126 | 0D6454971F814EBD007C0286 /* tvOS */, 127 | 0DE685731E4FD31E0089BF2F /* Products */, 128 | ); 129 | sourceTree = ""; 130 | }; 131 | 0DE685731E4FD31E0089BF2F /* Products */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 0DE685721E4FD31E0089BF2F /* CocoaOpenGL-Swift-macOS.app */, 135 | 0DE685B81E4FD4BC0089BF2F /* CocoaOpenGL-Swift-iOS.app */, 136 | 0D6454961F814EBD007C0286 /* CocoaOpenGL-Swift-tvOS.app */, 137 | ); 138 | name = Products; 139 | sourceTree = ""; 140 | }; 141 | 0DE685851E4FD3A20089BF2F /* Common */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 0DE685881E4FD3CC0089BF2F /* Cylinder.swift */, 145 | 0DE685891E4FD3CC0089BF2F /* Matrix4.swift */, 146 | 0DE6858A1E4FD3CC0089BF2F /* normalmap.png */, 147 | 0DE6858B1E4FD3CC0089BF2F /* Renderable.swift */, 148 | 0DE6858C1E4FD3CC0089BF2F /* Scene.swift */, 149 | 0DE6858D1E4FD3CC0089BF2F /* ShaderProgram.swift */, 150 | 0DE6858E1E4FD3CC0089BF2F /* Texture.swift */, 151 | ); 152 | path = Common; 153 | sourceTree = ""; 154 | }; 155 | 0DE685861E4FD3A70089BF2F /* iOS */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 0DE685961E4FD3E10089BF2F /* AppDelegate.swift */, 159 | 0DE685971E4FD3E10089BF2F /* Assets.xcassets */, 160 | 0DE685981E4FD3E10089BF2F /* Info.plist */, 161 | 0DE685991E4FD3E10089BF2F /* LaunchScreen.storyboard */, 162 | 0DE6859A1E4FD3E10089BF2F /* Main.storyboard */, 163 | 0DE6859B1E4FD3E10089BF2F /* MyGLKViewController.swift */, 164 | 0DE6859C1E4FD3E10089BF2F /* shader.fs */, 165 | 0DE6859D1E4FD3E10089BF2F /* shader.vs */, 166 | ); 167 | path = iOS; 168 | sourceTree = ""; 169 | }; 170 | 0DE685871E4FD3B00089BF2F /* macOS */ = { 171 | isa = PBXGroup; 172 | children = ( 173 | 0DE685A61E4FD3EF0089BF2F /* AppDelegate.swift */, 174 | 0DE685A71E4FD3EF0089BF2F /* Images.xcassets */, 175 | 0DE685A81E4FD3EF0089BF2F /* Info.plist */, 176 | 0DE685A91E4FD3EF0089BF2F /* MainMenu.xib */, 177 | 0DE685AA1E4FD3EF0089BF2F /* MyNSOpenGLView.swift */, 178 | 0DE685AB1E4FD3EF0089BF2F /* shader.fs */, 179 | 0DE685AC1E4FD3EF0089BF2F /* shader.vs */, 180 | ); 181 | path = macOS; 182 | sourceTree = ""; 183 | }; 184 | /* End PBXGroup section */ 185 | 186 | /* Begin PBXNativeTarget section */ 187 | 0D6454951F814EBD007C0286 /* CocoaOpenGL-Swift-tvOS */ = { 188 | isa = PBXNativeTarget; 189 | buildConfigurationList = 0D6454A41F814EBD007C0286 /* Build configuration list for PBXNativeTarget "CocoaOpenGL-Swift-tvOS" */; 190 | buildPhases = ( 191 | 0D6454921F814EBD007C0286 /* Sources */, 192 | 0D6454931F814EBD007C0286 /* Frameworks */, 193 | 0D6454941F814EBD007C0286 /* Resources */, 194 | ); 195 | buildRules = ( 196 | ); 197 | dependencies = ( 198 | ); 199 | name = "CocoaOpenGL-Swift-tvOS"; 200 | productName = "CocoaOpenGL-Swift-tvOS"; 201 | productReference = 0D6454961F814EBD007C0286 /* CocoaOpenGL-Swift-tvOS.app */; 202 | productType = "com.apple.product-type.application"; 203 | }; 204 | 0DE685711E4FD31E0089BF2F /* CocoaOpenGL-Swift-macOS */ = { 205 | isa = PBXNativeTarget; 206 | buildConfigurationList = 0DE6857D1E4FD31E0089BF2F /* Build configuration list for PBXNativeTarget "CocoaOpenGL-Swift-macOS" */; 207 | buildPhases = ( 208 | 0DE6856E1E4FD31E0089BF2F /* Sources */, 209 | 0DE6856F1E4FD31E0089BF2F /* Frameworks */, 210 | 0DE685701E4FD31E0089BF2F /* Resources */, 211 | ); 212 | buildRules = ( 213 | ); 214 | dependencies = ( 215 | ); 216 | name = "CocoaOpenGL-Swift-macOS"; 217 | productName = "CocoaOpenGL-Swift-macOS"; 218 | productReference = 0DE685721E4FD31E0089BF2F /* CocoaOpenGL-Swift-macOS.app */; 219 | productType = "com.apple.product-type.application"; 220 | }; 221 | 0DE685B71E4FD4BC0089BF2F /* CocoaOpenGL-Swift-iOS */ = { 222 | isa = PBXNativeTarget; 223 | buildConfigurationList = 0DE685CB1E4FD4BC0089BF2F /* Build configuration list for PBXNativeTarget "CocoaOpenGL-Swift-iOS" */; 224 | buildPhases = ( 225 | 0DE685B41E4FD4BC0089BF2F /* Sources */, 226 | 0DE685B51E4FD4BC0089BF2F /* Frameworks */, 227 | 0DE685B61E4FD4BC0089BF2F /* Resources */, 228 | ); 229 | buildRules = ( 230 | ); 231 | dependencies = ( 232 | ); 233 | name = "CocoaOpenGL-Swift-iOS"; 234 | productName = "CocoaOpenGL-Swift-iOS"; 235 | productReference = 0DE685B81E4FD4BC0089BF2F /* CocoaOpenGL-Swift-iOS.app */; 236 | productType = "com.apple.product-type.application"; 237 | }; 238 | /* End PBXNativeTarget section */ 239 | 240 | /* Begin PBXProject section */ 241 | 0DE685641E4FD28A0089BF2F /* Project object */ = { 242 | isa = PBXProject; 243 | attributes = { 244 | LastSwiftUpdateCheck = 0900; 245 | LastUpgradeCheck = 1230; 246 | TargetAttributes = { 247 | 0D6454951F814EBD007C0286 = { 248 | CreatedOnToolsVersion = 9.0; 249 | ProvisioningStyle = Automatic; 250 | }; 251 | 0DE685711E4FD31E0089BF2F = { 252 | CreatedOnToolsVersion = 8.2.1; 253 | LastSwiftMigration = 0900; 254 | ProvisioningStyle = Automatic; 255 | }; 256 | 0DE685B71E4FD4BC0089BF2F = { 257 | CreatedOnToolsVersion = 8.2.1; 258 | LastSwiftMigration = 1230; 259 | ProvisioningStyle = Automatic; 260 | }; 261 | }; 262 | }; 263 | buildConfigurationList = 0DE685671E4FD28A0089BF2F /* Build configuration list for PBXProject "CocoaOpenGL-Swift" */; 264 | compatibilityVersion = "Xcode 3.2"; 265 | developmentRegion = en; 266 | hasScannedForEncodings = 0; 267 | knownRegions = ( 268 | en, 269 | Base, 270 | ); 271 | mainGroup = 0DE685631E4FD28A0089BF2F; 272 | productRefGroup = 0DE685731E4FD31E0089BF2F /* Products */; 273 | projectDirPath = ""; 274 | projectRoot = ""; 275 | targets = ( 276 | 0DE685711E4FD31E0089BF2F /* CocoaOpenGL-Swift-macOS */, 277 | 0DE685B71E4FD4BC0089BF2F /* CocoaOpenGL-Swift-iOS */, 278 | 0D6454951F814EBD007C0286 /* CocoaOpenGL-Swift-tvOS */, 279 | ); 280 | }; 281 | /* End PBXProject section */ 282 | 283 | /* Begin PBXResourcesBuildPhase section */ 284 | 0D6454941F814EBD007C0286 /* Resources */ = { 285 | isa = PBXResourcesBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | 0D6454AF1F816FE0007C0286 /* normalmap.png in Resources */, 289 | 0D6454AD1F816FCB007C0286 /* shader.fs in Resources */, 290 | 0D6454AE1F816FCB007C0286 /* shader.vs in Resources */, 291 | 0D6454A01F814EBD007C0286 /* Assets.xcassets in Resources */, 292 | 0D64549E1F814EBD007C0286 /* Main.storyboard in Resources */, 293 | ); 294 | runOnlyForDeploymentPostprocessing = 0; 295 | }; 296 | 0DE685701E4FD31E0089BF2F /* Resources */ = { 297 | isa = PBXResourcesBuildPhase; 298 | buildActionMask = 2147483647; 299 | files = ( 300 | 0DE685B01E4FD3EF0089BF2F /* MainMenu.xib in Resources */, 301 | 0DE685AE1E4FD3EF0089BF2F /* Images.xcassets in Resources */, 302 | 0DE685B31E4FD3EF0089BF2F /* shader.vs in Resources */, 303 | 0DE685B21E4FD3EF0089BF2F /* shader.fs in Resources */, 304 | 0DE685911E4FD3CC0089BF2F /* normalmap.png in Resources */, 305 | ); 306 | runOnlyForDeploymentPostprocessing = 0; 307 | }; 308 | 0DE685B61E4FD4BC0089BF2F /* Resources */ = { 309 | isa = PBXResourcesBuildPhase; 310 | buildActionMask = 2147483647; 311 | files = ( 312 | 0DE685D61E4FD54C0089BF2F /* normalmap.png in Resources */, 313 | 0DE685D71E4FD54C0089BF2F /* Assets.xcassets in Resources */, 314 | 0DE685D81E4FD54C0089BF2F /* LaunchScreen.storyboard in Resources */, 315 | 0DE685D91E4FD54C0089BF2F /* Main.storyboard in Resources */, 316 | 0DE685DA1E4FD54C0089BF2F /* shader.fs in Resources */, 317 | 0DE685DB1E4FD54C0089BF2F /* shader.vs in Resources */, 318 | ); 319 | runOnlyForDeploymentPostprocessing = 0; 320 | }; 321 | /* End PBXResourcesBuildPhase section */ 322 | 323 | /* Begin PBXSourcesBuildPhase section */ 324 | 0D6454921F814EBD007C0286 /* Sources */ = { 325 | isa = PBXSourcesBuildPhase; 326 | buildActionMask = 2147483647; 327 | files = ( 328 | 0D6454B01F817014007C0286 /* AppDelegate.swift in Sources */, 329 | 0D6454A51F814FC6007C0286 /* Cylinder.swift in Sources */, 330 | 0D6454A61F814FC6007C0286 /* Matrix4.swift in Sources */, 331 | 0D6454A71F814FC6007C0286 /* Renderable.swift in Sources */, 332 | 0D6454A81F814FC6007C0286 /* Scene.swift in Sources */, 333 | 0D6454A91F814FC6007C0286 /* ShaderProgram.swift in Sources */, 334 | 0D6454AA1F814FC6007C0286 /* Texture.swift in Sources */, 335 | 0D6454AB1F814FC6007C0286 /* MyGLKViewController.swift in Sources */, 336 | ); 337 | runOnlyForDeploymentPostprocessing = 0; 338 | }; 339 | 0DE6856E1E4FD31E0089BF2F /* Sources */ = { 340 | isa = PBXSourcesBuildPhase; 341 | buildActionMask = 2147483647; 342 | files = ( 343 | 0DE685931E4FD3CC0089BF2F /* Scene.swift in Sources */, 344 | 0DE685951E4FD3CC0089BF2F /* Texture.swift in Sources */, 345 | 0DE685941E4FD3CC0089BF2F /* ShaderProgram.swift in Sources */, 346 | 0DE685AD1E4FD3EF0089BF2F /* AppDelegate.swift in Sources */, 347 | 0DE685921E4FD3CC0089BF2F /* Renderable.swift in Sources */, 348 | 0DE6858F1E4FD3CC0089BF2F /* Cylinder.swift in Sources */, 349 | 0DE685901E4FD3CC0089BF2F /* Matrix4.swift in Sources */, 350 | 0DE685B11E4FD3EF0089BF2F /* MyNSOpenGLView.swift in Sources */, 351 | ); 352 | runOnlyForDeploymentPostprocessing = 0; 353 | }; 354 | 0DE685B41E4FD4BC0089BF2F /* Sources */ = { 355 | isa = PBXSourcesBuildPhase; 356 | buildActionMask = 2147483647; 357 | files = ( 358 | 0DE685CE1E4FD5400089BF2F /* Cylinder.swift in Sources */, 359 | 0DE685CF1E4FD5400089BF2F /* Matrix4.swift in Sources */, 360 | 0DE685D01E4FD5400089BF2F /* Renderable.swift in Sources */, 361 | 0DE685D11E4FD5400089BF2F /* Scene.swift in Sources */, 362 | 0DE685D21E4FD5400089BF2F /* ShaderProgram.swift in Sources */, 363 | 0DE685D31E4FD5400089BF2F /* Texture.swift in Sources */, 364 | 0DE685D41E4FD5400089BF2F /* AppDelegate.swift in Sources */, 365 | 0DE685D51E4FD5400089BF2F /* MyGLKViewController.swift in Sources */, 366 | ); 367 | runOnlyForDeploymentPostprocessing = 0; 368 | }; 369 | /* End PBXSourcesBuildPhase section */ 370 | 371 | /* Begin PBXVariantGroup section */ 372 | 0D64549C1F814EBD007C0286 /* Main.storyboard */ = { 373 | isa = PBXVariantGroup; 374 | children = ( 375 | 0D64549D1F814EBD007C0286 /* Base */, 376 | ); 377 | name = Main.storyboard; 378 | sourceTree = ""; 379 | }; 380 | /* End PBXVariantGroup section */ 381 | 382 | /* Begin XCBuildConfiguration section */ 383 | 0D6454A21F814EBD007C0286 /* Debug */ = { 384 | isa = XCBuildConfiguration; 385 | buildSettings = { 386 | ALWAYS_SEARCH_USER_PATHS = NO; 387 | ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; 388 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 389 | CLANG_ANALYZER_NONNULL = YES; 390 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 391 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 392 | CLANG_CXX_LIBRARY = "libc++"; 393 | CLANG_ENABLE_MODULES = YES; 394 | CLANG_ENABLE_OBJC_ARC = YES; 395 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 396 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 397 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 398 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 399 | CODE_SIGN_STYLE = Automatic; 400 | COPY_PHASE_STRIP = NO; 401 | DEBUG_INFORMATION_FORMAT = dwarf; 402 | DEVELOPMENT_TEAM = ""; 403 | GCC_C_LANGUAGE_STANDARD = gnu11; 404 | GCC_DYNAMIC_NO_PIC = NO; 405 | GCC_OPTIMIZATION_LEVEL = 0; 406 | GCC_PREPROCESSOR_DEFINITIONS = ( 407 | "DEBUG=1", 408 | "GLES_SILENCE_DEPRECATION=1", 409 | ); 410 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 411 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 412 | INFOPLIST_FILE = tvOS/Info.plist; 413 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 414 | MTL_ENABLE_DEBUG_INFO = YES; 415 | PRODUCT_BUNDLE_IDENTIFIER = "com.joshbeam.CocoaOpenGL-Swift-tvOS"; 416 | PRODUCT_NAME = "$(TARGET_NAME)"; 417 | SDKROOT = appletvos; 418 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 419 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 420 | SWIFT_VERSION = 4.0; 421 | TARGETED_DEVICE_FAMILY = 3; 422 | TVOS_DEPLOYMENT_TARGET = 12.0; 423 | }; 424 | name = Debug; 425 | }; 426 | 0D6454A31F814EBD007C0286 /* Release */ = { 427 | isa = XCBuildConfiguration; 428 | buildSettings = { 429 | ALWAYS_SEARCH_USER_PATHS = NO; 430 | ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; 431 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 432 | CLANG_ANALYZER_NONNULL = YES; 433 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 434 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 435 | CLANG_CXX_LIBRARY = "libc++"; 436 | CLANG_ENABLE_MODULES = YES; 437 | CLANG_ENABLE_OBJC_ARC = YES; 438 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 439 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 440 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 441 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 442 | CODE_SIGN_STYLE = Automatic; 443 | COPY_PHASE_STRIP = NO; 444 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 445 | DEVELOPMENT_TEAM = ""; 446 | ENABLE_NS_ASSERTIONS = NO; 447 | GCC_C_LANGUAGE_STANDARD = gnu11; 448 | GCC_PREPROCESSOR_DEFINITIONS = "GLES_SILENCE_DEPRECATION=1"; 449 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 450 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 451 | INFOPLIST_FILE = tvOS/Info.plist; 452 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 453 | MTL_ENABLE_DEBUG_INFO = NO; 454 | PRODUCT_BUNDLE_IDENTIFIER = "com.joshbeam.CocoaOpenGL-Swift-tvOS"; 455 | PRODUCT_NAME = "$(TARGET_NAME)"; 456 | SDKROOT = appletvos; 457 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 458 | SWIFT_VERSION = 4.0; 459 | TARGETED_DEVICE_FAMILY = 3; 460 | TVOS_DEPLOYMENT_TARGET = 12.0; 461 | VALIDATE_PRODUCT = YES; 462 | }; 463 | name = Release; 464 | }; 465 | 0DE685681E4FD28A0089BF2F /* Debug */ = { 466 | isa = XCBuildConfiguration; 467 | buildSettings = { 468 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 469 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 470 | CLANG_WARN_BOOL_CONVERSION = YES; 471 | CLANG_WARN_COMMA = YES; 472 | CLANG_WARN_CONSTANT_CONVERSION = YES; 473 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 474 | CLANG_WARN_EMPTY_BODY = YES; 475 | CLANG_WARN_ENUM_CONVERSION = YES; 476 | CLANG_WARN_INFINITE_RECURSION = YES; 477 | CLANG_WARN_INT_CONVERSION = YES; 478 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 479 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 480 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 481 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 482 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 483 | CLANG_WARN_STRICT_PROTOTYPES = YES; 484 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 485 | CLANG_WARN_UNREACHABLE_CODE = YES; 486 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 487 | ENABLE_STRICT_OBJC_MSGSEND = YES; 488 | ENABLE_TESTABILITY = YES; 489 | GCC_NO_COMMON_BLOCKS = YES; 490 | GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; 491 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 492 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 493 | GCC_WARN_UNDECLARED_SELECTOR = YES; 494 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 495 | GCC_WARN_UNUSED_FUNCTION = YES; 496 | GCC_WARN_UNUSED_VARIABLE = YES; 497 | MACOSX_DEPLOYMENT_TARGET = 10.12; 498 | ONLY_ACTIVE_ARCH = YES; 499 | }; 500 | name = Debug; 501 | }; 502 | 0DE685691E4FD28A0089BF2F /* Release */ = { 503 | isa = XCBuildConfiguration; 504 | buildSettings = { 505 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 506 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 507 | CLANG_WARN_BOOL_CONVERSION = YES; 508 | CLANG_WARN_COMMA = YES; 509 | CLANG_WARN_CONSTANT_CONVERSION = YES; 510 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 511 | CLANG_WARN_EMPTY_BODY = YES; 512 | CLANG_WARN_ENUM_CONVERSION = YES; 513 | CLANG_WARN_INFINITE_RECURSION = YES; 514 | CLANG_WARN_INT_CONVERSION = YES; 515 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 516 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 517 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 518 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 519 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 520 | CLANG_WARN_STRICT_PROTOTYPES = YES; 521 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 522 | CLANG_WARN_UNREACHABLE_CODE = YES; 523 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 524 | ENABLE_STRICT_OBJC_MSGSEND = YES; 525 | GCC_NO_COMMON_BLOCKS = YES; 526 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 527 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 528 | GCC_WARN_UNDECLARED_SELECTOR = YES; 529 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 530 | GCC_WARN_UNUSED_FUNCTION = YES; 531 | GCC_WARN_UNUSED_VARIABLE = YES; 532 | MACOSX_DEPLOYMENT_TARGET = 10.12; 533 | }; 534 | name = Release; 535 | }; 536 | 0DE6857E1E4FD31E0089BF2F /* Debug */ = { 537 | isa = XCBuildConfiguration; 538 | buildSettings = { 539 | ALWAYS_SEARCH_USER_PATHS = NO; 540 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 541 | CLANG_ANALYZER_NONNULL = YES; 542 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 543 | CLANG_CXX_LIBRARY = "libc++"; 544 | CLANG_ENABLE_MODULES = YES; 545 | CLANG_ENABLE_OBJC_ARC = YES; 546 | CLANG_WARN_BOOL_CONVERSION = YES; 547 | CLANG_WARN_CONSTANT_CONVERSION = YES; 548 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 549 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 550 | CLANG_WARN_EMPTY_BODY = YES; 551 | CLANG_WARN_ENUM_CONVERSION = YES; 552 | CLANG_WARN_INFINITE_RECURSION = YES; 553 | CLANG_WARN_INT_CONVERSION = YES; 554 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 555 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 556 | CLANG_WARN_UNREACHABLE_CODE = YES; 557 | CODE_SIGN_IDENTITY = "-"; 558 | COMBINE_HIDPI_IMAGES = YES; 559 | COPY_PHASE_STRIP = NO; 560 | DEBUG_INFORMATION_FORMAT = dwarf; 561 | DEVELOPMENT_TEAM = ""; 562 | ENABLE_STRICT_OBJC_MSGSEND = YES; 563 | ENABLE_TESTABILITY = YES; 564 | GCC_C_LANGUAGE_STANDARD = gnu99; 565 | GCC_DYNAMIC_NO_PIC = NO; 566 | GCC_NO_COMMON_BLOCKS = YES; 567 | GCC_OPTIMIZATION_LEVEL = 0; 568 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 569 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 570 | GCC_WARN_UNDECLARED_SELECTOR = YES; 571 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 572 | GCC_WARN_UNUSED_FUNCTION = YES; 573 | GCC_WARN_UNUSED_VARIABLE = YES; 574 | INFOPLIST_FILE = "$(SRCROOT)/macOS/Info.plist"; 575 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 576 | MTL_ENABLE_DEBUG_INFO = YES; 577 | ONLY_ACTIVE_ARCH = YES; 578 | PRODUCT_BUNDLE_IDENTIFIER = "com.joshbeam.CocoaOpenGL-Swift-macOS"; 579 | PRODUCT_NAME = "$(TARGET_NAME)"; 580 | SDKROOT = macosx; 581 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 582 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 583 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 584 | SWIFT_VERSION = 4.0; 585 | }; 586 | name = Debug; 587 | }; 588 | 0DE6857F1E4FD31E0089BF2F /* Release */ = { 589 | isa = XCBuildConfiguration; 590 | buildSettings = { 591 | ALWAYS_SEARCH_USER_PATHS = NO; 592 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 593 | CLANG_ANALYZER_NONNULL = YES; 594 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 595 | CLANG_CXX_LIBRARY = "libc++"; 596 | CLANG_ENABLE_MODULES = YES; 597 | CLANG_ENABLE_OBJC_ARC = YES; 598 | CLANG_WARN_BOOL_CONVERSION = YES; 599 | CLANG_WARN_CONSTANT_CONVERSION = YES; 600 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 601 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 602 | CLANG_WARN_EMPTY_BODY = YES; 603 | CLANG_WARN_ENUM_CONVERSION = YES; 604 | CLANG_WARN_INFINITE_RECURSION = YES; 605 | CLANG_WARN_INT_CONVERSION = YES; 606 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 607 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 608 | CLANG_WARN_UNREACHABLE_CODE = YES; 609 | CODE_SIGN_IDENTITY = "-"; 610 | COMBINE_HIDPI_IMAGES = YES; 611 | COPY_PHASE_STRIP = NO; 612 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 613 | DEVELOPMENT_TEAM = ""; 614 | ENABLE_NS_ASSERTIONS = NO; 615 | ENABLE_STRICT_OBJC_MSGSEND = YES; 616 | GCC_C_LANGUAGE_STANDARD = gnu99; 617 | GCC_NO_COMMON_BLOCKS = YES; 618 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 619 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 620 | GCC_WARN_UNDECLARED_SELECTOR = YES; 621 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 622 | GCC_WARN_UNUSED_FUNCTION = YES; 623 | GCC_WARN_UNUSED_VARIABLE = YES; 624 | INFOPLIST_FILE = "$(SRCROOT)/macOS/Info.plist"; 625 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 626 | MTL_ENABLE_DEBUG_INFO = NO; 627 | PRODUCT_BUNDLE_IDENTIFIER = "com.joshbeam.CocoaOpenGL-Swift-macOS"; 628 | PRODUCT_NAME = "$(TARGET_NAME)"; 629 | SDKROOT = macosx; 630 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 631 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 632 | SWIFT_VERSION = 4.0; 633 | }; 634 | name = Release; 635 | }; 636 | 0DE685CC1E4FD4BC0089BF2F /* Debug */ = { 637 | isa = XCBuildConfiguration; 638 | buildSettings = { 639 | ALWAYS_SEARCH_USER_PATHS = NO; 640 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 641 | CLANG_ANALYZER_NONNULL = YES; 642 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 643 | CLANG_CXX_LIBRARY = "libc++"; 644 | CLANG_ENABLE_MODULES = YES; 645 | CLANG_ENABLE_OBJC_ARC = YES; 646 | CLANG_WARN_BOOL_CONVERSION = YES; 647 | CLANG_WARN_CONSTANT_CONVERSION = YES; 648 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 649 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 650 | CLANG_WARN_EMPTY_BODY = YES; 651 | CLANG_WARN_ENUM_CONVERSION = YES; 652 | CLANG_WARN_INFINITE_RECURSION = YES; 653 | CLANG_WARN_INT_CONVERSION = YES; 654 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 655 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 656 | CLANG_WARN_UNREACHABLE_CODE = YES; 657 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 658 | COPY_PHASE_STRIP = NO; 659 | DEBUG_INFORMATION_FORMAT = dwarf; 660 | DEVELOPMENT_TEAM = ""; 661 | ENABLE_STRICT_OBJC_MSGSEND = YES; 662 | ENABLE_TESTABILITY = YES; 663 | GCC_C_LANGUAGE_STANDARD = gnu99; 664 | GCC_DYNAMIC_NO_PIC = NO; 665 | GCC_NO_COMMON_BLOCKS = YES; 666 | GCC_OPTIMIZATION_LEVEL = 0; 667 | GCC_PREPROCESSOR_DEFINITIONS = ( 668 | "DEBUG=1", 669 | "GLES_SILENCE_DEPRECATION=1", 670 | ); 671 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 672 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 673 | GCC_WARN_UNDECLARED_SELECTOR = YES; 674 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 675 | GCC_WARN_UNUSED_FUNCTION = YES; 676 | GCC_WARN_UNUSED_VARIABLE = YES; 677 | INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; 678 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 679 | MTL_ENABLE_DEBUG_INFO = YES; 680 | ONLY_ACTIVE_ARCH = YES; 681 | PRODUCT_BUNDLE_IDENTIFIER = "com.joshbeam.CocoaOpenGL-Swift-iOS"; 682 | PRODUCT_NAME = "$(TARGET_NAME)"; 683 | SDKROOT = iphoneos; 684 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 685 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 686 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 687 | SWIFT_VERSION = 5.0; 688 | TARGETED_DEVICE_FAMILY = "1,2"; 689 | }; 690 | name = Debug; 691 | }; 692 | 0DE685CD1E4FD4BC0089BF2F /* Release */ = { 693 | isa = XCBuildConfiguration; 694 | buildSettings = { 695 | ALWAYS_SEARCH_USER_PATHS = NO; 696 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 697 | CLANG_ANALYZER_NONNULL = YES; 698 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 699 | CLANG_CXX_LIBRARY = "libc++"; 700 | CLANG_ENABLE_MODULES = YES; 701 | CLANG_ENABLE_OBJC_ARC = YES; 702 | CLANG_WARN_BOOL_CONVERSION = YES; 703 | CLANG_WARN_CONSTANT_CONVERSION = YES; 704 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 705 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 706 | CLANG_WARN_EMPTY_BODY = YES; 707 | CLANG_WARN_ENUM_CONVERSION = YES; 708 | CLANG_WARN_INFINITE_RECURSION = YES; 709 | CLANG_WARN_INT_CONVERSION = YES; 710 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 711 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 712 | CLANG_WARN_UNREACHABLE_CODE = YES; 713 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 714 | COPY_PHASE_STRIP = NO; 715 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 716 | DEVELOPMENT_TEAM = ""; 717 | ENABLE_NS_ASSERTIONS = NO; 718 | ENABLE_STRICT_OBJC_MSGSEND = YES; 719 | GCC_C_LANGUAGE_STANDARD = gnu99; 720 | GCC_NO_COMMON_BLOCKS = YES; 721 | GCC_PREPROCESSOR_DEFINITIONS = "GLES_SILENCE_DEPRECATION=1"; 722 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 723 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 724 | GCC_WARN_UNDECLARED_SELECTOR = YES; 725 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 726 | GCC_WARN_UNUSED_FUNCTION = YES; 727 | GCC_WARN_UNUSED_VARIABLE = YES; 728 | INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; 729 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 730 | MTL_ENABLE_DEBUG_INFO = NO; 731 | PRODUCT_BUNDLE_IDENTIFIER = "com.joshbeam.CocoaOpenGL-Swift-iOS"; 732 | PRODUCT_NAME = "$(TARGET_NAME)"; 733 | SDKROOT = iphoneos; 734 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 735 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 736 | SWIFT_VERSION = 5.0; 737 | TARGETED_DEVICE_FAMILY = "1,2"; 738 | VALIDATE_PRODUCT = YES; 739 | }; 740 | name = Release; 741 | }; 742 | /* End XCBuildConfiguration section */ 743 | 744 | /* Begin XCConfigurationList section */ 745 | 0D6454A41F814EBD007C0286 /* Build configuration list for PBXNativeTarget "CocoaOpenGL-Swift-tvOS" */ = { 746 | isa = XCConfigurationList; 747 | buildConfigurations = ( 748 | 0D6454A21F814EBD007C0286 /* Debug */, 749 | 0D6454A31F814EBD007C0286 /* Release */, 750 | ); 751 | defaultConfigurationIsVisible = 0; 752 | defaultConfigurationName = Release; 753 | }; 754 | 0DE685671E4FD28A0089BF2F /* Build configuration list for PBXProject "CocoaOpenGL-Swift" */ = { 755 | isa = XCConfigurationList; 756 | buildConfigurations = ( 757 | 0DE685681E4FD28A0089BF2F /* Debug */, 758 | 0DE685691E4FD28A0089BF2F /* Release */, 759 | ); 760 | defaultConfigurationIsVisible = 0; 761 | defaultConfigurationName = Release; 762 | }; 763 | 0DE6857D1E4FD31E0089BF2F /* Build configuration list for PBXNativeTarget "CocoaOpenGL-Swift-macOS" */ = { 764 | isa = XCConfigurationList; 765 | buildConfigurations = ( 766 | 0DE6857E1E4FD31E0089BF2F /* Debug */, 767 | 0DE6857F1E4FD31E0089BF2F /* Release */, 768 | ); 769 | defaultConfigurationIsVisible = 0; 770 | defaultConfigurationName = Release; 771 | }; 772 | 0DE685CB1E4FD4BC0089BF2F /* Build configuration list for PBXNativeTarget "CocoaOpenGL-Swift-iOS" */ = { 773 | isa = XCConfigurationList; 774 | buildConfigurations = ( 775 | 0DE685CC1E4FD4BC0089BF2F /* Debug */, 776 | 0DE685CD1E4FD4BC0089BF2F /* Release */, 777 | ); 778 | defaultConfigurationIsVisible = 0; 779 | defaultConfigurationName = Release; 780 | }; 781 | /* End XCConfigurationList section */ 782 | }; 783 | rootObject = 0DE685641E4FD28A0089BF2F /* Project object */; 784 | } 785 | -------------------------------------------------------------------------------- /Common/Cylinder.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | import Foundation 27 | #if os(macOS) 28 | import OpenGL 29 | #else 30 | import OpenGLES 31 | #endif 32 | 33 | class Cylinder: Renderable { 34 | private var numVertices = 0 35 | private var vertexArrayId: GLuint = 0 36 | private var bufferIds = [GLuint](repeating: 0, count: 5) 37 | 38 | init(program: ShaderProgram, numberOfDivisions divisions: Int) { 39 | let divisionsf = Float(divisions) 40 | 41 | numVertices = (divisions + 1) * 2 42 | let size = numVertices * 3 43 | let tcSize = numVertices * 2 44 | 45 | // Generate vertex data. 46 | var p = [Float](repeating: 0.0, count: size) 47 | var tc = [Float](repeating: 0.0, count: tcSize) 48 | var t = [Float](repeating: 0.0, count: size) 49 | var b = [Float](repeating: 0.0, count: size) 50 | var n = [Float](repeating: 0.0, count: size) 51 | for i in 0...divisions { 52 | let r1 = ((Float.pi * 2.0) / divisionsf) * Float(i) 53 | let r2 = r1 + Float.pi / 2.0 54 | 55 | let c1 = cosf(r1) 56 | let s1 = sinf(r1) 57 | let c2 = cosf(r2) 58 | let s2 = sinf(r2) 59 | 60 | let j = i * 6 61 | let k = i * 4 62 | 63 | // vertex positions 64 | p[j+0] = c1 65 | p[j+1] = 1.0 66 | p[j+2] = -s1 67 | p[j+3] = c1 68 | p[j+4] = -1.0 69 | p[j+5] = -s1 70 | 71 | // vertex texture coordinates 72 | tc[k+0] = 1.0 / divisionsf * Float(i) * 3.0 73 | tc[k+1] = 0.0 74 | tc[k+2] = tc[k+0] 75 | tc[k+3] = 1.0 76 | 77 | // vertex tangents 78 | t[j+0] = c2 79 | t[j+1] = 0.0 80 | t[j+2] = -s2 81 | t[j+3] = c2 82 | t[j+4] = 0.0 83 | t[j+5] = -s2 84 | 85 | // vertex bitangents 86 | b[j+0] = 0.0 87 | b[j+1] = 1.0 88 | b[j+2] = 0.0 89 | b[j+3] = 0.0 90 | b[j+4] = 1.0 91 | b[j+5] = 0.0 92 | 93 | // vertex normals 94 | n[j+0] = c1 95 | n[j+1] = 0.0 96 | n[j+2] = -s1 97 | n[j+3] = c1 98 | n[j+4] = 0.0 99 | n[j+5] = -s1 100 | } 101 | 102 | // Get the program's vertex data locations. 103 | let vertexPositionLocation = program.getAttributeLocation("vertexPosition")! 104 | let vertexTexCoordsLocation = program.getAttributeLocation("vertexTexCoords")! 105 | let vertexTangentLocation = program.getAttributeLocation("vertexTangent")! 106 | let vertexBitangentLocation = program.getAttributeLocation("vertexBitangent")! 107 | let vertexNormalLocation = program.getAttributeLocation("vertexNormal")! 108 | 109 | // Create vertex array. 110 | glGenVertexArrays(1, &vertexArrayId) 111 | glBindVertexArray(vertexArrayId) 112 | 113 | // Create buffers. 114 | bufferIds = [GLuint](repeating: 0, count: 5) 115 | glGenBuffers(5, &bufferIds) 116 | 117 | // Create position buffer. 118 | glBindBuffer(GLenum(GL_ARRAY_BUFFER), bufferIds[0]) 119 | glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout.size * size, p, GLenum(GL_STATIC_DRAW)) 120 | 121 | // Create position attribute array. 122 | glEnableVertexAttribArray(vertexPositionLocation) 123 | glVertexAttribPointer(vertexPositionLocation, 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, nil) 124 | 125 | // Create texture coordinates buffer. 126 | glBindBuffer(GLenum(GL_ARRAY_BUFFER), bufferIds[1]) 127 | glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout.size * tcSize, tc, GLenum(GL_STATIC_DRAW)) 128 | 129 | // Create texture coordinates attribute array. 130 | glEnableVertexAttribArray(vertexTexCoordsLocation) 131 | glVertexAttribPointer(vertexTexCoordsLocation, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, nil) 132 | 133 | // Create tangent buffer. 134 | glBindBuffer(GLenum(GL_ARRAY_BUFFER), bufferIds[2]) 135 | glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout.size * size, t, GLenum(GL_STATIC_DRAW)) 136 | 137 | // Create tangent attribute array. 138 | glEnableVertexAttribArray(vertexTangentLocation) 139 | glVertexAttribPointer(vertexTangentLocation, 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, nil) 140 | 141 | // Create bitangent buffer. 142 | glBindBuffer(GLenum(GL_ARRAY_BUFFER), bufferIds[3]) 143 | glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout.size * size, b, GLenum(GL_STATIC_DRAW)) 144 | 145 | // Create bitangent attribute array. 146 | glEnableVertexAttribArray(vertexBitangentLocation) 147 | glVertexAttribPointer(vertexBitangentLocation, 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, nil) 148 | 149 | // Create normal buffer. 150 | glBindBuffer(GLenum(GL_ARRAY_BUFFER), bufferIds[4]) 151 | glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout.size * size, n, GLenum(GL_STATIC_DRAW)) 152 | 153 | // Create normal attribute array. 154 | glEnableVertexAttribArray(vertexNormalLocation) 155 | glVertexAttribPointer(vertexNormalLocation, 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, nil) 156 | } 157 | 158 | deinit { 159 | glDeleteBuffers(5, &bufferIds) 160 | glDeleteVertexArrays(1, &vertexArrayId) 161 | } 162 | 163 | func render() { 164 | glBindVertexArray(vertexArrayId) 165 | glDrawArrays(GLenum(GL_TRIANGLE_STRIP), 0, GLint(numVertices)) 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /Common/Matrix4.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | import Foundation 27 | 28 | struct Matrix4 { 29 | var matrix: [Float] = [ 30 | 1.0, 0.0, 0.0, 0.0, 31 | 0.0, 1.0, 0.0, 0.0, 32 | 0.0, 0.0, 1.0, 0.0, 33 | 0.0, 0.0, 0.0, 1.0 34 | ] 35 | 36 | static func perspectiveMatrix(fov: Float, aspect: Float, near: Float, far: Float) -> Matrix4 { 37 | var matrix = Matrix4() 38 | let f = 1.0 / tanf(fov / 2.0) 39 | 40 | matrix.matrix[0] = f / aspect 41 | matrix.matrix[5] = f 42 | matrix.matrix[10] = (far + near) / (near - far) 43 | matrix.matrix[11] = -1.0 44 | matrix.matrix[14] = (2.0 * far * near) / (near - far) 45 | matrix.matrix[15] = 0.0 46 | 47 | return matrix 48 | } 49 | 50 | static func translationMatrix(x: Float, y: Float, z: Float) -> Matrix4 { 51 | var matrix = Matrix4() 52 | 53 | matrix.matrix[12] = x 54 | matrix.matrix[13] = y 55 | matrix.matrix[14] = z 56 | 57 | return matrix 58 | } 59 | 60 | static func rotationMatrix(angle: Float, x: Float, y: Float, z: Float) -> Matrix4 { 61 | var matrix = Matrix4() 62 | 63 | let c = cosf(angle) 64 | let ci = 1.0 - c 65 | let s = sinf(angle) 66 | 67 | let xy = x * y * ci 68 | let xz = x * z * ci 69 | let yz = y * z * ci 70 | let xs = x * s 71 | let ys = y * s 72 | let zs = z * s 73 | 74 | matrix.matrix[0] = x * x * ci + c 75 | matrix.matrix[1] = xy + zs 76 | matrix.matrix[2] = xz - ys 77 | matrix.matrix[4] = xy - zs 78 | matrix.matrix[5] = y * y * ci + c 79 | matrix.matrix[6] = yz + xs 80 | matrix.matrix[8] = xz + ys 81 | matrix.matrix[9] = yz - xs 82 | matrix.matrix[10] = z * z * ci + c 83 | 84 | return matrix 85 | } 86 | } 87 | 88 | func * (left: Matrix4, right: Matrix4) -> Matrix4 { 89 | let m1 = left.matrix 90 | let m2 = right.matrix 91 | var m = [Float](repeating: 0.0, count: 16) 92 | 93 | m[ 0] = m1[ 0]*m2[ 0] + m1[ 1]*m2[ 4] + m1[ 2]*m2[ 8] + m1[ 3]*m2[12] 94 | m[ 1] = m1[ 0]*m2[ 1] + m1[ 1]*m2[ 5] + m1[ 2]*m2[ 9] + m1[ 3]*m2[13] 95 | m[ 2] = m1[ 0]*m2[ 2] + m1[ 1]*m2[ 6] + m1[ 2]*m2[10] + m1[ 3]*m2[14] 96 | m[ 3] = m1[ 0]*m2[ 3] + m1[ 1]*m2[ 7] + m1[ 2]*m2[11] + m1[ 3]*m2[15] 97 | m[ 4] = m1[ 4]*m2[ 0] + m1[ 5]*m2[ 4] + m1[ 6]*m2[ 8] + m1[ 7]*m2[12] 98 | m[ 5] = m1[ 4]*m2[ 1] + m1[ 5]*m2[ 5] + m1[ 6]*m2[ 9] + m1[ 7]*m2[13] 99 | m[ 6] = m1[ 4]*m2[ 2] + m1[ 5]*m2[ 6] + m1[ 6]*m2[10] + m1[ 7]*m2[14] 100 | m[ 7] = m1[ 4]*m2[ 3] + m1[ 5]*m2[ 7] + m1[ 6]*m2[11] + m1[ 7]*m2[15] 101 | m[ 8] = m1[ 8]*m2[ 0] + m1[ 9]*m2[ 4] + m1[10]*m2[ 8] + m1[11]*m2[12] 102 | m[ 9] = m1[ 8]*m2[ 1] + m1[ 9]*m2[ 5] + m1[10]*m2[ 9] + m1[11]*m2[13] 103 | m[10] = m1[ 8]*m2[ 2] + m1[ 9]*m2[ 6] + m1[10]*m2[10] + m1[11]*m2[14] 104 | m[11] = m1[ 8]*m2[ 3] + m1[ 9]*m2[ 7] + m1[10]*m2[11] + m1[11]*m2[15] 105 | m[12] = m1[12]*m2[ 0] + m1[13]*m2[ 4] + m1[14]*m2[ 8] + m1[15]*m2[12] 106 | m[13] = m1[12]*m2[ 1] + m1[13]*m2[ 5] + m1[14]*m2[ 9] + m1[15]*m2[13] 107 | m[14] = m1[12]*m2[ 2] + m1[13]*m2[ 6] + m1[14]*m2[10] + m1[15]*m2[14] 108 | m[15] = m1[12]*m2[ 3] + m1[13]*m2[ 7] + m1[14]*m2[11] + m1[15]*m2[15] 109 | 110 | return Matrix4(matrix: m) 111 | } 112 | -------------------------------------------------------------------------------- /Common/Renderable.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | protocol Renderable { 27 | func render() 28 | } 29 | -------------------------------------------------------------------------------- /Common/Scene.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | import Foundation 27 | #if os(macOS) 28 | import OpenGL 29 | #else 30 | import OpenGLES 31 | #endif 32 | 33 | let NUM_LIGHTS = 3 34 | 35 | class Scene { 36 | private var program: ShaderProgram 37 | private var programProjectionMatrixLocation: GLuint 38 | private var programModelviewMatrixLocation: GLuint 39 | private var programCameraPositionLocation: GLuint 40 | private var programLightPositionLocation: GLuint 41 | private var programLightColorLocation: GLuint 42 | 43 | private var lightPosition = [Float](repeating: 0.0, count: NUM_LIGHTS * 3) 44 | private var lightColor: [Float] = [1.0, 0.0, 0.0, 45 | 0.0, 1.0, 0.0, 46 | 0.0, 0.0, 1.0] 47 | private var lightRotation: Float = 0.0 48 | 49 | private var normalmap: Texture? 50 | private var renderable: Renderable 51 | 52 | private var cameraRotation: Float = 0.0 53 | private var cameraPosition: [Float] = [0.0, 0.0, 4.0] 54 | 55 | init() { 56 | // Create the program, attach shaders, and link. 57 | program = ShaderProgram() 58 | program.attachShader("shader.vs", withType: GL_VERTEX_SHADER) 59 | program.attachShader("shader.fs", withType: GL_FRAGMENT_SHADER) 60 | program.link() 61 | 62 | // Get uniform locations. 63 | programProjectionMatrixLocation = program.getUniformLocation("projectionMatrix")! 64 | programModelviewMatrixLocation = program.getUniformLocation("modelviewMatrix")! 65 | programCameraPositionLocation = program.getUniformLocation("cameraPosition")! 66 | programLightPositionLocation = program.getUniformLocation("lightPosition")! 67 | programLightColorLocation = program.getUniformLocation("lightColor")! 68 | 69 | normalmap = Texture.loadFromFile("normalmap.png") 70 | renderable = Cylinder(program: program, numberOfDivisions: 36) 71 | } 72 | 73 | func render(_ projectionMatrix: Matrix4) { 74 | let translationMatrix = Matrix4.translationMatrix(x: -cameraPosition[0], y: -cameraPosition[1], z: -cameraPosition[2]) 75 | let rotationMatrix = Matrix4.rotationMatrix(angle: cameraRotation, x: 0.0, y: -1.0, z: 0.0) 76 | let modelviewMatrix = translationMatrix * rotationMatrix 77 | 78 | // Enable the program and set uniform variables. 79 | program.use() 80 | glUniformMatrix4fv(GLint(programProjectionMatrixLocation), 1, GLboolean(GL_FALSE), projectionMatrix.matrix) 81 | glUniformMatrix4fv(GLint(programModelviewMatrixLocation), 1, GLboolean(GL_FALSE), modelviewMatrix.matrix) 82 | glUniform3fv(GLint(programCameraPositionLocation), 1, cameraPosition) 83 | glUniform3fv(GLint(programLightPositionLocation), GLint(NUM_LIGHTS), lightPosition) 84 | glUniform3fv(GLint(programLightColorLocation), GLint(NUM_LIGHTS), lightColor) 85 | 86 | // Render the object. 87 | renderable.render() 88 | 89 | // Disable the program. 90 | glUseProgram(0) 91 | } 92 | 93 | func cycle(_ secondsElapsed: Float) { 94 | // Update the light positions. 95 | lightRotation += (Float.pi / 4.0) * secondsElapsed 96 | for i in 0.. GLuint? { 70 | let tmp = glGetAttribLocation(program, name.cString(using: String.Encoding.utf8)!) 71 | return tmp < 0 ? nil : GLuint(tmp) 72 | } 73 | 74 | func getUniformLocation(_ name: String) -> GLuint? { 75 | let tmp = glGetUniformLocation(program, name.cString(using: String.Encoding.utf8)!) 76 | return tmp < 0 ? nil : GLuint(tmp) 77 | } 78 | 79 | func use() { 80 | glUseProgram(program) 81 | } 82 | 83 | private func getGLShaderInfoLog(_ shader: GLuint) -> String { 84 | // Get the length of the info log. 85 | var length: GLint = 0 86 | glGetShaderiv(shader, GLenum(GL_INFO_LOG_LENGTH), &length) 87 | 88 | // Retrieve the info log. 89 | var str = [GLchar](repeating: GLchar(0), count: Int(length) + 1) 90 | var size: GLsizei = 0 91 | glGetShaderInfoLog(shader, GLsizei(length), &size, &str) 92 | 93 | return String(cString: str) 94 | } 95 | 96 | private func compileShader(_ file: String, withType type: GLenum) -> GLuint? { 97 | // Load the shader source. 98 | let path = Bundle.main.resourcePath! + "/" + file 99 | let source = try? String(contentsOfFile: path, encoding: String.Encoding.ascii) 100 | if source == nil { 101 | NSLog("Unable to load \(file)") 102 | return nil 103 | } 104 | 105 | let cSource = source!.cString(using: String.Encoding.ascii) 106 | var glcSource = UnsafePointer? (cSource!) 107 | 108 | // Compile the shader. 109 | let shader = glCreateShader(type) 110 | var length = GLint((source!.utf8).count) 111 | glShaderSource(shader, 1, &glcSource, &length) 112 | glCompileShader(shader) 113 | 114 | // Make sure the compilation was successful. 115 | var result: GLint = 0 116 | glGetShaderiv(shader, GLenum(GL_COMPILE_STATUS), &result) 117 | if result == GL_FALSE { 118 | NSLog("Compilation of \(file) failed: \(getGLShaderInfoLog(shader))") 119 | glDeleteShader(shader) 120 | return nil 121 | } 122 | 123 | return shader 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Common/Texture.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | import Foundation 27 | #if !os(Android) 28 | import CoreGraphics 29 | #endif 30 | #if os(macOS) 31 | import OpenGL 32 | #else 33 | import OpenGLES 34 | #endif 35 | 36 | class Texture { 37 | private(set) var textureId: GLuint 38 | private(set) var width: UInt 39 | private(set) var height: UInt 40 | 41 | init(textureId: GLuint, width: UInt, height: UInt) { 42 | self.textureId = textureId 43 | self.width = width 44 | self.height = height 45 | } 46 | 47 | deinit { 48 | glDeleteTextures(1, &textureId) 49 | } 50 | 51 | static func loadFromFile(_ filePath: String) -> Texture? { 52 | let fullPath = Bundle.main.resourcePath! + "/" + filePath 53 | #if !os(Android) 54 | let dataProvider = CGDataProvider(filename: fullPath) 55 | if dataProvider == nil { 56 | return nil 57 | } 58 | 59 | let image = CGImage(pngDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: false, intent: CGColorRenderingIntent.defaultIntent) 60 | let imageData = image?.dataProvider?.data 61 | 62 | // Get the image data, dimensions, and number of components. 63 | let data = CFDataGetBytePtr(imageData) 64 | let width = UInt((image?.width)!) 65 | let height = UInt((image?.height)!) 66 | let numComponents = (image?.bitsPerPixel)! / 8 67 | 68 | // Determine the GL texture format based on the number of components. 69 | var format: GLint 70 | switch numComponents { 71 | case 1: format = GL_RED 72 | case 3: format = GL_RGB 73 | case 4: format = GL_RGBA 74 | default: 75 | return nil 76 | } 77 | #else 78 | // workaround when CoreGraphics is not available 79 | let imageData = NSData(contentsOfFile: fullPath)! 80 | withExtendedLifetime(imageData) {} 81 | let data = imageData.bytes 82 | let width = UInt(512) 83 | let height = UInt(512) 84 | let format = GL_RGBA 85 | #endif 86 | 87 | // Generate and bind texture. 88 | var textureId: GLuint = 0 89 | glGenTextures(1, &textureId) 90 | glBindTexture(GLenum(GL_TEXTURE_2D), textureId) 91 | 92 | // Set parameters. 93 | glPixelStorei(GLenum(GL_UNPACK_ALIGNMENT), 1) 94 | glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), GL_REPEAT) 95 | glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), GL_REPEAT) 96 | glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), GL_LINEAR) 97 | glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), GL_LINEAR) 98 | 99 | // Set the texture data. 100 | glTexImage2D(GLenum(GL_TEXTURE_2D), 0, format, GLsizei(width), GLsizei(height), 0, GLenum(format), GLenum(GL_UNSIGNED_BYTE), data) 101 | 102 | return Texture(textureId: textureId, width: width, height: height) 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Common/normalmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshb/CocoaOpenGL-Swift/3bf42fcb09d046613b3d2428fbf2a9eb1daf5fe4/Common/normalmap.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2015-2020 Josh A. Beam 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CocoaOpenGL-Swift 2 | ================= 3 | 4 | This is a simple example of using Swift to create an OpenGL application for macOS, iOS, and tvOS. It features a rotating, normal mapped cylinder that is illuminated by three moving point lights of different colors. 5 | 6 | ![CocoaOpenGL-Swift](CocoaOpenGL-Swift.png) 7 | 8 | Aside from the vertex and fragment shaders written in GLSL, all of the application code is written in Swift. 9 | 10 | This application was developed by [Josh Beam](https://joshbeam.com/) and is distributed under a [BSD-style license](LICENSE). 11 | -------------------------------------------------------------------------------- /iOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | import UIKit 27 | 28 | @UIApplicationMain 29 | class AppDelegate: UIResponder, UIApplicationDelegate { 30 | var window: UIWindow? 31 | 32 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 33 | return true 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UIStatusBarHidden 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /iOS/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /iOS/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /iOS/MyGLKViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | import GLKit 27 | import OpenGLES 28 | 29 | class MyGLKViewController: GLKViewController { 30 | var context: EAGLContext? = nil 31 | 32 | private var scene: Scene! 33 | private var ticks: UInt64 = MyGLKViewController.getTicks() 34 | 35 | deinit { 36 | if EAGLContext.current() === self.context { 37 | EAGLContext.setCurrent(nil) 38 | } 39 | } 40 | 41 | override func viewDidLoad() { 42 | super.viewDidLoad() 43 | 44 | self.context = EAGLContext(api: .openGLES2) 45 | if self.context == nil { 46 | print("Failed to create ES context") 47 | } 48 | 49 | EAGLContext.setCurrent(self.context) 50 | 51 | let view = self.view as! GLKView 52 | view.context = self.context! 53 | view.drawableDepthFormat = .format24 54 | 55 | // Do some GL setup. 56 | glClearColor(0.0, 0.0, 0.0, 0.0) 57 | glClearDepthf(1.0) 58 | glDisable(GLenum(GL_BLEND)) 59 | glEnable(GLenum(GL_DEPTH_TEST)) 60 | glDepthFunc(GLenum(GL_LEQUAL)) 61 | glEnable(GLenum(GL_CULL_FACE)) 62 | glFrontFace(GLenum(GL_CCW)) 63 | glCullFace(GLenum(GL_BACK)) 64 | 65 | scene = Scene() 66 | } 67 | 68 | override func didReceiveMemoryWarning() { 69 | super.didReceiveMemoryWarning() 70 | 71 | if self.isViewLoaded && (self.view.window != nil) { 72 | self.view = nil 73 | 74 | if EAGLContext.current() === self.context { 75 | EAGLContext.setCurrent(nil) 76 | } 77 | self.context = nil 78 | } 79 | } 80 | 81 | override func glkView(_ view: GLKView, drawIn rect: CGRect) { 82 | // Create projection matrix. 83 | let aspectRatio = Float(rect.size.width / rect.size.height) 84 | let projectionMatrix = Matrix4.perspectiveMatrix(fov: Float.pi / 2.0, aspect: aspectRatio, near: 0.1, far: 200.0) 85 | 86 | // Render the scene. 87 | glClear(GLbitfield(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) 88 | scene.render(projectionMatrix) 89 | glFlush() 90 | 91 | // Cycle the scene. 92 | let newTicks = MyGLKViewController.getTicks() 93 | let secondsElapsed = Float(newTicks - ticks) / 1000.0 94 | ticks = newTicks 95 | scene.cycle(secondsElapsed) 96 | } 97 | 98 | private class func getTicks() -> UInt64 { 99 | var t = timeval() 100 | gettimeofday(&t, nil) 101 | return UInt64(t.tv_sec * 1000) + UInt64(t.tv_usec / 1000) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /iOS/shader.fs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010-2012 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | const int NUM_LIGHTS = 3; 27 | const lowp vec3 AMBIENT = vec3(0.1, 0.1, 0.1); 28 | const lowp float MAX_DIST = 2.5; 29 | const lowp float MAX_DIST_SQUARED = MAX_DIST * MAX_DIST; 30 | 31 | uniform sampler2D normalmap; 32 | uniform lowp vec3 lightColor[NUM_LIGHTS]; 33 | 34 | varying lowp vec2 fragmentTexCoords; 35 | varying lowp vec3 cameraVector; 36 | varying lowp vec3 lightVector[NUM_LIGHTS]; 37 | 38 | void 39 | main() 40 | { 41 | // initialize diffuse/specular lighting 42 | lowp vec3 diffuse = vec3(0.0, 0.0, 0.0); 43 | lowp vec3 specular = vec3(0.0, 0.0, 0.0); 44 | 45 | // get the fragment normal and camera direction 46 | lowp vec3 fragmentNormal = (texture2D(normalmap, fragmentTexCoords).rgb * 2.0) - 1.0; 47 | lowp vec3 normal = normalize(fragmentNormal); 48 | lowp vec3 cameraDir = normalize(cameraVector); 49 | 50 | // loop through each light 51 | for(int i = 0; i < NUM_LIGHTS; ++i) { 52 | // calculate distance between 0.0 and 1.0 53 | lowp float dist = min(dot(lightVector[i], lightVector[i]), MAX_DIST_SQUARED) / MAX_DIST_SQUARED; 54 | lowp float distFactor = 1.0 - dist; 55 | 56 | // diffuse 57 | lowp vec3 lightDir = normalize(lightVector[i]); 58 | lowp float diffuseDot = dot(normal, lightDir); 59 | diffuse += lightColor[i] * clamp(diffuseDot, 0.0, 1.0) * distFactor; 60 | 61 | // specular 62 | lowp vec3 halfAngle = normalize(cameraDir + lightDir); 63 | lowp vec3 specularColor = min(lightColor[i] + 0.5, 1.0); 64 | lowp float specularDot = dot(normal, halfAngle); 65 | specular += specularColor * pow(clamp(specularDot, 0.0, 1.0), 16.0) * distFactor; 66 | } 67 | 68 | lowp vec4 sample = vec4(1.0, 1.0, 1.0, 1.0); 69 | gl_FragColor = vec4(clamp(sample.rgb * (diffuse + AMBIENT) + specular, 0.0, 1.0), sample.a); 70 | } 71 | -------------------------------------------------------------------------------- /iOS/shader.vs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010-2012 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | const int NUM_LIGHTS = 3; 27 | 28 | uniform mat4 projectionMatrix; 29 | uniform mat4 modelviewMatrix; 30 | 31 | uniform vec3 cameraPosition; 32 | uniform vec3 lightPosition[NUM_LIGHTS]; 33 | 34 | attribute vec3 vertexPosition; 35 | attribute vec2 vertexTexCoords; 36 | attribute vec3 vertexTangent; 37 | attribute vec3 vertexBitangent; 38 | attribute vec3 vertexNormal; 39 | 40 | varying vec2 fragmentTexCoords; 41 | varying vec3 cameraVector; 42 | varying vec3 lightVector[NUM_LIGHTS]; 43 | 44 | void 45 | main() 46 | { 47 | mat3 tangentSpace = mat3(vertexTangent, vertexBitangent, vertexNormal); 48 | 49 | // set the vector from the vertex to the camera 50 | cameraVector = (cameraPosition - vertexPosition.xyz) * tangentSpace; 51 | 52 | // set the vectors from the vertex to each light 53 | for(int i = 0; i < NUM_LIGHTS; ++i) 54 | lightVector[i] = (lightPosition[i] - vertexPosition.xyz) * tangentSpace; 55 | 56 | // output the transformed vertex 57 | fragmentTexCoords = vertexTexCoords; 58 | gl_Position = (projectionMatrix * modelviewMatrix) * vec4(vertexPosition, 1.0); 59 | } 60 | -------------------------------------------------------------------------------- /macOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | import Cocoa 27 | import OpenGL 28 | import GLKit 29 | 30 | @NSApplicationMain 31 | class AppDelegate: NSObject, NSApplicationDelegate { 32 | @IBOutlet weak var window: NSWindow! 33 | @IBOutlet weak var view: MyNSOpenGLView! 34 | 35 | private var timer: Timer! 36 | private var scene: Scene! 37 | private var ticks: UInt64 = AppDelegate.getTicks() 38 | 39 | func applicationDidFinishLaunching(_ aNotification: Notification) { 40 | // Do some GL setup. 41 | glClearColor(0.0, 0.0, 0.0, 0.0) 42 | glClearDepth(1.0) 43 | glDisable(GLenum(GL_BLEND)) 44 | glEnable(GLenum(GL_DEPTH_TEST)) 45 | glDepthFunc(GLenum(GL_LEQUAL)) 46 | glEnable(GLenum(GL_CULL_FACE)) 47 | glFrontFace(GLenum(GL_CCW)) 48 | glCullFace(GLenum(GL_BACK)) 49 | 50 | scene = Scene() 51 | 52 | // Create a timer to render. 53 | timer = Timer(timeInterval: 1.0 / 60.0, repeats: true, block: timerFireMethod) 54 | RunLoop.current.add(timer, forMode: RunLoopMode.defaultRunLoopMode) 55 | } 56 | 57 | func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 58 | return true 59 | } 60 | 61 | func timerFireMethod(_ sender: Timer!) { 62 | // Render the scene. 63 | glClear(GLbitfield(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) 64 | scene.render(view.projectionMatrix) 65 | glFlush() 66 | view.flush() 67 | 68 | // Cycle the scene. 69 | let newTicks = AppDelegate.getTicks() 70 | let secondsElapsed = Float(newTicks - ticks) / 1000.0 71 | ticks = newTicks 72 | scene.cycle(secondsElapsed) 73 | } 74 | 75 | private class func getTicks() -> UInt64 { 76 | var t = timeval() 77 | gettimeofday(&t, nil) 78 | return UInt64(t.tv_sec * 1000) + UInt64(t.tv_usec / 1000) 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /macOS/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2015 Josh Beam. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /macOS/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /macOS/MyNSOpenGLView.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | import Cocoa 27 | 28 | class MyNSOpenGLView: NSOpenGLView 29 | { 30 | var projectionMatrix = Matrix4() 31 | 32 | private var trackingArea: NSTrackingArea? 33 | 34 | override func awakeFromNib() 35 | { 36 | let attr = [ 37 | NSOpenGLPixelFormatAttribute(NSOpenGLPFAOpenGLProfile), 38 | NSOpenGLPixelFormatAttribute(NSOpenGLProfileVersion3_2Core), 39 | NSOpenGLPixelFormatAttribute(NSOpenGLPFAColorSize), 24, 40 | NSOpenGLPixelFormatAttribute(NSOpenGLPFAAlphaSize), 8, 41 | NSOpenGLPixelFormatAttribute(NSOpenGLPFADoubleBuffer), 42 | NSOpenGLPixelFormatAttribute(NSOpenGLPFADepthSize), 32, 43 | 0 44 | ] 45 | 46 | let format = NSOpenGLPixelFormat(attributes: attr) 47 | let context = NSOpenGLContext(format: format!, share: nil) 48 | 49 | self.openGLContext = context 50 | self.openGLContext?.makeCurrentContext() 51 | } 52 | 53 | override func reshape() { 54 | let frame = self.frame 55 | 56 | // Update the viewport. 57 | glViewport(0, 0, GLsizei(frame.size.width), GLsizei(frame.size.height)) 58 | 59 | // Create projection matrix. 60 | let aspectRatio = Float(frame.size.width) / Float(frame.size.height) 61 | projectionMatrix = Matrix4.perspectiveMatrix(fov: Float.pi / 4.0, aspect: aspectRatio, near: 0.1, far: 200.0) 62 | 63 | // Remove existing tracking area if necessary. 64 | if trackingArea != nil { 65 | removeTrackingArea(trackingArea!) 66 | } 67 | 68 | // Create new tracking area. 69 | let options: NSTrackingArea.Options = [NSTrackingArea.Options.mouseMoved, NSTrackingArea.Options.activeWhenFirstResponder] 70 | trackingArea = NSTrackingArea(rect: frame, options: options, owner: self, userInfo: nil) 71 | } 72 | 73 | override var acceptsFirstResponder: Bool { 74 | return true 75 | } 76 | 77 | override func keyDown(with theEvent: NSEvent) { 78 | // Close the window when the escape key is pressed. 79 | if theEvent.keyCode == 0x35 { 80 | window?.close() 81 | } 82 | } 83 | 84 | func flush() 85 | { 86 | self.openGLContext?.flushBuffer() 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /macOS/shader.fs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010-2012 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #version 150 27 | 28 | const int NUM_LIGHTS = 3; 29 | const vec3 AMBIENT = vec3(0.1, 0.1, 0.1); 30 | const float MAX_DIST = 2.5; 31 | const float MAX_DIST_SQUARED = MAX_DIST * MAX_DIST; 32 | 33 | uniform sampler2D normalmap; 34 | uniform vec3 lightColor[NUM_LIGHTS]; 35 | 36 | in vec2 fragmentTexCoords; 37 | in vec3 cameraVector; 38 | in vec3 lightVector[NUM_LIGHTS]; 39 | 40 | out vec4 fragmentColor; 41 | 42 | void 43 | main() 44 | { 45 | // initialize diffuse/specular lighting 46 | vec3 diffuse = vec3(0.0, 0.0, 0.0); 47 | vec3 specular = vec3(0.0, 0.0, 0.0); 48 | 49 | // get the fragment normal and camera direction 50 | vec3 fragmentNormal = (texture(normalmap, fragmentTexCoords).rgb * 2.0) - 1.0; 51 | vec3 normal = normalize(fragmentNormal); 52 | vec3 cameraDir = normalize(cameraVector); 53 | 54 | // loop through each light 55 | for(int i = 0; i < NUM_LIGHTS; ++i) { 56 | // calculate distance between 0.0 and 1.0 57 | float dist = min(dot(lightVector[i], lightVector[i]), MAX_DIST_SQUARED) / MAX_DIST_SQUARED; 58 | float distFactor = 1.0 - dist; 59 | 60 | // diffuse 61 | vec3 lightDir = normalize(lightVector[i]); 62 | float diffuseDot = dot(normal, lightDir); 63 | diffuse += lightColor[i] * clamp(diffuseDot, 0.0, 1.0) * distFactor; 64 | 65 | // specular 66 | vec3 halfAngle = normalize(cameraDir + lightDir); 67 | vec3 specularColor = min(lightColor[i] + 0.5, 1.0); 68 | float specularDot = dot(normal, halfAngle); 69 | specular += specularColor * pow(clamp(specularDot, 0.0, 1.0), 16.0) * distFactor; 70 | } 71 | 72 | vec4 sample = vec4(1.0, 1.0, 1.0, 1.0); 73 | fragmentColor = vec4(clamp(sample.rgb * (diffuse + AMBIENT) + specular, 0.0, 1.0), sample.a); 74 | } -------------------------------------------------------------------------------- /macOS/shader.vs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010-2012 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #version 150 27 | 28 | const int NUM_LIGHTS = 3; 29 | 30 | uniform mat4 projectionMatrix; 31 | uniform mat4 modelviewMatrix; 32 | 33 | uniform vec3 cameraPosition; 34 | uniform vec3 lightPosition[NUM_LIGHTS]; 35 | 36 | in vec3 vertexPosition; 37 | in vec2 vertexTexCoords; 38 | in vec3 vertexTangent; 39 | in vec3 vertexBitangent; 40 | in vec3 vertexNormal; 41 | 42 | out vec2 fragmentTexCoords; 43 | out vec3 cameraVector; 44 | out vec3 lightVector[NUM_LIGHTS]; 45 | 46 | void 47 | main() 48 | { 49 | mat3 tangentSpace = mat3(vertexTangent, vertexBitangent, vertexNormal); 50 | 51 | // set the vector from the vertex to the camera 52 | cameraVector = (cameraPosition - vertexPosition.xyz) * tangentSpace; 53 | 54 | // set the vectors from the vertex to each light 55 | for(int i = 0; i < NUM_LIGHTS; ++i) 56 | lightVector[i] = (lightPosition[i] - vertexPosition.xyz) * tangentSpace; 57 | 58 | // output the transformed vertex 59 | fragmentTexCoords = vertexTexCoords; 60 | gl_Position = (projectionMatrix * modelviewMatrix) * vec4(vertexPosition, 1.0); 61 | } 62 | -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "version" : 1, 14 | "author" : "xcode" 15 | } 16 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "layers" : [ 3 | { 4 | "filename" : "Front.imagestacklayer" 5 | }, 6 | { 7 | "filename" : "Middle.imagestacklayer" 8 | }, 9 | { 10 | "filename" : "Back.imagestacklayer" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "version" : 1, 14 | "author" : "xcode" 15 | } 16 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "version" : 1, 14 | "author" : "xcode" 15 | } 16 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "version" : 1, 14 | "author" : "xcode" 15 | } 16 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "layers" : [ 3 | { 4 | "filename" : "Front.imagestacklayer" 5 | }, 6 | { 7 | "filename" : "Middle.imagestacklayer" 8 | }, 9 | { 10 | "filename" : "Back.imagestacklayer" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "version" : 1, 14 | "author" : "xcode" 15 | } 16 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "version" : 1, 14 | "author" : "xcode" 15 | } 16 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets" : [ 3 | { 4 | "size" : "1280x768", 5 | "idiom" : "tv", 6 | "filename" : "App Icon - App Store.imagestack", 7 | "role" : "primary-app-icon" 8 | }, 9 | { 10 | "size" : "400x240", 11 | "idiom" : "tv", 12 | "filename" : "App Icon.imagestack", 13 | "role" : "primary-app-icon" 14 | }, 15 | { 16 | "size" : "2320x720", 17 | "idiom" : "tv", 18 | "filename" : "Top Shelf Image Wide.imageset", 19 | "role" : "top-shelf-image-wide" 20 | }, 21 | { 22 | "size" : "1920x720", 23 | "idiom" : "tv", 24 | "filename" : "Top Shelf Image.imageset", 25 | "role" : "top-shelf-image" 26 | } 27 | ], 28 | "info" : { 29 | "version" : 1, 30 | "author" : "xcode" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "version" : 1, 14 | "author" : "xcode" 15 | } 16 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "version" : 1, 14 | "author" : "xcode" 15 | } 16 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /tvOS/Assets.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "landscape", 5 | "idiom" : "tv", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "11.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "landscape", 12 | "idiom" : "tv", 13 | "extent" : "full-screen", 14 | "minimum-system-version" : "9.0", 15 | "scale" : "1x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /tvOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIMainStoryboardFile 24 | Main 25 | UIRequiredDeviceCapabilities 26 | 27 | arm64 28 | 29 | UIUserInterfaceStyle 30 | Automatic 31 | 32 | 33 | --------------------------------------------------------------------------------