├── .gitignore ├── 2DDrawing ├── Star │ ├── Star.xcodeproj │ │ └── project.pbxproj │ └── Star │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── GameViewController.swift │ │ ├── Info.plist │ │ ├── Shaders.metal │ │ └── vertices.swift └── StarVertices.txt ├── HelloTriangle ├── HelloMetal.xcodeproj │ └── project.pbxproj └── HelloMetal │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── Shaders.metal │ └── ViewController.swift ├── README.md └── Shaders:ModelIO ├── TeapotLighting.xcodeproj └── project.pbxproj └── TeapotLighting ├── AppDelegate.swift ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── GameViewController.swift ├── GeometricTypes.swift ├── Info.plist ├── Lighting.metal ├── Uniforms.swift └── wt_teapot.obj /.gitignore: -------------------------------------------------------------------------------- 1 | # Exclude the build directory 2 | build/* 3 | examples/FilterShowcase/build* 4 | 5 | # Exclude temp nibs and swap files 6 | *~.nib 7 | *.swp 8 | 9 | # Exclude OS X folder attributes 10 | .DS_Store 11 | .svn 12 | 13 | # Exclude user-specific XCode 3 and 4 files 14 | *.mode1 15 | *.mode1v3 16 | *.mode2v3 17 | *.perspective 18 | *.perspectivev3 19 | *.pbxuser 20 | *.xcworkspace 21 | xcuserdata 22 | 23 | # Documentation 24 | documentation/* 25 | 26 | -------------------------------------------------------------------------------- /2DDrawing/Star/Star.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 793688341DC7CEA800805279 /* vertices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 793688331DC7CEA800805279 /* vertices.swift */; }; 11 | 7989D70C1DC52453003AEA03 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7989D70B1DC52453003AEA03 /* Metal.framework */; }; 12 | 7989D70E1DC52453003AEA03 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7989D70D1DC52453003AEA03 /* MetalKit.framework */; }; 13 | 7989D7101DC52453003AEA03 /* ModelIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7989D70F1DC52453003AEA03 /* ModelIO.framework */; }; 14 | 7989D7131DC52453003AEA03 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7989D7121DC52453003AEA03 /* AppDelegate.swift */; }; 15 | 7989D7151DC52453003AEA03 /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7989D7141DC52453003AEA03 /* GameViewController.swift */; }; 16 | 7989D7171DC52453003AEA03 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 7989D7161DC52453003AEA03 /* Shaders.metal */; }; 17 | 7989D71A1DC52453003AEA03 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7989D7181DC52453003AEA03 /* Main.storyboard */; }; 18 | 7989D71C1DC52453003AEA03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7989D71B1DC52453003AEA03 /* Assets.xcassets */; }; 19 | 7989D71F1DC52453003AEA03 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7989D71D1DC52453003AEA03 /* LaunchScreen.storyboard */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 793688331DC7CEA800805279 /* vertices.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = vertices.swift; sourceTree = ""; }; 24 | 7989D7081DC52453003AEA03 /* Star.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Star.app; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | 7989D70B1DC52453003AEA03 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 26 | 7989D70D1DC52453003AEA03 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; 27 | 7989D70F1DC52453003AEA03 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = System/Library/Frameworks/ModelIO.framework; sourceTree = SDKROOT; }; 28 | 7989D7121DC52453003AEA03 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 29 | 7989D7141DC52453003AEA03 /* GameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewController.swift; sourceTree = ""; }; 30 | 7989D7161DC52453003AEA03 /* Shaders.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; 31 | 7989D7191DC52453003AEA03 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 32 | 7989D71B1DC52453003AEA03 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 33 | 7989D71E1DC52453003AEA03 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 34 | 7989D7201DC52453003AEA03 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | 7989D7051DC52453003AEA03 /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | 7989D7101DC52453003AEA03 /* ModelIO.framework in Frameworks */, 43 | 7989D70C1DC52453003AEA03 /* Metal.framework in Frameworks */, 44 | 7989D70E1DC52453003AEA03 /* MetalKit.framework in Frameworks */, 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | 7989D6FF1DC52453003AEA03 = { 52 | isa = PBXGroup; 53 | children = ( 54 | 7989D7111DC52453003AEA03 /* Star */, 55 | 7989D70A1DC52453003AEA03 /* Frameworks */, 56 | 7989D7091DC52453003AEA03 /* Products */, 57 | ); 58 | sourceTree = ""; 59 | }; 60 | 7989D7091DC52453003AEA03 /* Products */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 7989D7081DC52453003AEA03 /* Star.app */, 64 | ); 65 | name = Products; 66 | sourceTree = ""; 67 | }; 68 | 7989D70A1DC52453003AEA03 /* Frameworks */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 7989D70B1DC52453003AEA03 /* Metal.framework */, 72 | 7989D70D1DC52453003AEA03 /* MetalKit.framework */, 73 | 7989D70F1DC52453003AEA03 /* ModelIO.framework */, 74 | ); 75 | name = Frameworks; 76 | sourceTree = ""; 77 | }; 78 | 7989D7111DC52453003AEA03 /* Star */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 7989D7121DC52453003AEA03 /* AppDelegate.swift */, 82 | 7989D7141DC52453003AEA03 /* GameViewController.swift */, 83 | 793688331DC7CEA800805279 /* vertices.swift */, 84 | 7989D7161DC52453003AEA03 /* Shaders.metal */, 85 | 7989D7181DC52453003AEA03 /* Main.storyboard */, 86 | 7989D71B1DC52453003AEA03 /* Assets.xcassets */, 87 | 7989D71D1DC52453003AEA03 /* LaunchScreen.storyboard */, 88 | 7989D7201DC52453003AEA03 /* Info.plist */, 89 | ); 90 | path = Star; 91 | sourceTree = ""; 92 | }; 93 | /* End PBXGroup section */ 94 | 95 | /* Begin PBXNativeTarget section */ 96 | 7989D7071DC52453003AEA03 /* Star */ = { 97 | isa = PBXNativeTarget; 98 | buildConfigurationList = 7989D7231DC52453003AEA03 /* Build configuration list for PBXNativeTarget "Star" */; 99 | buildPhases = ( 100 | 7989D7041DC52453003AEA03 /* Sources */, 101 | 7989D7051DC52453003AEA03 /* Frameworks */, 102 | 7989D7061DC52453003AEA03 /* Resources */, 103 | ); 104 | buildRules = ( 105 | ); 106 | dependencies = ( 107 | ); 108 | name = Star; 109 | productName = Star; 110 | productReference = 7989D7081DC52453003AEA03 /* Star.app */; 111 | productType = "com.apple.product-type.application"; 112 | }; 113 | /* End PBXNativeTarget section */ 114 | 115 | /* Begin PBXProject section */ 116 | 7989D7001DC52453003AEA03 /* Project object */ = { 117 | isa = PBXProject; 118 | attributes = { 119 | LastSwiftUpdateCheck = 0800; 120 | LastUpgradeCheck = 0800; 121 | ORGANIZATIONNAME = RedQueenCoder; 122 | TargetAttributes = { 123 | 7989D7071DC52453003AEA03 = { 124 | CreatedOnToolsVersion = 8.0; 125 | ProvisioningStyle = Automatic; 126 | }; 127 | }; 128 | }; 129 | buildConfigurationList = 7989D7031DC52453003AEA03 /* Build configuration list for PBXProject "Star" */; 130 | compatibilityVersion = "Xcode 3.2"; 131 | developmentRegion = English; 132 | hasScannedForEncodings = 0; 133 | knownRegions = ( 134 | en, 135 | Base, 136 | ); 137 | mainGroup = 7989D6FF1DC52453003AEA03; 138 | productRefGroup = 7989D7091DC52453003AEA03 /* Products */; 139 | projectDirPath = ""; 140 | projectRoot = ""; 141 | targets = ( 142 | 7989D7071DC52453003AEA03 /* Star */, 143 | ); 144 | }; 145 | /* End PBXProject section */ 146 | 147 | /* Begin PBXResourcesBuildPhase section */ 148 | 7989D7061DC52453003AEA03 /* Resources */ = { 149 | isa = PBXResourcesBuildPhase; 150 | buildActionMask = 2147483647; 151 | files = ( 152 | 7989D71F1DC52453003AEA03 /* LaunchScreen.storyboard in Resources */, 153 | 7989D71C1DC52453003AEA03 /* Assets.xcassets in Resources */, 154 | 7989D71A1DC52453003AEA03 /* Main.storyboard in Resources */, 155 | ); 156 | runOnlyForDeploymentPostprocessing = 0; 157 | }; 158 | /* End PBXResourcesBuildPhase section */ 159 | 160 | /* Begin PBXSourcesBuildPhase section */ 161 | 7989D7041DC52453003AEA03 /* Sources */ = { 162 | isa = PBXSourcesBuildPhase; 163 | buildActionMask = 2147483647; 164 | files = ( 165 | 7989D7171DC52453003AEA03 /* Shaders.metal in Sources */, 166 | 7989D7151DC52453003AEA03 /* GameViewController.swift in Sources */, 167 | 793688341DC7CEA800805279 /* vertices.swift in Sources */, 168 | 7989D7131DC52453003AEA03 /* AppDelegate.swift in Sources */, 169 | ); 170 | runOnlyForDeploymentPostprocessing = 0; 171 | }; 172 | /* End PBXSourcesBuildPhase section */ 173 | 174 | /* Begin PBXVariantGroup section */ 175 | 7989D7181DC52453003AEA03 /* Main.storyboard */ = { 176 | isa = PBXVariantGroup; 177 | children = ( 178 | 7989D7191DC52453003AEA03 /* Base */, 179 | ); 180 | name = Main.storyboard; 181 | sourceTree = ""; 182 | }; 183 | 7989D71D1DC52453003AEA03 /* LaunchScreen.storyboard */ = { 184 | isa = PBXVariantGroup; 185 | children = ( 186 | 7989D71E1DC52453003AEA03 /* Base */, 187 | ); 188 | name = LaunchScreen.storyboard; 189 | sourceTree = ""; 190 | }; 191 | /* End PBXVariantGroup section */ 192 | 193 | /* Begin XCBuildConfiguration section */ 194 | 7989D7211DC52453003AEA03 /* Debug */ = { 195 | isa = XCBuildConfiguration; 196 | buildSettings = { 197 | ALWAYS_SEARCH_USER_PATHS = NO; 198 | CLANG_ANALYZER_NONNULL = YES; 199 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 200 | CLANG_CXX_LIBRARY = "libc++"; 201 | CLANG_ENABLE_MODULES = YES; 202 | CLANG_ENABLE_OBJC_ARC = YES; 203 | CLANG_WARN_BOOL_CONVERSION = YES; 204 | CLANG_WARN_CONSTANT_CONVERSION = YES; 205 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 206 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 207 | CLANG_WARN_EMPTY_BODY = YES; 208 | CLANG_WARN_ENUM_CONVERSION = YES; 209 | CLANG_WARN_INFINITE_RECURSION = YES; 210 | CLANG_WARN_INT_CONVERSION = YES; 211 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 212 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 213 | CLANG_WARN_UNREACHABLE_CODE = YES; 214 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 215 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 216 | COPY_PHASE_STRIP = NO; 217 | DEBUG_INFORMATION_FORMAT = dwarf; 218 | ENABLE_STRICT_OBJC_MSGSEND = YES; 219 | ENABLE_TESTABILITY = YES; 220 | GCC_C_LANGUAGE_STANDARD = gnu99; 221 | GCC_DYNAMIC_NO_PIC = NO; 222 | GCC_NO_COMMON_BLOCKS = YES; 223 | GCC_OPTIMIZATION_LEVEL = 0; 224 | GCC_PREPROCESSOR_DEFINITIONS = ( 225 | "DEBUG=1", 226 | "$(inherited)", 227 | ); 228 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 229 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 230 | GCC_WARN_UNDECLARED_SELECTOR = YES; 231 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 232 | GCC_WARN_UNUSED_FUNCTION = YES; 233 | GCC_WARN_UNUSED_VARIABLE = YES; 234 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 235 | MTL_ENABLE_DEBUG_INFO = YES; 236 | ONLY_ACTIVE_ARCH = YES; 237 | SDKROOT = iphoneos; 238 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 239 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 240 | }; 241 | name = Debug; 242 | }; 243 | 7989D7221DC52453003AEA03 /* Release */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | ALWAYS_SEARCH_USER_PATHS = NO; 247 | CLANG_ANALYZER_NONNULL = YES; 248 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 249 | CLANG_CXX_LIBRARY = "libc++"; 250 | CLANG_ENABLE_MODULES = YES; 251 | CLANG_ENABLE_OBJC_ARC = YES; 252 | CLANG_WARN_BOOL_CONVERSION = YES; 253 | CLANG_WARN_CONSTANT_CONVERSION = YES; 254 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 255 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 256 | CLANG_WARN_EMPTY_BODY = YES; 257 | CLANG_WARN_ENUM_CONVERSION = YES; 258 | CLANG_WARN_INFINITE_RECURSION = YES; 259 | CLANG_WARN_INT_CONVERSION = YES; 260 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 261 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 262 | CLANG_WARN_UNREACHABLE_CODE = YES; 263 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 264 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 265 | COPY_PHASE_STRIP = NO; 266 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 267 | ENABLE_NS_ASSERTIONS = NO; 268 | ENABLE_STRICT_OBJC_MSGSEND = YES; 269 | GCC_C_LANGUAGE_STANDARD = gnu99; 270 | GCC_NO_COMMON_BLOCKS = YES; 271 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 272 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 273 | GCC_WARN_UNDECLARED_SELECTOR = YES; 274 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 275 | GCC_WARN_UNUSED_FUNCTION = YES; 276 | GCC_WARN_UNUSED_VARIABLE = YES; 277 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 278 | MTL_ENABLE_DEBUG_INFO = NO; 279 | SDKROOT = iphoneos; 280 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 281 | VALIDATE_PRODUCT = YES; 282 | }; 283 | name = Release; 284 | }; 285 | 7989D7241DC52453003AEA03 /* Debug */ = { 286 | isa = XCBuildConfiguration; 287 | buildSettings = { 288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 289 | DEVELOPMENT_TEAM = ""; 290 | INFOPLIST_FILE = Star/Info.plist; 291 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 292 | PRODUCT_BUNDLE_IDENTIFIER = com.redqueencoder.Star; 293 | PRODUCT_NAME = "$(TARGET_NAME)"; 294 | SWIFT_VERSION = 3.0; 295 | }; 296 | name = Debug; 297 | }; 298 | 7989D7251DC52453003AEA03 /* Release */ = { 299 | isa = XCBuildConfiguration; 300 | buildSettings = { 301 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 302 | DEVELOPMENT_TEAM = ""; 303 | INFOPLIST_FILE = Star/Info.plist; 304 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 305 | PRODUCT_BUNDLE_IDENTIFIER = com.redqueencoder.Star; 306 | PRODUCT_NAME = "$(TARGET_NAME)"; 307 | SWIFT_VERSION = 3.0; 308 | }; 309 | name = Release; 310 | }; 311 | /* End XCBuildConfiguration section */ 312 | 313 | /* Begin XCConfigurationList section */ 314 | 7989D7031DC52453003AEA03 /* Build configuration list for PBXProject "Star" */ = { 315 | isa = XCConfigurationList; 316 | buildConfigurations = ( 317 | 7989D7211DC52453003AEA03 /* Debug */, 318 | 7989D7221DC52453003AEA03 /* Release */, 319 | ); 320 | defaultConfigurationIsVisible = 0; 321 | defaultConfigurationName = Release; 322 | }; 323 | 7989D7231DC52453003AEA03 /* Build configuration list for PBXNativeTarget "Star" */ = { 324 | isa = XCConfigurationList; 325 | buildConfigurations = ( 326 | 7989D7241DC52453003AEA03 /* Debug */, 327 | 7989D7251DC52453003AEA03 /* Release */, 328 | ); 329 | defaultConfigurationIsVisible = 0; 330 | defaultConfigurationName = Release; 331 | }; 332 | /* End XCConfigurationList section */ 333 | }; 334 | rootObject = 7989D7001DC52453003AEA03 /* Project object */; 335 | } 336 | -------------------------------------------------------------------------------- /2DDrawing/Star/Star/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Star 4 | // 5 | // Created by Janie Clayton on 10/29/16. 6 | // Copyright © 2017 RedQueenCoder. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /2DDrawing/Star/Star/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /2DDrawing/Star/Star/Base.lproj/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 | -------------------------------------------------------------------------------- /2DDrawing/Star/Star/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 | -------------------------------------------------------------------------------- /2DDrawing/Star/Star/GameViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.swift 3 | // Star 4 | // 5 | // Created by Janie Clayton on 10/29/16. 6 | // Copyright © 2017 RedQueenCoder. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Metal 11 | import MetalKit 12 | 13 | let MaxBuffers = 3 14 | let ConstantBufferSize = 2048*1024 15 | 16 | class GameViewController:UIViewController, MTKViewDelegate { 17 | 18 | // Properties 19 | var device: MTLDevice! = nil 20 | var commandQueue: MTLCommandQueue! = nil 21 | var pipelineState: MTLRenderPipelineState! = nil 22 | var vertexBuffer: MTLBuffer! = nil 23 | var vertexColorBuffer: MTLBuffer! = nil 24 | let inflightSemaphore = DispatchSemaphore(value: MaxBuffers) 25 | var bufferIndex = 0 26 | 27 | override func viewDidLoad() { 28 | 29 | super.viewDidLoad() 30 | 31 | // Create device 32 | device = MTLCreateSystemDefaultDevice() 33 | guard device != nil else { // Fallback to a blank UIView, an application could also fallback to OpenGL ES here. 34 | print("Metal is not supported on this device") 35 | self.view = UIView(frame: self.view.frame) 36 | return 37 | } 38 | 39 | // setup view properties 40 | let view = self.view as! MTKView 41 | view.device = device 42 | view.delegate = self 43 | 44 | loadAssets() 45 | } 46 | 47 | func loadAssets() { 48 | // load any resources required for rendering 49 | let view = self.view as! MTKView 50 | commandQueue = device.makeCommandQueue() 51 | commandQueue.label = "main command queue" 52 | 53 | // Create library for project 54 | let defaultLibrary = device.newDefaultLibrary()! 55 | let fragmentProgram = defaultLibrary.makeFunction(name: "passThroughFragment")! 56 | let vertexProgram = defaultLibrary.makeFunction(name: "passThroughVertex")! 57 | 58 | // Create render pipeline descriptor 59 | let pipelineStateDescriptor = MTLRenderPipelineDescriptor() 60 | pipelineStateDescriptor.vertexFunction = vertexProgram 61 | pipelineStateDescriptor.fragmentFunction = fragmentProgram 62 | pipelineStateDescriptor.colorAttachments[0].pixelFormat = view.colorPixelFormat 63 | pipelineStateDescriptor.sampleCount = view.sampleCount 64 | 65 | do { 66 | try pipelineState = device.makeRenderPipelineState(descriptor: pipelineStateDescriptor) 67 | } catch let error { 68 | print("Failed to create pipeline state, error \(error)") 69 | } 70 | 71 | // Layout memory and set up vertex buffers 72 | let dataSize = vertexData.count * MemoryLayout.size 73 | vertexBuffer = device.makeBuffer(bytes: vertexData, length: dataSize, options: []) 74 | vertexBuffer.label = "vertices" 75 | 76 | vertexColorBuffer = device.makeBuffer(bytes: vertexColorData, length: dataSize, options: []) 77 | vertexColorBuffer.label = "colors" 78 | } 79 | 80 | func update() { 81 | // Perform any work that must be done on every frame update, such as animation 82 | } 83 | 84 | func draw(in view: MTKView) { 85 | 86 | // use semaphore to encode 3 frames ahead 87 | let _ = inflightSemaphore.wait(timeout: DispatchTime.distantFuture) 88 | let commandBuffer = commandQueue.makeCommandBuffer() 89 | commandBuffer.label = "Frame command buffer" 90 | 91 | // use completion handler to signal the semaphore when this frame is completed allowing the encoding of the next frame to proceed 92 | // use capture list to avoid any retain cycles if the command buffer gets retained anywhere besides this stack frame 93 | commandBuffer.addCompletedHandler{ [weak self] commandBuffer in 94 | if let strongSelf = self { 95 | strongSelf.inflightSemaphore.signal() 96 | } 97 | return 98 | } 99 | 100 | if let renderPassDescriptor = view.currentRenderPassDescriptor, let currentDrawable = view.currentDrawable { 101 | let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) 102 | renderEncoder.label = "render encoder" 103 | 104 | renderEncoder.pushDebugGroup("draw star") 105 | renderEncoder.setRenderPipelineState(pipelineState) 106 | 107 | renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, at: 0) 108 | renderEncoder.setVertexBuffer(vertexColorBuffer, offset:0 , at: 1) 109 | renderEncoder.drawPrimitives(type: .triangle, 110 | vertexStart: 0, 111 | vertexCount: vertexData.count) 112 | 113 | renderEncoder.popDebugGroup() 114 | renderEncoder.endEncoding() 115 | 116 | commandBuffer.present(currentDrawable) 117 | } 118 | 119 | // bufferIndex matches the current semaphore controled frame index to ensure writing occurs at the correct region in the vertex buffer 120 | bufferIndex = (bufferIndex + 1) % MaxBuffers 121 | 122 | commandBuffer.commit() 123 | } 124 | 125 | 126 | func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { 127 | 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /2DDrawing/Star/Star/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 | metal 31 | 32 | UIStatusBarHidden 33 | 34 | UISupportedInterfaceOrientations 35 | 36 | UIInterfaceOrientationPortrait 37 | UIInterfaceOrientationLandscapeLeft 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /2DDrawing/Star/Star/Shaders.metal: -------------------------------------------------------------------------------- 1 | // 2 | // Shaders.metal 3 | // Star 4 | // 5 | // Created by Janie Clayton on 10/29/16. 6 | // Copyright © 2017 RedQueenCoder. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | using namespace metal; 12 | 13 | struct VertexInOut 14 | { 15 | float4 position [[position]]; 16 | float4 color; 17 | }; 18 | 19 | vertex VertexInOut passThroughVertex(uint vid [[ vertex_id ]], 20 | constant packed_float4* position [[ buffer(0) ]], 21 | constant packed_float4* color [[ buffer(1) ]]) 22 | { 23 | VertexInOut outVertex; 24 | 25 | outVertex.position = position[vid]; 26 | outVertex.color = color[vid]; 27 | 28 | return outVertex; 29 | }; 30 | 31 | fragment half4 passThroughFragment(VertexInOut inFrag [[stage_in]]) 32 | { 33 | return half4(inFrag.color); 34 | }; 35 | -------------------------------------------------------------------------------- /2DDrawing/Star/Star/vertices.swift: -------------------------------------------------------------------------------- 1 | // 2 | // vertices.swift 3 | // Star 4 | // 5 | // Created by Janie Clayton on 10/31/16. 6 | // Copyright © 2017 RedQueenCoder. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | let vertexData:[Float] = 12 | [ 13 | // Internal Triangles 14 | 0.0, 0.0, 0.0, 1.0, 15 | -0.2, 0.2, 0.0, 1.0, 16 | 0.2, 0.2, 0.0, 1.0, 17 | 18 | 0.0, 0.0, 0.0, 1.0, 19 | 0.2, 0.2, 0.0, 1.0, 20 | 0.3, 0.0, 0.0, 1.0, 21 | 22 | 0.0, 0.0, 0.0, 1.0, 23 | 0.3, 0.0, 0.0, 1.0, 24 | 0.0, -0.2, 0.0, 1.0, 25 | 26 | 0.0, 0.0, 0.0, 1.0, 27 | 0.0, -0.2, 0.0, 1.0, 28 | -0.3, 0.0, 0.0, 1.0, 29 | 30 | 0.0, 0.0, 0.0, 1.0, 31 | -0.3, 0.0, 0.0, 1.0, 32 | -0.2, 0.2, 0.0, 1.0, 33 | 34 | // External Triangles 35 | 0.0, 0.6, 0.0, 1.0, 36 | -0.2, 0.2, 0.0, 1.0, 37 | 0.2, 0.2, 0.0, 1.0, 38 | 39 | 0.6, 0.2, 0.0, 1.0, 40 | 0.2, 0.2, 0.0, 1.0, 41 | 0.3, 0.0, 0.0, 1.0, 42 | 43 | 0.6, -0.4, 0.0, 1.0, 44 | 0.0, -0.2, 0.0, 1.0, 45 | 0.3, 0.0, 0.0, 1.0, 46 | 47 | -0.6, -0.4, 0.0, 1.0, 48 | 0.0, -0.2, 0.0, 1.0, 49 | -0.3, 0.0, 0.0, 1.0, 50 | 51 | -0.6, 0.2, 0.0, 1.0, 52 | -0.2, 0.2, 0.0, 1.0, 53 | -0.3, 0.0, 0.0, 1.0 54 | ] 55 | 56 | let vertexColorData:[Float] = 57 | [ 58 | // Internal Triangles 59 | 1.0, 1.0, 1.0, 1.0, 60 | 1.0, 1.0, 1.0, 1.0, 61 | 1.0, 1.0, 1.0, 1.0, 62 | 63 | 1.0, 1.0, 1.0, 1.0, 64 | 1.0, 1.0, 1.0, 1.0, 65 | 1.0, 1.0, 1.0, 1.0, 66 | 67 | 1.0, 1.0, 1.0, 1.0, 68 | 1.0, 1.0, 1.0, 1.0, 69 | 1.0, 1.0, 1.0, 1.0, 70 | 71 | 1.0, 1.0, 1.0, 1.0, 72 | 1.0, 1.0, 1.0, 1.0, 73 | 1.0, 1.0, 1.0, 1.0, 74 | 75 | 1.0, 1.0, 1.0, 1.0, 76 | 1.0, 1.0, 1.0, 1.0, 77 | 1.0, 1.0, 1.0, 1.0, 78 | 79 | // External Triangles 80 | 1.0, 0.0, 0.0, 1.0, 81 | 1.0, 1.0, 1.0, 1.0, 82 | 1.0, 1.0, 1.0, 1.0, 83 | 84 | 1.0, 0.0, 0.0, 1.0, 85 | 1.0, 1.0, 1.0, 1.0, 86 | 1.0, 1.0, 1.0, 1.0, 87 | 88 | 1.0, 0.0, 0.0, 1.0, 89 | 1.0, 1.0, 1.0, 1.0, 90 | 1.0, 1.0, 1.0, 1.0, 91 | 92 | 1.0, 0.0, 0.0, 1.0, 93 | 1.0, 1.0, 1.0, 1.0, 94 | 1.0, 1.0, 1.0, 1.0, 95 | 96 | 1.0, 0.0, 0.0, 1.0, 97 | 1.0, 1.0, 1.0, 1.0, 98 | 1.0, 1.0, 1.0, 1.0 99 | ] 100 | -------------------------------------------------------------------------------- /2DDrawing/StarVertices.txt: -------------------------------------------------------------------------------- 1 | {0, 0.2, 0, 1} 2 | {0.1, 0.1, 0, 1} 3 | {0.2, 0.05, 0, 1} 4 | {0.1, 0, 0, 1} 5 | {0.2, -0.1, 0, 1} 6 | {0, 0, 0, 1} 7 | {-0.2, -0.1, 0, 1} 8 | {-0.1, 0, 0, 1} 9 | {-0.2, 0.05, 0, 1} 10 | {-0.1, 0.1, 0, 1} 11 | 12 | 13 | https://www.opengl.org/discussion_boards/showthread.php/171893-Draw-a-star -------------------------------------------------------------------------------- /HelloTriangle/HelloMetal.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7932A9921C2F67B200EB6811 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7932A9911C2F67B200EB6811 /* AppDelegate.swift */; }; 11 | 7932A9941C2F67B200EB6811 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7932A9931C2F67B200EB6811 /* ViewController.swift */; }; 12 | 7932A9971C2F67B200EB6811 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7932A9951C2F67B200EB6811 /* Main.storyboard */; }; 13 | 7932A9991C2F67B200EB6811 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7932A9981C2F67B200EB6811 /* Assets.xcassets */; }; 14 | 7932A99C1C2F67B200EB6811 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7932A99A1C2F67B200EB6811 /* LaunchScreen.storyboard */; }; 15 | 7932A9A41C2F6E8C00EB6811 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 7932A9A31C2F6E8C00EB6811 /* Shaders.metal */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 7932A98E1C2F67B200EB6811 /* HelloMetal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloMetal.app; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | 7932A9911C2F67B200EB6811 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 21 | 7932A9931C2F67B200EB6811 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 22 | 7932A9961C2F67B200EB6811 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 23 | 7932A9981C2F67B200EB6811 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 24 | 7932A99B1C2F67B200EB6811 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 25 | 7932A99D1C2F67B200EB6811 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 26 | 7932A9A31C2F6E8C00EB6811 /* Shaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Shaders.metal; sourceTree = ""; }; 27 | /* End PBXFileReference section */ 28 | 29 | /* Begin PBXFrameworksBuildPhase section */ 30 | 7932A98B1C2F67B200EB6811 /* Frameworks */ = { 31 | isa = PBXFrameworksBuildPhase; 32 | buildActionMask = 2147483647; 33 | files = ( 34 | ); 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXFrameworksBuildPhase section */ 38 | 39 | /* Begin PBXGroup section */ 40 | 7932A9851C2F67B200EB6811 = { 41 | isa = PBXGroup; 42 | children = ( 43 | 7932A9901C2F67B200EB6811 /* HelloMetal */, 44 | 7932A98F1C2F67B200EB6811 /* Products */, 45 | ); 46 | sourceTree = ""; 47 | }; 48 | 7932A98F1C2F67B200EB6811 /* Products */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | 7932A98E1C2F67B200EB6811 /* HelloMetal.app */, 52 | ); 53 | name = Products; 54 | sourceTree = ""; 55 | }; 56 | 7932A9901C2F67B200EB6811 /* HelloMetal */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 7932A9911C2F67B200EB6811 /* AppDelegate.swift */, 60 | 7932A9931C2F67B200EB6811 /* ViewController.swift */, 61 | 7932A9A31C2F6E8C00EB6811 /* Shaders.metal */, 62 | 7932A9951C2F67B200EB6811 /* Main.storyboard */, 63 | 7932A9981C2F67B200EB6811 /* Assets.xcassets */, 64 | 7932A99A1C2F67B200EB6811 /* LaunchScreen.storyboard */, 65 | 7932A99D1C2F67B200EB6811 /* Info.plist */, 66 | ); 67 | path = HelloMetal; 68 | sourceTree = ""; 69 | }; 70 | /* End PBXGroup section */ 71 | 72 | /* Begin PBXNativeTarget section */ 73 | 7932A98D1C2F67B200EB6811 /* HelloMetal */ = { 74 | isa = PBXNativeTarget; 75 | buildConfigurationList = 7932A9A01C2F67B200EB6811 /* Build configuration list for PBXNativeTarget "HelloMetal" */; 76 | buildPhases = ( 77 | 7932A98A1C2F67B200EB6811 /* Sources */, 78 | 7932A98B1C2F67B200EB6811 /* Frameworks */, 79 | 7932A98C1C2F67B200EB6811 /* Resources */, 80 | ); 81 | buildRules = ( 82 | ); 83 | dependencies = ( 84 | ); 85 | name = HelloMetal; 86 | productName = HelloMetal; 87 | productReference = 7932A98E1C2F67B200EB6811 /* HelloMetal.app */; 88 | productType = "com.apple.product-type.application"; 89 | }; 90 | /* End PBXNativeTarget section */ 91 | 92 | /* Begin PBXProject section */ 93 | 7932A9861C2F67B200EB6811 /* Project object */ = { 94 | isa = PBXProject; 95 | attributes = { 96 | LastSwiftUpdateCheck = 0720; 97 | LastUpgradeCheck = 0920; 98 | ORGANIZATIONNAME = "Red Queen Coder"; 99 | TargetAttributes = { 100 | 7932A98D1C2F67B200EB6811 = { 101 | CreatedOnToolsVersion = 7.0; 102 | }; 103 | }; 104 | }; 105 | buildConfigurationList = 7932A9891C2F67B200EB6811 /* Build configuration list for PBXProject "HelloMetal" */; 106 | compatibilityVersion = "Xcode 3.2"; 107 | developmentRegion = English; 108 | hasScannedForEncodings = 0; 109 | knownRegions = ( 110 | en, 111 | Base, 112 | ); 113 | mainGroup = 7932A9851C2F67B200EB6811; 114 | productRefGroup = 7932A98F1C2F67B200EB6811 /* Products */; 115 | projectDirPath = ""; 116 | projectRoot = ""; 117 | targets = ( 118 | 7932A98D1C2F67B200EB6811 /* HelloMetal */, 119 | ); 120 | }; 121 | /* End PBXProject section */ 122 | 123 | /* Begin PBXResourcesBuildPhase section */ 124 | 7932A98C1C2F67B200EB6811 /* Resources */ = { 125 | isa = PBXResourcesBuildPhase; 126 | buildActionMask = 2147483647; 127 | files = ( 128 | 7932A99C1C2F67B200EB6811 /* LaunchScreen.storyboard in Resources */, 129 | 7932A9991C2F67B200EB6811 /* Assets.xcassets in Resources */, 130 | 7932A9971C2F67B200EB6811 /* Main.storyboard in Resources */, 131 | ); 132 | runOnlyForDeploymentPostprocessing = 0; 133 | }; 134 | /* End PBXResourcesBuildPhase section */ 135 | 136 | /* Begin PBXSourcesBuildPhase section */ 137 | 7932A98A1C2F67B200EB6811 /* Sources */ = { 138 | isa = PBXSourcesBuildPhase; 139 | buildActionMask = 2147483647; 140 | files = ( 141 | 7932A9A41C2F6E8C00EB6811 /* Shaders.metal in Sources */, 142 | 7932A9941C2F67B200EB6811 /* ViewController.swift in Sources */, 143 | 7932A9921C2F67B200EB6811 /* AppDelegate.swift in Sources */, 144 | ); 145 | runOnlyForDeploymentPostprocessing = 0; 146 | }; 147 | /* End PBXSourcesBuildPhase section */ 148 | 149 | /* Begin PBXVariantGroup section */ 150 | 7932A9951C2F67B200EB6811 /* Main.storyboard */ = { 151 | isa = PBXVariantGroup; 152 | children = ( 153 | 7932A9961C2F67B200EB6811 /* Base */, 154 | ); 155 | name = Main.storyboard; 156 | sourceTree = ""; 157 | }; 158 | 7932A99A1C2F67B200EB6811 /* LaunchScreen.storyboard */ = { 159 | isa = PBXVariantGroup; 160 | children = ( 161 | 7932A99B1C2F67B200EB6811 /* Base */, 162 | ); 163 | name = LaunchScreen.storyboard; 164 | sourceTree = ""; 165 | }; 166 | /* End PBXVariantGroup section */ 167 | 168 | /* Begin XCBuildConfiguration section */ 169 | 7932A99E1C2F67B200EB6811 /* Debug */ = { 170 | isa = XCBuildConfiguration; 171 | buildSettings = { 172 | ALWAYS_SEARCH_USER_PATHS = NO; 173 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 174 | CLANG_CXX_LIBRARY = "libc++"; 175 | CLANG_ENABLE_MODULES = YES; 176 | CLANG_ENABLE_OBJC_ARC = YES; 177 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 178 | CLANG_WARN_BOOL_CONVERSION = YES; 179 | CLANG_WARN_COMMA = YES; 180 | CLANG_WARN_CONSTANT_CONVERSION = YES; 181 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 182 | CLANG_WARN_EMPTY_BODY = YES; 183 | CLANG_WARN_ENUM_CONVERSION = YES; 184 | CLANG_WARN_INFINITE_RECURSION = YES; 185 | CLANG_WARN_INT_CONVERSION = YES; 186 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 187 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 188 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 189 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 190 | CLANG_WARN_STRICT_PROTOTYPES = YES; 191 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 192 | CLANG_WARN_UNREACHABLE_CODE = YES; 193 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 194 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 195 | COPY_PHASE_STRIP = NO; 196 | DEBUG_INFORMATION_FORMAT = dwarf; 197 | ENABLE_STRICT_OBJC_MSGSEND = YES; 198 | ENABLE_TESTABILITY = YES; 199 | GCC_C_LANGUAGE_STANDARD = gnu99; 200 | GCC_DYNAMIC_NO_PIC = NO; 201 | GCC_NO_COMMON_BLOCKS = YES; 202 | GCC_OPTIMIZATION_LEVEL = 0; 203 | GCC_PREPROCESSOR_DEFINITIONS = ( 204 | "DEBUG=1", 205 | "$(inherited)", 206 | ); 207 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 208 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 209 | GCC_WARN_UNDECLARED_SELECTOR = YES; 210 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 211 | GCC_WARN_UNUSED_FUNCTION = YES; 212 | GCC_WARN_UNUSED_VARIABLE = YES; 213 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 214 | MTL_ENABLE_DEBUG_INFO = YES; 215 | ONLY_ACTIVE_ARCH = YES; 216 | SDKROOT = iphoneos; 217 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 218 | SWIFT_VERSION = 4.0; 219 | TARGETED_DEVICE_FAMILY = "1,2"; 220 | }; 221 | name = Debug; 222 | }; 223 | 7932A99F1C2F67B200EB6811 /* Release */ = { 224 | isa = XCBuildConfiguration; 225 | buildSettings = { 226 | ALWAYS_SEARCH_USER_PATHS = NO; 227 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 228 | CLANG_CXX_LIBRARY = "libc++"; 229 | CLANG_ENABLE_MODULES = YES; 230 | CLANG_ENABLE_OBJC_ARC = YES; 231 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 232 | CLANG_WARN_BOOL_CONVERSION = YES; 233 | CLANG_WARN_COMMA = YES; 234 | CLANG_WARN_CONSTANT_CONVERSION = YES; 235 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 236 | CLANG_WARN_EMPTY_BODY = YES; 237 | CLANG_WARN_ENUM_CONVERSION = YES; 238 | CLANG_WARN_INFINITE_RECURSION = YES; 239 | CLANG_WARN_INT_CONVERSION = YES; 240 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 241 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 242 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 243 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 244 | CLANG_WARN_STRICT_PROTOTYPES = YES; 245 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 246 | CLANG_WARN_UNREACHABLE_CODE = YES; 247 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 248 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 249 | COPY_PHASE_STRIP = NO; 250 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 251 | ENABLE_NS_ASSERTIONS = NO; 252 | ENABLE_STRICT_OBJC_MSGSEND = YES; 253 | GCC_C_LANGUAGE_STANDARD = gnu99; 254 | GCC_NO_COMMON_BLOCKS = YES; 255 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 256 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 257 | GCC_WARN_UNDECLARED_SELECTOR = YES; 258 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 259 | GCC_WARN_UNUSED_FUNCTION = YES; 260 | GCC_WARN_UNUSED_VARIABLE = YES; 261 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 262 | MTL_ENABLE_DEBUG_INFO = NO; 263 | SDKROOT = iphoneos; 264 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 265 | SWIFT_VERSION = 4.0; 266 | TARGETED_DEVICE_FAMILY = "1,2"; 267 | VALIDATE_PRODUCT = YES; 268 | }; 269 | name = Release; 270 | }; 271 | 7932A9A11C2F67B200EB6811 /* Debug */ = { 272 | isa = XCBuildConfiguration; 273 | buildSettings = { 274 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 275 | CLANG_ENABLE_MODULES = YES; 276 | DEVELOPMENT_TEAM = ""; 277 | INFOPLIST_FILE = HelloMetal/Info.plist; 278 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 279 | PRODUCT_BUNDLE_IDENTIFIER = com.redqueencoder.HelloMetal; 280 | PRODUCT_NAME = "$(TARGET_NAME)"; 281 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 282 | SWIFT_VERSION = 4.0; 283 | }; 284 | name = Debug; 285 | }; 286 | 7932A9A21C2F67B200EB6811 /* Release */ = { 287 | isa = XCBuildConfiguration; 288 | buildSettings = { 289 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 290 | CLANG_ENABLE_MODULES = YES; 291 | DEVELOPMENT_TEAM = ""; 292 | INFOPLIST_FILE = HelloMetal/Info.plist; 293 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 294 | PRODUCT_BUNDLE_IDENTIFIER = com.redqueencoder.HelloMetal; 295 | PRODUCT_NAME = "$(TARGET_NAME)"; 296 | SWIFT_VERSION = 4.0; 297 | }; 298 | name = Release; 299 | }; 300 | /* End XCBuildConfiguration section */ 301 | 302 | /* Begin XCConfigurationList section */ 303 | 7932A9891C2F67B200EB6811 /* Build configuration list for PBXProject "HelloMetal" */ = { 304 | isa = XCConfigurationList; 305 | buildConfigurations = ( 306 | 7932A99E1C2F67B200EB6811 /* Debug */, 307 | 7932A99F1C2F67B200EB6811 /* Release */, 308 | ); 309 | defaultConfigurationIsVisible = 0; 310 | defaultConfigurationName = Release; 311 | }; 312 | 7932A9A01C2F67B200EB6811 /* Build configuration list for PBXNativeTarget "HelloMetal" */ = { 313 | isa = XCConfigurationList; 314 | buildConfigurations = ( 315 | 7932A9A11C2F67B200EB6811 /* Debug */, 316 | 7932A9A21C2F67B200EB6811 /* Release */, 317 | ); 318 | defaultConfigurationIsVisible = 0; 319 | defaultConfigurationName = Release; 320 | }; 321 | /* End XCConfigurationList section */ 322 | }; 323 | rootObject = 7932A9861C2F67B200EB6811 /* Project object */; 324 | } 325 | -------------------------------------------------------------------------------- /HelloTriangle/HelloMetal/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // HelloMetal 4 | // 5 | // Created by Janie Clayton on 12/26/15. 6 | // Copyright © 2017 Red Queen Coder. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | private func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | return true 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /HelloTriangle/HelloMetal/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /HelloTriangle/HelloMetal/Base.lproj/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 | -------------------------------------------------------------------------------- /HelloTriangle/HelloMetal/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 | -------------------------------------------------------------------------------- /HelloTriangle/HelloMetal/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 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /HelloTriangle/HelloMetal/Shaders.metal: -------------------------------------------------------------------------------- 1 | // 2 | // Shaders.metal 3 | // HelloMetal 4 | // 5 | // Created by Janie Clayton on 12/26/15. 6 | // Copyright © 2017 Red Queen Coder. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | vertex float4 basic_vertex(const device packed_float3* vertex_array [[ buffer(0) ]], unsigned int vid [[ vertex_id ]]) { 13 | return float4(vertex_array[vid], 1.0); 14 | } 15 | 16 | fragment half4 basic_fragment(){ 17 | return half4(1.0); 18 | } 19 | -------------------------------------------------------------------------------- /HelloTriangle/HelloMetal/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // HelloMetal 4 | // 5 | // Created by Janie Clayton on 12/26/15. 6 | // Copyright © 2017 Red Queen Coder. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Metal 11 | import QuartzCore 12 | 13 | class ViewController: UIViewController { 14 | 15 | // Properties 16 | var device: MTLDevice! = nil 17 | var metalLayer: CAMetalLayer! = nil 18 | var vertexBuffer: MTLBuffer! = nil 19 | var metalPipeline: MTLRenderPipelineState! = nil 20 | var commandQueue: MTLCommandQueue! = nil 21 | var timer: CADisplayLink! = nil 22 | 23 | let vertexData:[Float] = [ 24 | 0.0, 0.5, 0.0, 25 | -1.0, -0.5, 0.0, 26 | 1.0, -0.5, 0.0 27 | ] 28 | 29 | override func viewDidLoad() { 30 | super.viewDidLoad() 31 | // Do any additional setup after loading the view, typically from a nib. 32 | device = MTLCreateSystemDefaultDevice() 33 | 34 | // Set the CAMetalLayer 35 | metalLayer = CAMetalLayer() 36 | metalLayer.device = device 37 | metalLayer.pixelFormat = .bgra8Unorm 38 | metalLayer.framebufferOnly = true 39 | metalLayer.frame = view.layer.frame 40 | view.layer.addSublayer(metalLayer) 41 | 42 | // Set the Vertex Buffer 43 | let dataSize = vertexData.count * MemoryLayout.size(ofValue: vertexData[0]) 44 | vertexBuffer = device.makeBuffer(bytes: vertexData, length: dataSize, options: []) 45 | 46 | // Set the Rendering Pipeline 47 | let defaultLibrary = device.makeDefaultLibrary() 48 | let fragmentProgram = defaultLibrary?.makeFunction(name: "basic_fragment") 49 | let vertexProgram = defaultLibrary?.makeFunction(name: "basic_vertex") 50 | 51 | let pipelineStateDescriptor = MTLRenderPipelineDescriptor() 52 | pipelineStateDescriptor.vertexFunction = vertexProgram 53 | pipelineStateDescriptor.fragmentFunction = fragmentProgram 54 | pipelineStateDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm 55 | 56 | do { 57 | try metalPipeline = device.makeRenderPipelineState(descriptor: pipelineStateDescriptor) 58 | } catch let error { 59 | print("Failed to create pipeline state, error \(error)") 60 | } 61 | 62 | // Set the Command Queue 63 | commandQueue = device.makeCommandQueue() 64 | 65 | // Set the Timer 66 | timer = CADisplayLink(target: self, selector: #selector(gameloop)) 67 | timer.add(to: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode) 68 | } 69 | 70 | override func didReceiveMemoryWarning() { 71 | super.didReceiveMemoryWarning() 72 | // Dispose of any resources that can be recreated. 73 | } 74 | 75 | func render() { 76 | let renderPassDescriptor = MTLRenderPassDescriptor() 77 | let drawable = metalLayer.nextDrawable() 78 | renderPassDescriptor.colorAttachments[0].texture = drawable!.texture 79 | renderPassDescriptor.colorAttachments[0].loadAction = .clear 80 | renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor(red: 1.0, green: 0.0, blue: 1.0, alpha: 1.0) 81 | 82 | // Create Command Buffer 83 | let commandBuffer = commandQueue.makeCommandBuffer() 84 | 85 | // Create Render Command Encoder 86 | let renderEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: renderPassDescriptor) 87 | renderEncoder?.setRenderPipelineState(metalPipeline) 88 | renderEncoder?.setVertexBuffer(vertexBuffer, offset: 0, index: 0) 89 | renderEncoder?.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1) 90 | renderEncoder?.endEncoding() 91 | 92 | // Commit the Command Buffer 93 | commandBuffer?.present(drawable!) 94 | commandBuffer?.commit() 95 | } 96 | 97 | @objc func gameloop() { 98 | autoreleasepool{ 99 | self.render() 100 | } 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Metal-Programming-Guide 2 | This is the sample code for the Metal Programming Guide. It is my intention to maintain this code for future versions of both Swift and Metal. It is also my intention to add to this repository over time. There were several conceptual chapters in the book where I did not have sample projects, such as the machine vision chapter. I would like to create accompanying projects to supplement the ones I created during the creation of this book. 3 | -------------------------------------------------------------------------------- /Shaders:ModelIO/TeapotLighting.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 79A35CF51E327C70002FEAD2 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79A35CF41E327C70002FEAD2 /* Metal.framework */; }; 11 | 79A35CF71E327C70002FEAD2 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79A35CF61E327C70002FEAD2 /* MetalKit.framework */; }; 12 | 79A35CF91E327C70002FEAD2 /* ModelIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79A35CF81E327C70002FEAD2 /* ModelIO.framework */; }; 13 | 79A35CFC1E327C70002FEAD2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79A35CFB1E327C70002FEAD2 /* AppDelegate.swift */; }; 14 | 79A35CFE1E327C70002FEAD2 /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79A35CFD1E327C70002FEAD2 /* GameViewController.swift */; }; 15 | 79A35D031E327C70002FEAD2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 79A35D011E327C70002FEAD2 /* Main.storyboard */; }; 16 | 79A35D051E327C70002FEAD2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 79A35D041E327C70002FEAD2 /* Assets.xcassets */; }; 17 | 79A35D081E327C70002FEAD2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 79A35D061E327C70002FEAD2 /* LaunchScreen.storyboard */; }; 18 | 79A35D101E327C84002FEAD2 /* wt_teapot.obj in Resources */ = {isa = PBXBuildFile; fileRef = 79A35D0F1E327C84002FEAD2 /* wt_teapot.obj */; }; 19 | 79A35D121E33BC36002FEAD2 /* Lighting.metal in Sources */ = {isa = PBXBuildFile; fileRef = 79A35D111E33BC36002FEAD2 /* Lighting.metal */; }; 20 | 79A35D141E37CB36002FEAD2 /* GeometricTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79A35D131E37CB36002FEAD2 /* GeometricTypes.swift */; }; 21 | 79A35D161E3A888B002FEAD2 /* Uniforms.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79A35D151E3A888B002FEAD2 /* Uniforms.swift */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXFileReference section */ 25 | 79A35CF11E327C70002FEAD2 /* TeapotLighting.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TeapotLighting.app; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | 79A35CF41E327C70002FEAD2 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; 27 | 79A35CF61E327C70002FEAD2 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; 28 | 79A35CF81E327C70002FEAD2 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = System/Library/Frameworks/ModelIO.framework; sourceTree = SDKROOT; }; 29 | 79A35CFB1E327C70002FEAD2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 30 | 79A35CFD1E327C70002FEAD2 /* GameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameViewController.swift; sourceTree = ""; }; 31 | 79A35D021E327C70002FEAD2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 32 | 79A35D041E327C70002FEAD2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 33 | 79A35D071E327C70002FEAD2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 34 | 79A35D091E327C70002FEAD2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 35 | 79A35D0F1E327C84002FEAD2 /* wt_teapot.obj */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = wt_teapot.obj; sourceTree = ""; }; 36 | 79A35D111E33BC36002FEAD2 /* Lighting.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Lighting.metal; sourceTree = ""; }; 37 | 79A35D131E37CB36002FEAD2 /* GeometricTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeometricTypes.swift; sourceTree = ""; }; 38 | 79A35D151E3A888B002FEAD2 /* Uniforms.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Uniforms.swift; sourceTree = ""; }; 39 | /* End PBXFileReference section */ 40 | 41 | /* Begin PBXFrameworksBuildPhase section */ 42 | 79A35CEE1E327C70002FEAD2 /* Frameworks */ = { 43 | isa = PBXFrameworksBuildPhase; 44 | buildActionMask = 2147483647; 45 | files = ( 46 | 79A35CF91E327C70002FEAD2 /* ModelIO.framework in Frameworks */, 47 | 79A35CF51E327C70002FEAD2 /* Metal.framework in Frameworks */, 48 | 79A35CF71E327C70002FEAD2 /* MetalKit.framework in Frameworks */, 49 | ); 50 | runOnlyForDeploymentPostprocessing = 0; 51 | }; 52 | /* End PBXFrameworksBuildPhase section */ 53 | 54 | /* Begin PBXGroup section */ 55 | 79A35CE81E327C70002FEAD2 = { 56 | isa = PBXGroup; 57 | children = ( 58 | 79A35CFA1E327C70002FEAD2 /* TeapotLighting */, 59 | 79A35CF31E327C70002FEAD2 /* Frameworks */, 60 | 79A35CF21E327C70002FEAD2 /* Products */, 61 | ); 62 | sourceTree = ""; 63 | }; 64 | 79A35CF21E327C70002FEAD2 /* Products */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 79A35CF11E327C70002FEAD2 /* TeapotLighting.app */, 68 | ); 69 | name = Products; 70 | sourceTree = ""; 71 | }; 72 | 79A35CF31E327C70002FEAD2 /* Frameworks */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 79A35CF41E327C70002FEAD2 /* Metal.framework */, 76 | 79A35CF61E327C70002FEAD2 /* MetalKit.framework */, 77 | 79A35CF81E327C70002FEAD2 /* ModelIO.framework */, 78 | ); 79 | name = Frameworks; 80 | sourceTree = ""; 81 | }; 82 | 79A35CFA1E327C70002FEAD2 /* TeapotLighting */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 79A35CFB1E327C70002FEAD2 /* AppDelegate.swift */, 86 | 79A35CFD1E327C70002FEAD2 /* GameViewController.swift */, 87 | 79A35D171E3A8997002FEAD2 /* DataTypes */, 88 | 79A35D111E33BC36002FEAD2 /* Lighting.metal */, 89 | 79A35D011E327C70002FEAD2 /* Main.storyboard */, 90 | 79A35D0F1E327C84002FEAD2 /* wt_teapot.obj */, 91 | 79A35D041E327C70002FEAD2 /* Assets.xcassets */, 92 | 79A35D061E327C70002FEAD2 /* LaunchScreen.storyboard */, 93 | 79A35D091E327C70002FEAD2 /* Info.plist */, 94 | ); 95 | path = TeapotLighting; 96 | sourceTree = ""; 97 | }; 98 | 79A35D171E3A8997002FEAD2 /* DataTypes */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 79A35D131E37CB36002FEAD2 /* GeometricTypes.swift */, 102 | 79A35D151E3A888B002FEAD2 /* Uniforms.swift */, 103 | ); 104 | name = DataTypes; 105 | sourceTree = ""; 106 | }; 107 | /* End PBXGroup section */ 108 | 109 | /* Begin PBXNativeTarget section */ 110 | 79A35CF01E327C70002FEAD2 /* TeapotLighting */ = { 111 | isa = PBXNativeTarget; 112 | buildConfigurationList = 79A35D0C1E327C70002FEAD2 /* Build configuration list for PBXNativeTarget "TeapotLighting" */; 113 | buildPhases = ( 114 | 79A35CED1E327C70002FEAD2 /* Sources */, 115 | 79A35CEE1E327C70002FEAD2 /* Frameworks */, 116 | 79A35CEF1E327C70002FEAD2 /* Resources */, 117 | ); 118 | buildRules = ( 119 | ); 120 | dependencies = ( 121 | ); 122 | name = TeapotLighting; 123 | productName = TeapotLighting; 124 | productReference = 79A35CF11E327C70002FEAD2 /* TeapotLighting.app */; 125 | productType = "com.apple.product-type.application"; 126 | }; 127 | /* End PBXNativeTarget section */ 128 | 129 | /* Begin PBXProject section */ 130 | 79A35CE91E327C70002FEAD2 /* Project object */ = { 131 | isa = PBXProject; 132 | attributes = { 133 | LastSwiftUpdateCheck = 0810; 134 | LastUpgradeCheck = 0810; 135 | ORGANIZATIONNAME = RedQueenCoder; 136 | TargetAttributes = { 137 | 79A35CF01E327C70002FEAD2 = { 138 | CreatedOnToolsVersion = 8.1; 139 | DevelopmentTeam = R7QEZYD6L8; 140 | ProvisioningStyle = Automatic; 141 | }; 142 | }; 143 | }; 144 | buildConfigurationList = 79A35CEC1E327C70002FEAD2 /* Build configuration list for PBXProject "TeapotLighting" */; 145 | compatibilityVersion = "Xcode 3.2"; 146 | developmentRegion = English; 147 | hasScannedForEncodings = 0; 148 | knownRegions = ( 149 | en, 150 | Base, 151 | ); 152 | mainGroup = 79A35CE81E327C70002FEAD2; 153 | productRefGroup = 79A35CF21E327C70002FEAD2 /* Products */; 154 | projectDirPath = ""; 155 | projectRoot = ""; 156 | targets = ( 157 | 79A35CF01E327C70002FEAD2 /* TeapotLighting */, 158 | ); 159 | }; 160 | /* End PBXProject section */ 161 | 162 | /* Begin PBXResourcesBuildPhase section */ 163 | 79A35CEF1E327C70002FEAD2 /* Resources */ = { 164 | isa = PBXResourcesBuildPhase; 165 | buildActionMask = 2147483647; 166 | files = ( 167 | 79A35D081E327C70002FEAD2 /* LaunchScreen.storyboard in Resources */, 168 | 79A35D101E327C84002FEAD2 /* wt_teapot.obj in Resources */, 169 | 79A35D051E327C70002FEAD2 /* Assets.xcassets in Resources */, 170 | 79A35D031E327C70002FEAD2 /* Main.storyboard in Resources */, 171 | ); 172 | runOnlyForDeploymentPostprocessing = 0; 173 | }; 174 | /* End PBXResourcesBuildPhase section */ 175 | 176 | /* Begin PBXSourcesBuildPhase section */ 177 | 79A35CED1E327C70002FEAD2 /* Sources */ = { 178 | isa = PBXSourcesBuildPhase; 179 | buildActionMask = 2147483647; 180 | files = ( 181 | 79A35D121E33BC36002FEAD2 /* Lighting.metal in Sources */, 182 | 79A35CFE1E327C70002FEAD2 /* GameViewController.swift in Sources */, 183 | 79A35D141E37CB36002FEAD2 /* GeometricTypes.swift in Sources */, 184 | 79A35D161E3A888B002FEAD2 /* Uniforms.swift in Sources */, 185 | 79A35CFC1E327C70002FEAD2 /* AppDelegate.swift in Sources */, 186 | ); 187 | runOnlyForDeploymentPostprocessing = 0; 188 | }; 189 | /* End PBXSourcesBuildPhase section */ 190 | 191 | /* Begin PBXVariantGroup section */ 192 | 79A35D011E327C70002FEAD2 /* Main.storyboard */ = { 193 | isa = PBXVariantGroup; 194 | children = ( 195 | 79A35D021E327C70002FEAD2 /* Base */, 196 | ); 197 | name = Main.storyboard; 198 | sourceTree = ""; 199 | }; 200 | 79A35D061E327C70002FEAD2 /* LaunchScreen.storyboard */ = { 201 | isa = PBXVariantGroup; 202 | children = ( 203 | 79A35D071E327C70002FEAD2 /* Base */, 204 | ); 205 | name = LaunchScreen.storyboard; 206 | sourceTree = ""; 207 | }; 208 | /* End PBXVariantGroup section */ 209 | 210 | /* Begin XCBuildConfiguration section */ 211 | 79A35D0A1E327C70002FEAD2 /* Debug */ = { 212 | isa = XCBuildConfiguration; 213 | buildSettings = { 214 | ALWAYS_SEARCH_USER_PATHS = NO; 215 | CLANG_ANALYZER_NONNULL = YES; 216 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 217 | CLANG_CXX_LIBRARY = "libc++"; 218 | CLANG_ENABLE_MODULES = YES; 219 | CLANG_ENABLE_OBJC_ARC = YES; 220 | CLANG_WARN_BOOL_CONVERSION = YES; 221 | CLANG_WARN_CONSTANT_CONVERSION = YES; 222 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 223 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 224 | CLANG_WARN_EMPTY_BODY = YES; 225 | CLANG_WARN_ENUM_CONVERSION = YES; 226 | CLANG_WARN_INFINITE_RECURSION = YES; 227 | CLANG_WARN_INT_CONVERSION = YES; 228 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 229 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 230 | CLANG_WARN_UNREACHABLE_CODE = YES; 231 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 232 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 233 | COPY_PHASE_STRIP = NO; 234 | DEBUG_INFORMATION_FORMAT = dwarf; 235 | ENABLE_STRICT_OBJC_MSGSEND = YES; 236 | ENABLE_TESTABILITY = YES; 237 | GCC_C_LANGUAGE_STANDARD = gnu99; 238 | GCC_DYNAMIC_NO_PIC = NO; 239 | GCC_NO_COMMON_BLOCKS = YES; 240 | GCC_OPTIMIZATION_LEVEL = 0; 241 | GCC_PREPROCESSOR_DEFINITIONS = ( 242 | "DEBUG=1", 243 | "$(inherited)", 244 | ); 245 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 246 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 247 | GCC_WARN_UNDECLARED_SELECTOR = YES; 248 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 249 | GCC_WARN_UNUSED_FUNCTION = YES; 250 | GCC_WARN_UNUSED_VARIABLE = YES; 251 | IPHONEOS_DEPLOYMENT_TARGET = 10.1; 252 | MTL_ENABLE_DEBUG_INFO = YES; 253 | ONLY_ACTIVE_ARCH = YES; 254 | SDKROOT = iphoneos; 255 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 256 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 257 | }; 258 | name = Debug; 259 | }; 260 | 79A35D0B1E327C70002FEAD2 /* Release */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | ALWAYS_SEARCH_USER_PATHS = NO; 264 | CLANG_ANALYZER_NONNULL = YES; 265 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 266 | CLANG_CXX_LIBRARY = "libc++"; 267 | CLANG_ENABLE_MODULES = YES; 268 | CLANG_ENABLE_OBJC_ARC = YES; 269 | CLANG_WARN_BOOL_CONVERSION = YES; 270 | CLANG_WARN_CONSTANT_CONVERSION = YES; 271 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 272 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 273 | CLANG_WARN_EMPTY_BODY = YES; 274 | CLANG_WARN_ENUM_CONVERSION = YES; 275 | CLANG_WARN_INFINITE_RECURSION = YES; 276 | CLANG_WARN_INT_CONVERSION = YES; 277 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 278 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 279 | CLANG_WARN_UNREACHABLE_CODE = YES; 280 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 281 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 282 | COPY_PHASE_STRIP = NO; 283 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 284 | ENABLE_NS_ASSERTIONS = NO; 285 | ENABLE_STRICT_OBJC_MSGSEND = YES; 286 | GCC_C_LANGUAGE_STANDARD = gnu99; 287 | GCC_NO_COMMON_BLOCKS = YES; 288 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 289 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 290 | GCC_WARN_UNDECLARED_SELECTOR = YES; 291 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 292 | GCC_WARN_UNUSED_FUNCTION = YES; 293 | GCC_WARN_UNUSED_VARIABLE = YES; 294 | IPHONEOS_DEPLOYMENT_TARGET = 10.1; 295 | MTL_ENABLE_DEBUG_INFO = NO; 296 | SDKROOT = iphoneos; 297 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 298 | VALIDATE_PRODUCT = YES; 299 | }; 300 | name = Release; 301 | }; 302 | 79A35D0D1E327C70002FEAD2 /* Debug */ = { 303 | isa = XCBuildConfiguration; 304 | buildSettings = { 305 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 306 | DEVELOPMENT_TEAM = R7QEZYD6L8; 307 | INFOPLIST_FILE = TeapotLighting/Info.plist; 308 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 309 | PRODUCT_BUNDLE_IDENTIFIER = com.redqueencoder.TeapotLighting; 310 | PRODUCT_NAME = "$(TARGET_NAME)"; 311 | SWIFT_VERSION = 3.0; 312 | }; 313 | name = Debug; 314 | }; 315 | 79A35D0E1E327C70002FEAD2 /* Release */ = { 316 | isa = XCBuildConfiguration; 317 | buildSettings = { 318 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 319 | DEVELOPMENT_TEAM = R7QEZYD6L8; 320 | INFOPLIST_FILE = TeapotLighting/Info.plist; 321 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 322 | PRODUCT_BUNDLE_IDENTIFIER = com.redqueencoder.TeapotLighting; 323 | PRODUCT_NAME = "$(TARGET_NAME)"; 324 | SWIFT_VERSION = 3.0; 325 | }; 326 | name = Release; 327 | }; 328 | /* End XCBuildConfiguration section */ 329 | 330 | /* Begin XCConfigurationList section */ 331 | 79A35CEC1E327C70002FEAD2 /* Build configuration list for PBXProject "TeapotLighting" */ = { 332 | isa = XCConfigurationList; 333 | buildConfigurations = ( 334 | 79A35D0A1E327C70002FEAD2 /* Debug */, 335 | 79A35D0B1E327C70002FEAD2 /* Release */, 336 | ); 337 | defaultConfigurationIsVisible = 0; 338 | defaultConfigurationName = Release; 339 | }; 340 | 79A35D0C1E327C70002FEAD2 /* Build configuration list for PBXNativeTarget "TeapotLighting" */ = { 341 | isa = XCConfigurationList; 342 | buildConfigurations = ( 343 | 79A35D0D1E327C70002FEAD2 /* Debug */, 344 | 79A35D0E1E327C70002FEAD2 /* Release */, 345 | ); 346 | defaultConfigurationIsVisible = 0; 347 | defaultConfigurationName = Release; 348 | }; 349 | /* End XCConfigurationList section */ 350 | }; 351 | rootObject = 79A35CE91E327C70002FEAD2 /* Project object */; 352 | } 353 | -------------------------------------------------------------------------------- /Shaders:ModelIO/TeapotLighting/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // TeapotLighting 4 | // 5 | // Created by Janie Clayton on 1/20/17. 6 | // Copyright © 2017 RedQueenCoder. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 17 | return true 18 | } 19 | 20 | } 21 | 22 | -------------------------------------------------------------------------------- /Shaders:ModelIO/TeapotLighting/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Shaders:ModelIO/TeapotLighting/Base.lproj/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 | -------------------------------------------------------------------------------- /Shaders:ModelIO/TeapotLighting/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 | -------------------------------------------------------------------------------- /Shaders:ModelIO/TeapotLighting/GameViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.swift 3 | // TeapotLighting 4 | // 5 | // Created by Janie Clayton on 1/20/17. 6 | // Copyright © 2017 RedQueenCoder. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Metal 11 | import MetalKit 12 | import simd 13 | 14 | let MaxBuffers = 3 15 | let ConstantBufferSize = 1024*1024 16 | 17 | class GameViewController:UIViewController, MTKViewDelegate { 18 | 19 | var device: MTLDevice! = nil 20 | var meshes: [MTKMesh]! 21 | var uniformBuffer: MTLBuffer! = nil 22 | var commandQueue: MTLCommandQueue! = nil 23 | let vertexDescriptor = MTLVertexDescriptor() 24 | var pipelineState: MTLRenderPipelineState! = nil 25 | var rotationAngle: Float32 = 0 26 | 27 | override func viewDidLoad() { 28 | 29 | super.viewDidLoad() 30 | 31 | device = MTLCreateSystemDefaultDevice() 32 | guard device != nil else { // Fallback to a blank UIView, an application could also fallback to OpenGL ES here. 33 | print("Metal is not supported on this device") 34 | self.view = UIView(frame: self.view.frame) 35 | return 36 | } 37 | 38 | // setup view properties 39 | let view = self.view as! MTKView 40 | view.device = device 41 | view.delegate = self 42 | 43 | loadAssets() 44 | initializeAssets() 45 | } 46 | 47 | func loadAssets() { 48 | 49 | // load any resources required for rendering 50 | let view = self.view as! MTKView 51 | commandQueue = device.makeCommandQueue() 52 | commandQueue.label = "main command queue" 53 | 54 | let defaultLibrary = device.newDefaultLibrary()! 55 | let fragmentProgram = defaultLibrary.makeFunction(name: "lightingFragment")! 56 | let vertexProgram = defaultLibrary.makeFunction(name: "lightingVertex")! 57 | 58 | 59 | vertexDescriptor.attributes[0].offset = 0 60 | vertexDescriptor.attributes[0].format = MTLVertexFormat.float3 // position 61 | vertexDescriptor.attributes[1].offset = 12 62 | vertexDescriptor.attributes[1].format = MTLVertexFormat.float3 // Vertex normal 63 | vertexDescriptor.layouts[0].stride = 24 64 | 65 | let pipelineStateDescriptor = MTLRenderPipelineDescriptor() 66 | pipelineStateDescriptor.vertexFunction = vertexProgram 67 | pipelineStateDescriptor.fragmentFunction = fragmentProgram 68 | pipelineStateDescriptor.colorAttachments[0].pixelFormat = view.colorPixelFormat 69 | pipelineStateDescriptor.sampleCount = view.sampleCount 70 | pipelineStateDescriptor.vertexDescriptor = vertexDescriptor 71 | 72 | do { 73 | try pipelineState = device.makeRenderPipelineState(descriptor: pipelineStateDescriptor) 74 | } catch let error { 75 | print("Failed to create pipeline state, error \(error)") 76 | } 77 | 78 | } 79 | 80 | func initializeAssets() { 81 | let desc = MTKModelIOVertexDescriptorFromMetal(vertexDescriptor) 82 | var attribute = desc.attributes[0] as! MDLVertexAttribute 83 | attribute.name = MDLVertexAttributePosition 84 | attribute = desc.attributes[1] as! MDLVertexAttribute 85 | attribute.name = MDLVertexAttributeNormal 86 | let mtkBufferAllocator = MTKMeshBufferAllocator(device: device!) 87 | let url = Bundle.main.url(forResource: "wt_teapot", withExtension: "obj") 88 | let asset = MDLAsset(url: url!, vertexDescriptor: desc, bufferAllocator: mtkBufferAllocator) 89 | 90 | do { 91 | meshes = try MTKMesh.newMeshes(from: asset, device: device!, sourceMeshes: nil) 92 | } 93 | catch let error { 94 | fatalError("\(error)") 95 | } 96 | 97 | // Vector Uniforms 98 | let teapotColor = float4(0.7, 0.47, 0.18, 1.0) 99 | let lightPosition = float4(5.0, 5.0, 2.0, 1.0) 100 | let reflectivity = float3(1.0, 1.0, 1.0) 101 | let intensity = float3(2.0, 2.0, 2.0) 102 | 103 | // Matrix Uniforms 104 | let yAxis = Vector4(x: 0, y: -1, z: 0, w: 0) 105 | let modelViewMatrix = Matrix4x4.rotationAboutAxis(yAxis, byAngle: rotationAngle) 106 | let aspect = Float32(self.view.bounds.width) / Float32(self.view.bounds.height) 107 | 108 | let projectionMatrix = Matrix4x4.perspectiveProjection(aspect, fieldOfViewY: 60, near: 0.1, far: 100.0) 109 | 110 | let uniform = Uniforms(lightPosition: lightPosition, color: teapotColor, reflectivity: reflectivity, lightIntensity: intensity, projectionMatrix: projectionMatrix, modelViewMatrix: modelViewMatrix) 111 | let uniforms = [uniform] 112 | uniformBuffer = device.makeBuffer(length: MemoryLayout.size, options: []) 113 | memcpy(uniformBuffer.contents(), uniforms, MemoryLayout.size) 114 | } 115 | 116 | func draw(in view: MTKView) { 117 | 118 | let commandBuffer = commandQueue.makeCommandBuffer() 119 | commandBuffer.label = "Frame command buffer" 120 | 121 | // Generate render pass descriptor 122 | if let renderPassDescriptor = view.currentRenderPassDescriptor, let currentDrawable = view.currentDrawable { 123 | let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) 124 | renderEncoder.label = "render encoder" 125 | 126 | renderEncoder.setCullMode(MTLCullMode.back) 127 | renderEncoder.pushDebugGroup("draw teapot") 128 | renderEncoder.setRenderPipelineState(pipelineState) 129 | let mesh = (meshes?.first)! 130 | let vertexBuffer = mesh.vertexBuffers[0] 131 | renderEncoder.setVertexBuffer(vertexBuffer.buffer, offset: vertexBuffer.offset, at: 0) 132 | renderEncoder.setVertexBuffer(uniformBuffer, offset:0, at:1) 133 | renderEncoder.setFragmentBuffer(uniformBuffer, offset: 0, at: 0) 134 | let submesh = mesh.submeshes.first! 135 | renderEncoder.drawIndexedPrimitives(type: submesh.primitiveType, indexCount: submesh.indexCount, indexType: submesh.indexType, indexBuffer: submesh.indexBuffer.buffer, indexBufferOffset: submesh.indexBuffer.offset) 136 | renderEncoder.popDebugGroup() 137 | renderEncoder.endEncoding() 138 | 139 | commandBuffer.present(currentDrawable) 140 | } 141 | 142 | commandBuffer.commit() 143 | } 144 | 145 | 146 | func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { 147 | 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Shaders:ModelIO/TeapotLighting/GeometricTypes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GeometricTypes.swift 3 | // SwiftMetalDemo 4 | // 5 | // Created by Warren Moore on 11/4/14. 6 | // Copyright (c) 2014 Warren Moore. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Vector4 12 | { 13 | var x: Float32 14 | var y: Float32 15 | var z: Float32 16 | var w: Float32 17 | } 18 | 19 | struct Vector3 20 | { 21 | var r: Float32 22 | var g: Float32 23 | var b: Float32 24 | } 25 | 26 | struct ColorRGBA 27 | { 28 | var r: Float32 29 | var g: Float32 30 | var b: Float32 31 | var a: Float32 32 | } 33 | 34 | struct TexCoords 35 | { 36 | var u: Float32 37 | var v: Float32 38 | } 39 | 40 | struct ColoredVertex 41 | { 42 | var position: Vector4 43 | var color: ColorRGBA 44 | } 45 | 46 | struct Vertex 47 | { 48 | var position: Vector4 49 | var normal: Vector4 50 | var texCoords: TexCoords 51 | } 52 | 53 | struct Matrix4x4 54 | { 55 | var X: Vector4 56 | var Y: Vector4 57 | var Z: Vector4 58 | var W: Vector4 59 | 60 | init() 61 | { 62 | X = Vector4(x: 1, y: 0, z: 0, w: 0) 63 | Y = Vector4(x: 0, y: 1, z: 0, w: 0) 64 | Z = Vector4(x: 0, y: 0, z: 1, w: 0) 65 | W = Vector4(x: 0, y: 0, z: 0, w: 1) 66 | } 67 | 68 | static func rotationAboutAxis(_ axis: Vector4, byAngle angle: Float32) -> Matrix4x4 69 | { 70 | var mat = Matrix4x4() 71 | 72 | let c = cos(angle) 73 | let s = sin(angle) 74 | 75 | mat.X.x = axis.x * axis.x + (1 - axis.x * axis.x) * c 76 | mat.X.y = axis.x * axis.y * (1 - c) - axis.z * s 77 | mat.X.z = axis.x * axis.z * (1 - c) + axis.y * s 78 | 79 | mat.Y.x = axis.x * axis.y * (1 - c) + axis.z * s 80 | mat.Y.y = axis.y * axis.y + (1 - axis.y * axis.y) * c 81 | mat.Y.z = axis.y * axis.z * (1 - c) - axis.x * s 82 | 83 | mat.Z.x = axis.x * axis.z * (1 - c) - axis.y * s 84 | mat.Z.y = axis.y * axis.z * (1 - c) + axis.x * s 85 | mat.Z.z = axis.z * axis.z + (1 - axis.z * axis.z) * c 86 | 87 | return mat 88 | } 89 | 90 | static func perspectiveProjection(_ aspect: Float32, fieldOfViewY: Float32, near: Float32, far: Float32) -> Matrix4x4 91 | { 92 | var mat = Matrix4x4() 93 | 94 | let fovRadians = fieldOfViewY * Float32(M_PI / 180.0) 95 | 96 | let yScale = 1 / tan(fovRadians * 0.5) 97 | let xScale = yScale / aspect 98 | let zRange = far - near 99 | let zScale = -(far + near) / zRange 100 | let wzScale = -2 * far * near / zRange 101 | 102 | mat.X.x = xScale 103 | mat.Y.y = yScale 104 | mat.Z.z = zScale 105 | mat.Z.w = -1 106 | mat.W.z = wzScale 107 | 108 | return mat; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Shaders:ModelIO/TeapotLighting/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 | metal 31 | 32 | UIStatusBarHidden 33 | 34 | UISupportedInterfaceOrientations 35 | 36 | UIInterfaceOrientationPortrait 37 | UIInterfaceOrientationLandscapeLeft 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Shaders:ModelIO/TeapotLighting/Lighting.metal: -------------------------------------------------------------------------------- 1 | // 2 | // Lighting.metal 3 | // TeapotLighting 4 | // 5 | // Created by Janie Clayton on 1/21/17. 6 | // Copyright © 2017 RedQueenCoder. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | struct VertexIn 13 | { 14 | float3 position [[attribute(0)]]; 15 | float3 normal [[attribute(1)]]; 16 | }; 17 | 18 | struct Uniforms 19 | { 20 | float4 lightPosition; 21 | float4 color; 22 | packed_float3 reflectivity; 23 | packed_float3 intensity; 24 | float4x4 modelViewMatrix; 25 | float4x4 projectionMatrix; 26 | }; 27 | 28 | struct VertexOut 29 | { 30 | float4 position [[position]]; 31 | float4 lightIntensity; 32 | }; 33 | 34 | vertex VertexOut lightingVertex(VertexIn vertexIn [[stage_in]], 35 | constant Uniforms &uniforms [[buffer(1)]]) 36 | { 37 | VertexOut outVertex; 38 | 39 | float4 position = float4(vertexIn.position, 1) + float4(0.0, 0.0, -3.0, 0.0); 40 | float4 normal = float4(vertexIn.normal, 0); 41 | 42 | float4 tnorm = normalize(uniforms.projectionMatrix * uniforms.modelViewMatrix * normal); 43 | float4 eyeCoords = uniforms.projectionMatrix * uniforms.modelViewMatrix * position; 44 | float4 s = normalize(uniforms.lightPosition - eyeCoords); 45 | 46 | outVertex.lightIntensity = float4(uniforms.intensity, 1.0) * float4(uniforms.reflectivity, 1.0) * max( dot(s, tnorm), 0.0); 47 | outVertex.position = uniforms.projectionMatrix * uniforms.modelViewMatrix * position; 48 | 49 | return outVertex; 50 | }; 51 | 52 | fragment half4 lightingFragment(VertexOut inFrag [[stage_in]], 53 | constant Uniforms &uniforms [[buffer(0)]]) 54 | { 55 | return half4(inFrag.lightIntensity * uniforms.color); 56 | }; 57 | -------------------------------------------------------------------------------- /Shaders:ModelIO/TeapotLighting/Uniforms.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Uniforms.swift 3 | // TeapotLighting 4 | // 5 | // Created by Janie Clayton on 1/26/17. 6 | // Copyright © 2017 RedQueenCoder. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import simd 11 | 12 | struct Uniforms { 13 | let lightPosition:float4 14 | let color:float4 15 | let reflectivity:float3 16 | let lightIntensity:float3 17 | let projectionMatrix:Matrix4x4 18 | let modelViewMatrix:Matrix4x4 19 | } 20 | --------------------------------------------------------------------------------