├── .gitignore ├── HelloMetal ├── HelloMetal │ ├── photo_night.jpg │ ├── VideoMetalView.m │ ├── VideoMetalView.h │ ├── AppDelegate.h │ ├── main.m │ ├── ViewController.h │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ ├── AppDelegate.m │ └── ViewController.m └── HelloMetal.xcodeproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── volvet.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ ├── xcuserdata │ └── volvet.xcuserdatad │ │ ├── xcschemes │ │ ├── xcschememanagement.plist │ │ └── HelloMetal.xcscheme │ │ └── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── project.pbxproj ├── MetalImage ├── MetalImage │ ├── Assets.xcassets │ │ ├── mandrill.imageset │ │ │ ├── mandrill.png │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── AppDelegate.h │ ├── main.m │ ├── MainBoundleTextureProvider.h │ ├── GaussianBlurFilter.h │ ├── SaturationAdjustmentFilter.h │ ├── UIImage+TextureUtility.h │ ├── IPContext.h │ ├── ViewController.h │ ├── IPContext.m │ ├── ImageFilter.h │ ├── SaturationAdjustmentFilter.m │ ├── Info.plist │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Shaders.metal │ ├── AppDelegate.m │ ├── MainBoundleTextureProvider.m │ ├── UIImage+TextureUtility.m │ ├── GaussianBlurFilter.m │ ├── ImageFilter.m │ └── ViewController.m └── MetalImage.xcodeproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── volvetzhang.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ └── volvetzhang.xcuserdatad │ └── xcschemes │ ├── xcschememanagement.plist │ └── MetalImage.xcscheme ├── Draw2d ├── Draw2d.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── volvetzhang.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── volvetzhang.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── Draw2d.xcscheme └── Draw2d │ ├── ViewController.h │ ├── AppDelegate.h │ ├── MetalView.h │ ├── main.m │ ├── Shaders.metal │ ├── ViewController.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard │ ├── AppDelegate.m │ └── MetalView.m ├── Draw3d ├── Draw3d.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── volvetzhang.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── volvetzhang.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── Draw3d.xcscheme └── Draw3d │ ├── ViewController.h │ ├── AppDelegate.h │ ├── MetalRender.h │ ├── main.m │ ├── MathUtility.h │ ├── Shader.metal │ ├── ViewController.m │ ├── MetalView.h │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard │ ├── AppDelegate.m │ ├── MathUtility.m │ ├── MetalView.m │ └── MetalRender.m ├── Teapot ├── Teapot.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── volvetzhang.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── volvetzhang.xcuserdatad │ │ ├── xcschemes │ │ ├── xcschememanagement.plist │ │ └── Teapot.xcscheme │ │ └── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist └── Teapot │ ├── ViewController.h │ ├── MetalViewRender.h │ ├── AppDelegate.h │ ├── main.m │ ├── OBJGroup.h │ ├── OBJModel.h │ ├── OBJMesh.h │ ├── typedef.h │ ├── OBJGroup.m │ ├── MathUtility.h │ ├── OBJMesh.m │ ├── ViewController.m │ ├── UIMetalView.h │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard │ ├── AppDelegate.m │ ├── shader.metal │ ├── MathUtility.m │ ├── UIMetalView.m │ ├── MetalViewRender.m │ └── OBJModel.mm ├── ClearTheScreen ├── ClearTheScreen.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ ├── volvet.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ │ └── volvetzhang.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ ├── volvet.xcuserdatad │ │ └── xcschemes │ │ │ ├── xcschememanagement.plist │ │ │ └── ClearTheScreen.xcscheme │ │ └── volvetzhang.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── ClearTheScreen.xcscheme └── ClearTheScreen │ ├── ViewController.h │ ├── MetalView.h │ ├── AppDelegate.h │ ├── main.m │ ├── ViewController.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard │ ├── MetalView.m │ └── AppDelegate.m ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /HelloMetal/HelloMetal/photo_night.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volvet/metalDemo/HEAD/HelloMetal/HelloMetal/photo_night.jpg -------------------------------------------------------------------------------- /MetalImage/MetalImage/Assets.xcassets/mandrill.imageset/mandrill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volvet/metalDemo/HEAD/MetalImage/MetalImage/Assets.xcassets/mandrill.imageset/mandrill.png -------------------------------------------------------------------------------- /Draw2d/Draw2d.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Draw3d/Draw3d.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Teapot/Teapot.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HelloMetal/HelloMetal.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MetalImage/MetalImage.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Draw2d/Draw2d.xcodeproj/project.xcworkspace/xcuserdata/volvetzhang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volvet/metalDemo/HEAD/Draw2d/Draw2d.xcodeproj/project.xcworkspace/xcuserdata/volvetzhang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Draw3d/Draw3d.xcodeproj/project.xcworkspace/xcuserdata/volvetzhang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volvet/metalDemo/HEAD/Draw3d/Draw3d.xcodeproj/project.xcworkspace/xcuserdata/volvetzhang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Teapot/Teapot.xcodeproj/project.xcworkspace/xcuserdata/volvetzhang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volvet/metalDemo/HEAD/Teapot/Teapot.xcodeproj/project.xcworkspace/xcuserdata/volvetzhang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /HelloMetal/HelloMetal.xcodeproj/project.xcworkspace/xcuserdata/volvet.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volvet/metalDemo/HEAD/HelloMetal/HelloMetal.xcodeproj/project.xcworkspace/xcuserdata/volvet.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MetalImage/MetalImage.xcodeproj/project.xcworkspace/xcuserdata/volvetzhang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volvet/metalDemo/HEAD/MetalImage/MetalImage.xcodeproj/project.xcworkspace/xcuserdata/volvetzhang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen.xcodeproj/project.xcworkspace/xcuserdata/volvet.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volvet/metalDemo/HEAD/ClearTheScreen/ClearTheScreen.xcodeproj/project.xcworkspace/xcuserdata/volvet.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen.xcodeproj/project.xcworkspace/xcuserdata/volvetzhang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volvet/metalDemo/HEAD/ClearTheScreen/ClearTheScreen.xcodeproj/project.xcworkspace/xcuserdata/volvetzhang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /HelloMetal/HelloMetal/VideoMetalView.m: -------------------------------------------------------------------------------- 1 | // 2 | // VideoMetalView.m 3 | // HelloMetal 4 | // 5 | // Created by Volvet Zhang on 16/3/5. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import "VideoMetalView.h" 10 | 11 | @implementation VideoMetalView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Draw2d/Draw2d/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // Draw2d 4 | // 5 | // Created by Volvet Zhang on 16/3/18. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Draw3d/Draw3d/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // Draw3d 4 | // 5 | // Created by Volvet Zhang on 16/3/19. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Teapot/Teapot/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/3/27. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /HelloMetal/HelloMetal/VideoMetalView.h: -------------------------------------------------------------------------------- 1 | // 2 | // VideoMetalView.h 3 | // HelloMetal 4 | // 5 | // Created by Volvet Zhang on 16/3/5. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VideoMetalView : MTKView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // ClearTheScreen 4 | // 5 | // Created by Volvet Zhang on 16/3/13. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Teapot/Teapot/MetalViewRender.h: -------------------------------------------------------------------------------- 1 | // 2 | // MentalViewRender.h 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/4/2. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UIMetalView.h" 11 | 12 | 13 | @interface MetalViewRender : NSObject 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen/MetalView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalView.h 3 | // ClearTheScreen 4 | // 5 | // Created by Volvet Zhang on 16/3/13. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | @interface MetalView : UIView 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Draw2d/Draw2d/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Draw2d 4 | // 5 | // Created by Volvet Zhang on 16/3/18. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Draw2d/Draw2d/MetalView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalView.h 3 | // Draw2d 4 | // 5 | // Created by Volvet Zhang on 16/3/18. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | @import Metal; 11 | @import QuartzCore; 12 | 13 | @interface MetalView : UIView 14 | 15 | @property (nonatomic, readonly) CAMetalLayer *mMetalLayer; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Draw3d/Draw3d/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Draw3d 4 | // 5 | // Created by Volvet Zhang on 16/3/19. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Teapot/Teapot/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/3/27. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/4/23. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /HelloMetal/HelloMetal/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // HelloMetal 4 | // 5 | // Created by Volvet Zhang on 16/3/5. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Draw3d/Draw3d/MetalRender.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalRender.h 3 | // Draw3d 4 | // 5 | // Created by Volvet Zhang on 16/3/20. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #ifndef MetalRender_h 10 | #define MetalRender_h 11 | 12 | #import "MetalView.h" 13 | 14 | @interface MetalRender : NSObject 15 | 16 | @end 17 | 18 | 19 | #endif /* MetalRender_h */ 20 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ClearTheScreen 4 | // 5 | // Created by Volvet Zhang on 16/3/13. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # metalDemo 2 | Video process demo base on metal 3 | 4 | #### ClearTheScreen 5 | Clear the view screen by MTL clear color 6 | 7 | #### Draw2d 8 | Draw triangle 9 | 10 | #### Draw3d 11 | Draw cube 12 | 13 | #### Teapot 14 | Draw teapot 15 | 16 | #### MetalImage 17 | Gaussion Blur Filter and Saturation Adjustment Filter by Metal 18 | 19 | ### Reference 20 | https://github.com/metal-by-example 21 | -------------------------------------------------------------------------------- /Draw2d/Draw2d/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Draw2d 4 | // 5 | // Created by Volvet Zhang on 16/3/18. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Draw3d/Draw3d/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Draw3d 4 | // 5 | // Created by Volvet Zhang on 16/3/19. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Teapot/Teapot/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/3/27. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/4/23. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /HelloMetal/HelloMetal/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // HelloMetal 4 | // 5 | // Created by Volvet Zhang on 16/3/5. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ClearTheScreen 4 | // 5 | // Created by Volvet Zhang on 16/3/13. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Assets.xcassets/mandrill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "mandrill.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Teapot/Teapot/OBJGroup.h: -------------------------------------------------------------------------------- 1 | // 2 | // OBJGroup.h 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/3/27. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface OBJGroup : NSObject 12 | 13 | - (instancetype) initWithName :(NSString*) name; 14 | 15 | @property (copy) NSString * name; 16 | @property (copy) NSData * vertexData; 17 | @property (copy) NSData * indexData; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /HelloMetal/HelloMetal/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // HelloMetal 4 | // 5 | // Created by Volvet Zhang on 16/3/5. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @import AVFoundation; 12 | @import Metal; 13 | @import MetalKit; 14 | @import MetalPerformanceShaders; 15 | 16 | @interface ViewController : UIViewController 17 | 18 | 19 | @end 20 | 21 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MainBoundleTextureProvider.h: -------------------------------------------------------------------------------- 1 | // 2 | // MainBoundleTextureProvider.h 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/5/2. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImageFilter.h" 11 | 12 | @interface MainBoundleTextureProvider : NSObject 13 | 14 | + (instancetype) textureProviderWithImageNamed :(NSString*)imageName context:(IPContext*)context; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/GaussianBlurFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // GaussianBlurFilter.h 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/5/1. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "ImageFilter.h" 10 | 11 | @interface GaussianBlurFilter : ImageFilter 12 | 13 | @property (nonatomic, assign) float radius; 14 | @property (nonatomic, assign) float sigma; 15 | 16 | + (instancetype) filterWithRadius :(float)radius :(IPContext*) context; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/SaturationAdjustmentFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // SaturationAdjustmentFilter.h 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/5/1. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "ImageFilter.h" 10 | 11 | @interface SaturationAdjustmentFilter : ImageFilter 12 | 13 | @property (nonatomic, assign) float saturationFactor; 14 | 15 | + (instancetype) filterWithSaturationFactor : (float)saturation context:(IPContext*)context; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/UIImage+TextureUtility.h: -------------------------------------------------------------------------------- 1 | // 2 | // TextureUtility.h 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/5/1. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #ifndef TextureUtility_h 10 | #define TextureUtility_h 11 | 12 | @import UIKit; 13 | 14 | @protocol MTLTexture; 15 | 16 | @interface UIImage (TextureUtility) 17 | 18 | + (UIImage*) imageWithMTLTexture: (id) texture; 19 | 20 | @end 21 | 22 | 23 | #endif /* TextureUtility_h */ 24 | -------------------------------------------------------------------------------- /Teapot/Teapot/OBJModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // OBJModel.h 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/3/27. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class OBJGroup; 12 | 13 | @interface OBJModel : NSObject 14 | 15 | - (instancetype) initWithContentsOfURL :(NSURL*)fileUrl generateNormals:(BOOL)generateNormals; 16 | 17 | @property (nonatomic, readonly) NSArray * groups; 18 | 19 | - (OBJGroup*) groupForName :(NSString*)groupName; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/IPContext.h: -------------------------------------------------------------------------------- 1 | // 2 | // IPContext.h 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/4/23. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | @interface IPContext : NSObject 14 | 15 | @property (nonatomic, strong) id device; 16 | @property (nonatomic, strong) id library; 17 | @property (nonatomic, strong) id commandQuene; 18 | 19 | 20 | + (instancetype) newContext; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Draw2d/Draw2d/Shaders.metal: -------------------------------------------------------------------------------- 1 | // 2 | // Shaders.metal 3 | // Draw2d 4 | // 5 | // Created by Volvet Zhang on 16/3/19. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | struct Vertex 13 | { 14 | float4 position[[position]]; 15 | float4 color; 16 | }; 17 | 18 | 19 | vertex Vertex vertex_main(device Vertex * vertices [[buffer(0)]], uint vid [[vertex_id]]) 20 | { 21 | return vertices[vid]; 22 | } 23 | 24 | fragment float4 fragment_main(Vertex inVertex [[stage_in]]) 25 | { 26 | return inVertex.color; 27 | } 28 | -------------------------------------------------------------------------------- /Draw2d/Draw2d/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // Draw2d 4 | // 5 | // Created by Volvet Zhang on 16/3/18. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view, typically from a nib. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/4/23. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @property (weak, nonatomic) IBOutlet UIImageView *imageView; 14 | 15 | @property (weak, nonatomic) IBOutlet UISlider *blurRadiusSlider; 16 | 17 | @property (weak, nonatomic) IBOutlet UISlider *saturationSlider; 18 | 19 | - (IBAction)blurRadiusDidChange:(id)sender; 20 | 21 | 22 | - (IBAction)saturationDidChange:(id)sender; 23 | 24 | @end 25 | 26 | -------------------------------------------------------------------------------- /Draw2d/Draw2d.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Draw2d.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | D3AE2DB91C9C330900C8AC82 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Draw3d/Draw3d.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Draw3d.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | D3908F2B1C9D6B3700076D59 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Teapot/Teapot.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Teapot.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | D38854781CA7A3EB00916E0A 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // ClearTheScreen 4 | // 5 | // Created by Volvet Zhang on 16/3/13. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view, typically from a nib. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Teapot/Teapot/OBJMesh.h: -------------------------------------------------------------------------------- 1 | // 2 | // OBJMesh.h 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/3/27. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #ifndef OBJMesh_h 10 | #define OBJMesh_h 11 | 12 | @import Metal; 13 | @import UIKit; 14 | 15 | @class OBJGroup; 16 | 17 | @interface Mesh : NSObject 18 | 19 | @property (nonatomic, readonly) id vertexBuffer; 20 | @property (nonatomic, readonly) id indexBuffer; 21 | 22 | @end 23 | 24 | @interface OBJMesh : Mesh 25 | 26 | - (instancetype) initWithGroup :(OBJGroup*) group device:(id)device; 27 | 28 | @end 29 | 30 | #endif /* OBJMesh_h */ 31 | -------------------------------------------------------------------------------- /HelloMetal/HelloMetal.xcodeproj/xcuserdata/volvet.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | HelloMetal.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1483CCC31C8A9622003E8891 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /MetalImage/MetalImage.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MetalImage.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | D3AB0F5D1CCB5A2D00090731 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen.xcodeproj/xcuserdata/volvet.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ClearTheScreen.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 14A170AB1C9515D6000B8D14 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ClearTheScreen.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 14A170AB1C9515D6000B8D14 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/IPContext.m: -------------------------------------------------------------------------------- 1 | // 2 | // IPContext.m 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/4/23. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "IPContext.h" 10 | 11 | @implementation IPContext 12 | 13 | + (instancetype) newContext { 14 | return [[self alloc] initWithDevice:nil]; 15 | } 16 | 17 | - (instancetype) initWithDevice : (id) device { 18 | if( self = [super init] ){ 19 | _device = device ? device : MTLCreateSystemDefaultDevice(); 20 | _library = [_device newDefaultLibrary]; 21 | _commandQuene = [_device newCommandQueue]; 22 | } 23 | return self; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Teapot/Teapot/typedef.h: -------------------------------------------------------------------------------- 1 | // 2 | // typedef.h 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/3/27. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #ifndef typedef_h 10 | #define typedef_h 11 | 12 | 13 | #include 14 | #include 15 | 16 | #define VertexIndexType MTLIndexTypeUInt16 17 | typedef uint16_t VertexIndex; 18 | 19 | typedef struct __attribute((packed)) { 20 | vector_float4 position; 21 | vector_float4 normal; 22 | } Vertex; 23 | 24 | typedef struct __attribute((packed)) { 25 | matrix_float4x4 modelViewProjectionMatrix; 26 | matrix_float4x4 modelViewMatrix; 27 | matrix_float3x3 normalMatrix; 28 | } Uniforms; 29 | 30 | 31 | 32 | #endif /* typedef_h */ 33 | -------------------------------------------------------------------------------- /Draw3d/Draw3d/MathUtility.h: -------------------------------------------------------------------------------- 1 | // 2 | // MathUtility.h 3 | // Draw3d 4 | // 5 | // Created by Volvet Zhang on 16/3/19. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #ifndef MathUtility_h 10 | #define MathUtility_h 11 | 12 | 13 | @import simd; 14 | 15 | // build a translation matrix 16 | matrix_float4x4 matrix_float4x4_translation(vector_float3 t); 17 | 18 | // build a scale matrix 19 | matrix_float4x4 matrix_float4x4_uniform_scale(float scale); 20 | 21 | // build a rotation matrix 22 | matrix_float4x4 matrix_float4x4_rotation(vector_float3 axis, float angle); 23 | 24 | // build a symmetric perspective matrix 25 | matrix_float4x4 matrix_float4x4_perspective(float aspect, float fovy, float near, float far); 26 | 27 | 28 | #endif /* MathUtility_h */ 29 | -------------------------------------------------------------------------------- /Teapot/Teapot/OBJGroup.m: -------------------------------------------------------------------------------- 1 | // 2 | // OBJGroup.m 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/3/27. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "typedef.h" 10 | #import "OBJGroup.h" 11 | 12 | 13 | @implementation OBJGroup 14 | 15 | - (instancetype) initWithName:(NSString *)name { 16 | if( self = [super init] ){ 17 | _name = [name copy]; 18 | } 19 | return self; 20 | } 21 | 22 | - (NSString *) description { 23 | size_t vertCount = _vertexData.length / sizeof(Vertex); 24 | size_t indexCount = _indexData.length / sizeof(VertexIndex); 25 | 26 | return [NSString stringWithFormat:@" 10 | using namespace metal; 11 | 12 | struct Vertex { 13 | float4 position[[position]]; 14 | float4 color; 15 | }; 16 | 17 | struct Uniforms { 18 | float4x4 modelViewProjectionMatrix; 19 | }; 20 | 21 | vertex Vertex vertex_main(device Vertex * vertices[[buffer(0)]], constant Uniforms * uniforms[[buffer(1)]], 22 | uint vid[[vertex_id]]) 23 | { 24 | Vertex vertexOut; 25 | 26 | vertexOut.position = uniforms->modelViewProjectionMatrix * vertices[vid].position; 27 | vertexOut.color = vertices[vid].color; 28 | 29 | return vertexOut; 30 | } 31 | 32 | 33 | fragment half4 fragment_main(Vertex vertexIn[[stage_in]]) 34 | { 35 | return half4(vertexIn.color); 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /Draw3d/Draw3d/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // Draw3d 4 | // 5 | // Created by Volvet Zhang on 16/3/19. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "MetalRender.h" 11 | 12 | @interface ViewController () 13 | 14 | @property (nonatomic, strong) MetalRender * mRender; 15 | 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | - (MetalView*) metalView { 21 | return (MetalView*)self.view; 22 | } 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | // Do any additional setup after loading the view, typically from a nib. 27 | 28 | self.mRender = [[MetalRender alloc] init]; 29 | self.metalView.mDelegate = self.mRender; 30 | } 31 | 32 | - (void)didReceiveMemoryWarning { 33 | [super didReceiveMemoryWarning]; 34 | // Dispose of any resources that can be recreated. 35 | } 36 | 37 | - (BOOL) prefersStatusBarHidden { 38 | return YES; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Teapot/Teapot/OBJMesh.m: -------------------------------------------------------------------------------- 1 | // 2 | // OBJMesh.m 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/3/27. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | 10 | #import "OBJMesh.h" 11 | #import "OBJGroup.h" 12 | 13 | 14 | @implementation Mesh 15 | 16 | @end 17 | 18 | 19 | @implementation OBJMesh 20 | 21 | @synthesize vertexBuffer; 22 | @synthesize indexBuffer; 23 | 24 | - (instancetype) initWithGroup:(OBJGroup *)group device:(id)device { 25 | if( self = [super init] ){ 26 | vertexBuffer = [device newBufferWithBytes:[group.vertexData bytes] length:[group.vertexData length] options:MTLResourceCPUCacheModeDefaultCache]; 27 | 28 | [vertexBuffer setLabel:group.name]; 29 | 30 | indexBuffer = [device newBufferWithBytes:[group.indexData bytes] length:[group.indexData length] options:MTLResourceCPUCacheModeDefaultCache]; 31 | 32 | [indexBuffer setLabel:group.name]; 33 | } 34 | 35 | return self; 36 | } 37 | 38 | @end -------------------------------------------------------------------------------- /Draw3d/Draw3d/MetalView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalView.h 3 | // Draw3d 4 | // 5 | // Created by Volvet Zhang on 16/3/20. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | @import Metal; 11 | @import QuartzCore; 12 | 13 | 14 | @protocol MetalViewDelegate; 15 | 16 | 17 | @interface MetalView : UIView 18 | 19 | @property (nonatomic, weak) id mDelegate; 20 | 21 | @property (nonatomic) NSInteger mPreferredFramePerSecond; 22 | 23 | @property (nonatomic) MTLPixelFormat pixelFormat; 24 | 25 | @property (nonatomic, assign) MTLClearColor mClearColor; 26 | 27 | @property (nonatomic, readonly) NSTimeInterval mFrameDuration; 28 | 29 | @property (nonatomic, readonly) id mCurrentDrawable; 30 | 31 | @property (nonatomic) MTLRenderPassDescriptor * currentRenderPassDescriptor; 32 | 33 | - (CAMetalLayer*) metalLayer; 34 | 35 | @end 36 | 37 | 38 | @protocol MetalViewDelegate 39 | 40 | - (void) drawInView:(MetalView*)view; 41 | 42 | @end -------------------------------------------------------------------------------- /Teapot/Teapot/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/3/27. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ViewController.h" 11 | #import "UIMetalView.h" 12 | #import "MetalViewRender.h" 13 | 14 | 15 | @interface ViewController () 16 | 17 | @property (nonatomic, strong) MetalViewRender * metalViewRender; 18 | 19 | @end 20 | 21 | @implementation ViewController 22 | 23 | - (UIMetalView*) uiMetalView { 24 | return (UIMetalView*) self.view; 25 | } 26 | 27 | - (void)viewDidLoad { 28 | [super viewDidLoad]; 29 | // Do any additional setup after loading the view, typically from a nib. 30 | _metalViewRender = [[MetalViewRender alloc] init]; 31 | self.uiMetalView.delegate = _metalViewRender; 32 | } 33 | 34 | - (BOOL) prefersStatusBarHidden { 35 | return YES; 36 | } 37 | 38 | - (void)didReceiveMemoryWarning { 39 | [super didReceiveMemoryWarning]; 40 | // Dispose of any resources that can be recreated. 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Teapot/Teapot/UIMetalView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIMetalView.h 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/4/2. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | @protocol UIMetalViewDelegate; 14 | 15 | 16 | @interface UIMetalView : UIView 17 | 18 | @property (nonatomic, weak) id delegate; 19 | 20 | @property (nonatomic, readonly) CAMetalLayer * metalLayer; 21 | 22 | @property (nonatomic) NSInteger preferredFramesPerSecond; 23 | 24 | @property (nonatomic) MTLPixelFormat colorPixelFormat; 25 | 26 | @property (nonatomic, assign) MTLClearColor clearColor; 27 | 28 | @property (nonatomic, readonly) NSTimeInterval frameDuration; 29 | 30 | @property (nonatomic, readonly) id currentDrawable; 31 | 32 | @property (nonatomic, readonly) MTLRenderPassDescriptor * currentRenderPassDescriptor; 33 | 34 | @end 35 | 36 | @protocol UIMetalViewDelegate 37 | 38 | - (void) drawInView :(UIMetalView *) view; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 volvet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageFilter.h 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/4/24. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | #import "IPContext.h" 14 | 15 | 16 | 17 | @protocol TextureProvider 18 | 19 | @property (nonatomic, readonly) id texture; 20 | 21 | @end 22 | 23 | @protocol TextureConsumer 24 | 25 | @property (nonatomic, strong) id provider; 26 | 27 | @end 28 | 29 | 30 | @interface ImageFilter : NSObject 31 | 32 | @property (nonatomic, strong) IPContext * context; 33 | @property (nonatomic, strong) id uniformBuffer; 34 | @property (nonatomic, strong) id pipeline; 35 | @property (nonatomic, strong) id internalTexture; 36 | @property (nonatomic, assign, getter=isDirty) BOOL dirty; 37 | 38 | - (instancetype) initWithFunctionName :(NSString*) functionName context:(IPContext*) context; 39 | - (void) configureArgumentTableWithCommandEncoder :(id) commandEncoder; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Draw2d/Draw2d/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 | } -------------------------------------------------------------------------------- /Teapot/Teapot/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 | } -------------------------------------------------------------------------------- /HelloMetal/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 | } -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen/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 | } -------------------------------------------------------------------------------- /Draw3d/Draw3d/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 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /MetalImage/MetalImage/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 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /MetalImage/MetalImage/SaturationAdjustmentFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // SaturationAdjustmentFilter.m 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/5/1. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "SaturationAdjustmentFilter.h" 10 | 11 | struct AdjustSaturationUniforms 12 | { 13 | float saturationFactor; 14 | }; 15 | 16 | @implementation SaturationAdjustmentFilter 17 | 18 | + (instancetype) filterWithSaturationFactor:(float)saturation context:(IPContext *)context { 19 | return [[self alloc] initWithSaturationFactor : saturation context:context]; 20 | } 21 | 22 | - (instancetype) initWithSaturationFactor : (float)saturation context:(IPContext*)context { 23 | if( self = [super initWithFunctionName:@"adjust_saturation" context:context] ){ 24 | _saturationFactor = saturation; 25 | } 26 | return self; 27 | } 28 | 29 | - (void) setSaturationFactor:(float)saturationFactor { 30 | self.dirty = YES; 31 | 32 | _saturationFactor = saturationFactor; 33 | } 34 | 35 | - (void) configureArgumentTableWithCommandEncoder:(id)commandEncoder { 36 | struct AdjustSaturationUniforms uniforms; 37 | 38 | uniforms.saturationFactor = _saturationFactor; 39 | 40 | if( !self.uniformBuffer ) { 41 | self.uniformBuffer = [self.context.device newBufferWithLength:sizeof(uniforms) options:MTLResourceOptionCPUCacheModeDefault]; 42 | } 43 | 44 | memcpy( [self.uniformBuffer contents], &uniforms, sizeof(uniforms) ); 45 | [commandEncoder setBuffer:self.uniformBuffer offset:0 atIndex:0]; 46 | 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /HelloMetal/HelloMetal.xcodeproj/xcuserdata/volvet.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Draw2d/Draw2d/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 | -------------------------------------------------------------------------------- /Draw3d/Draw3d/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 | -------------------------------------------------------------------------------- /Teapot/Teapot/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 | -------------------------------------------------------------------------------- /HelloMetal/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 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/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 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen/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 | -------------------------------------------------------------------------------- /Draw2d/Draw2d/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 | -------------------------------------------------------------------------------- /Draw3d/Draw3d/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 | -------------------------------------------------------------------------------- /Teapot/Teapot/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 | -------------------------------------------------------------------------------- /HelloMetal/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 | 27 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen/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 | -------------------------------------------------------------------------------- /Draw2d/Draw2d/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 | -------------------------------------------------------------------------------- /Draw3d/Draw3d/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 | -------------------------------------------------------------------------------- /Teapot/Teapot/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 | -------------------------------------------------------------------------------- /HelloMetal/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 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/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 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen/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 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/Shaders.metal: -------------------------------------------------------------------------------- 1 | // 2 | // Shaders.metal 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/5/2. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | 13 | struct AdjustStaturationUniforms 14 | { 15 | float saturationFactor; 16 | }; 17 | 18 | kernel void adjust_saturation(texture2d inTexture[[texture(0)]], 19 | texture2d outTexture[[texture(1)]], 20 | constant AdjustStaturationUniforms & uniforms[[buffer(0)]], 21 | uint2 gid[[thread_position_in_grid]]) 22 | { 23 | float4 inColor = inTexture.read(gid); 24 | float value = dot(inColor.rgb, float3(0.299, 0.587, 0.014)); 25 | float4 grayColor(value, value, value, 1.0); 26 | 27 | float4 outColor = mix(grayColor, inColor, uniforms.saturationFactor); 28 | outTexture.write(outColor, gid); 29 | } 30 | 31 | 32 | kernel void gaussian_blur_2d(texture2d inTexture[[texture(0)]], 33 | texture2d outTexture[[texture(1)]], 34 | texture2d weights[[texture(2)]], 35 | uint2 gid[[thread_position_in_grid]]) 36 | { 37 | int size = weights.get_width(); 38 | int radius = size / 2; 39 | float4 accumColor(0, 0, 0, 0); 40 | 41 | for( int j=0;j mDevice; 15 | @property (nonatomic, strong) id mCommandQueue; 16 | 17 | @end 18 | 19 | @implementation MetalView 20 | 21 | + (id) layerClass { 22 | return [CAMetalLayer class]; 23 | } 24 | 25 | 26 | -(instancetype)initWithCoder:(NSCoder *)aDecoder { 27 | if( self = [super initWithCoder:aDecoder] ){ 28 | self.mDevice = MTLCreateSystemDefaultDevice(); 29 | self.mCommandQueue = [self.mDevice newCommandQueue]; 30 | 31 | self.metalLayer.device = self.mDevice; 32 | self.metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; 33 | } 34 | 35 | return self; 36 | } 37 | 38 | -(CAMetalLayer*) metalLayer { 39 | return (CAMetalLayer*) self.layer; 40 | } 41 | 42 | -(void)didMoveToWindow { 43 | [self redraw]; 44 | } 45 | 46 | -(void)redraw { 47 | id drawable = [self.metalLayer nextDrawable]; 48 | id texture = drawable.texture; 49 | 50 | MTLRenderPassDescriptor *passDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; 51 | passDescriptor.colorAttachments[0].texture = texture; 52 | passDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; 53 | passDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; 54 | passDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(1, 0, 1, 1); 55 | 56 | 57 | id commandBuffer = [self.mCommandQueue commandBuffer]; 58 | id commandEncoder = [commandBuffer renderCommandEncoderWithDescriptor:passDescriptor]; 59 | 60 | [commandEncoder endEncoding]; 61 | [commandBuffer presentDrawable:drawable]; 62 | [commandBuffer commit]; 63 | } 64 | 65 | 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Draw2d/Draw2d/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Draw2d 4 | // 5 | // Created by Volvet Zhang on 16/3/18. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Draw3d/Draw3d/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Draw3d 4 | // 5 | // Created by Volvet Zhang on 16/3/19. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Teapot/Teapot/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/3/27. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/4/23. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /HelloMetal/HelloMetal/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // HelloMetal 4 | // 5 | // Created by Volvet Zhang on 16/3/5. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ClearTheScreen 4 | // 5 | // Created by Volvet Zhang on 16/3/13. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Teapot/Teapot.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 18 | 19 | 20 | 22 | 34 | 35 | 36 | 38 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/MainBoundleTextureProvider.m: -------------------------------------------------------------------------------- 1 | // 2 | // MainBoundleTextureProvider.m 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/5/2. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | @import Metal; 10 | @import UIKit; 11 | 12 | #import "MainBoundleTextureProvider.h" 13 | 14 | 15 | @interface MainBoundleTextureProvider() 16 | 17 | @property (nonatomic, strong) id texture; 18 | 19 | @end 20 | 21 | @implementation MainBoundleTextureProvider 22 | 23 | + (instancetype) textureProviderWithImageNamed:(NSString *)imageName context:(IPContext *)context { 24 | return [[self alloc] initWithImageNamed:imageName context:context]; 25 | } 26 | 27 | 28 | - (instancetype) initWithImageNamed :(NSString*)imageName context:(IPContext*)context { 29 | if( self = [super init] ){ 30 | UIImage * image = [UIImage imageNamed:imageName]; 31 | _texture = [self textureForImage:image context:context]; 32 | } 33 | 34 | return self; 35 | } 36 | 37 | - (id) textureForImage :(UIImage*)image context:(IPContext*)context { 38 | CGImageRef imageRef = [image CGImage]; 39 | 40 | NSUInteger width = CGImageGetWidth(imageRef); 41 | NSUInteger height = CGImageGetHeight(imageRef); 42 | CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); 43 | uint8_t * rawData = (uint8_t*)malloc(width * height * 4); 44 | const NSUInteger bytesPerPixel = 4; 45 | const NSUInteger bytesPerRow = bytesPerPixel * width; 46 | const NSUInteger bitsPerComponent = 8; 47 | CGContextRef bitmapContext = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorspace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrder32Big); 48 | CGColorSpaceRelease(colorspace); 49 | 50 | CGContextTranslateCTM(bitmapContext, 0, height); 51 | CGContextScaleCTM(bitmapContext, 1, -1); 52 | 53 | CGContextDrawImage(bitmapContext, CGRectMake(0, 0, width, height), imageRef); 54 | CGContextRelease(bitmapContext); 55 | 56 | MTLTextureDescriptor * descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm width:width height:height mipmapped:NO]; 57 | 58 | id texture = [context.device newTextureWithDescriptor:descriptor]; 59 | MTLRegion region = MTLRegionMake2D(0, 0, width, height); 60 | [texture replaceRegion:region mipmapLevel:0 withBytes:rawData bytesPerRow:bytesPerRow]; 61 | 62 | free(rawData); 63 | return texture; 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/UIImage+TextureUtility.m: -------------------------------------------------------------------------------- 1 | // 2 | // TextureUtility.m 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/5/1. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "UIImage+TextureUtility.h" 12 | 13 | 14 | static void ReleaseDataCallback(void * inof, const void * data, size_t size) 15 | { 16 | free((void*)data); 17 | } 18 | 19 | @implementation UIImage(TextureUtility) 20 | 21 | + (UIImage*) imageWithMTLTexture :(id)texture { 22 | NSAssert([texture pixelFormat] == MTLPixelFormatRGBA8Unorm, @"Unexpected pixel format"); 23 | 24 | CGSize imageSize = CGSizeMake([texture width], [texture height]); 25 | size_t imageByteCount = imageSize.width * imageSize.height * 4; 26 | 27 | void * imageBytes = malloc(imageByteCount); 28 | NSUInteger bytesPerRow = imageSize.width * 4; 29 | MTLRegion region = MTLRegionMake2D(0, 0, imageSize.width, imageSize.height); 30 | [texture getBytes :imageBytes bytesPerRow:bytesPerRow fromRegion:region mipmapLevel:0]; 31 | 32 | CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, 33 | imageBytes, 34 | imageByteCount, 35 | ReleaseDataCallback); 36 | const int bitsPerComponent = 8; 37 | const int bitsPerPixel = 32; 38 | CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); 39 | CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big; 40 | CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 41 | CGImageRef imageRef = CGImageCreate(imageSize.width, 42 | imageSize.height, 43 | bitsPerComponent, 44 | bitsPerPixel, 45 | bytesPerRow, 46 | colorspace, 47 | bitmapInfo, 48 | provider, 49 | NULL, 50 | false, 51 | renderingIntent); 52 | UIImage * img = [UIImage imageWithCGImage:imageRef scale:0.0 orientation:UIImageOrientationDownMirrored]; 53 | CFRelease(provider); 54 | CFRelease(colorspace); 55 | CFRelease(imageRef); 56 | 57 | return img; 58 | } 59 | 60 | @end -------------------------------------------------------------------------------- /Draw3d/Draw3d/MathUtility.m: -------------------------------------------------------------------------------- 1 | // 2 | // MathUtility.m 3 | // Draw3d 4 | // 5 | // Created by Volvet Zhang on 16/3/19. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "MathUtility.h" 10 | 11 | 12 | // build a translation matrix 13 | matrix_float4x4 matrix_float4x4_translation(vector_float3 t) 14 | { 15 | vector_float4 X = { 1, 0, 0, 0 }; 16 | vector_float4 Y = { 0, 1, 0, 0 }; 17 | vector_float4 Z = { 0, 0, 1, 0 }; 18 | vector_float4 W = { t.x, t.y, t.z, 1 }; 19 | 20 | matrix_float4x4 mat = { X, Y, Z, W }; 21 | 22 | return mat; 23 | } 24 | 25 | // build a scale matrix 26 | matrix_float4x4 matrix_float4x4_uniform_scale(float scale) 27 | { 28 | vector_float4 X = { scale, 0, 0, 0 }; 29 | vector_float4 Y = { 0, scale, 0, 0 }; 30 | vector_float4 Z = { 0, 0, scale, 0 }; 31 | vector_float4 W = { 0, 0, 0, 1 }; 32 | 33 | matrix_float4x4 mat = { X, Y, Z, W }; 34 | 35 | return mat; 36 | } 37 | 38 | // build a rotation matrix 39 | matrix_float4x4 matrix_float4x4_rotation(vector_float3 axis, float angle) 40 | { 41 | float c = cos(angle); 42 | float s = sin(angle); 43 | 44 | vector_float4 X; 45 | X.x = axis.x * axis.x + (1 - axis.x * axis.x) * c; 46 | X.y = axis.x * axis.y * (1 - c) - axis.z * s; 47 | X.z = axis.x * axis.z * (1 - c) + axis.y * s; 48 | X.w = 0.0; 49 | 50 | vector_float4 Y; 51 | Y.x = axis.x * axis.y * (1 - c) + axis.z * s; 52 | Y.y = axis.y * axis.y + (1 - axis.y * axis.y) * c; 53 | Y.z = axis.y * axis.z * (1 - c) - axis.x * s; 54 | Y.w = 0.0; 55 | 56 | vector_float4 Z; 57 | Z.x = axis.x * axis.z * (1 - c) - axis.y * s; 58 | Z.y = axis.y * axis.z * (1 - c) + axis.x * s; 59 | Z.z = axis.z * axis.z + (1 - axis.z * axis.z) * c; 60 | Z.w = 0.0; 61 | 62 | vector_float4 W; 63 | W.x = 0.0; 64 | W.y = 0.0; 65 | W.z = 0.0; 66 | W.w = 1.0; 67 | 68 | matrix_float4x4 mat = { X, Y, Z, W }; 69 | 70 | return mat; 71 | } 72 | 73 | // build a symmetric perspective matrix 74 | matrix_float4x4 matrix_float4x4_perspective(float aspect, float fovy, float near, float far) 75 | { 76 | float yScale = 1 / tan(fovy * 0.5); 77 | float xScale = yScale / aspect; 78 | float zRange = far - near; 79 | float zScale = -(far + near) / zRange; 80 | float wzScale = -2 * far * near / zRange; 81 | 82 | vector_float4 P = { xScale, 0, 0, 0 }; 83 | vector_float4 Q = { 0, yScale, 0, 0 }; 84 | vector_float4 R = { 0, 0, zScale, -1 }; 85 | vector_float4 S = { 0, 0, wzScale, 0 }; 86 | 87 | matrix_float4x4 mat = { P, Q, R, S }; 88 | 89 | return mat; 90 | } -------------------------------------------------------------------------------- /Teapot/Teapot/shader.metal: -------------------------------------------------------------------------------- 1 | // 2 | // shader.metal 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/4/2. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | 12 | using namespace metal; 13 | 14 | struct Light 15 | { 16 | float3 direction; 17 | float3 ambientColor; 18 | float3 diffuseColor; 19 | float3 specularColor; 20 | }; 21 | 22 | constant Light light = { 23 | .direction = { 0.13, 0.72, 0.68 }, 24 | .ambientColor = { 0.05, 0.05, 0.05 }, 25 | .diffuseColor = { 0.9, 0.9, 0.9 }, 26 | .specularColor = { 1, 1, 1 } 27 | }; 28 | 29 | struct Material 30 | { 31 | float3 ambientColor; 32 | float3 diffuseColor; 33 | float3 specularColor; 34 | float specularPower; 35 | }; 36 | 37 | constant Material material = { 38 | .ambientColor = { 0.9, 0.1, 0 }, 39 | .diffuseColor = { 0.9, 0.1, 0 }, 40 | .specularColor = { 1, 1, 1 }, 41 | .specularPower = 100 42 | }; 43 | 44 | struct Uniforms 45 | { 46 | float4x4 modelViewProjectionMatrix; 47 | float4x4 modelViewMatrix; 48 | float3x3 normalMatrix; 49 | }; 50 | 51 | struct Vertex 52 | { 53 | float4 position; 54 | float4 normal; 55 | }; 56 | 57 | struct ProjectedVertex 58 | { 59 | float4 position [[position]]; 60 | float3 eye; 61 | float3 normal; 62 | }; 63 | 64 | vertex ProjectedVertex vertex_main(device Vertex *vertices [[buffer(0)]], 65 | constant Uniforms &uniforms [[buffer(1)]], 66 | uint vid [[vertex_id]]) 67 | { 68 | ProjectedVertex outVert; 69 | outVert.position = uniforms.modelViewProjectionMatrix * vertices[vid].position; 70 | outVert.eye = -(uniforms.modelViewMatrix * vertices[vid].position).xyz; 71 | outVert.normal = uniforms.normalMatrix * vertices[vid].normal.xyz; 72 | 73 | return outVert; 74 | } 75 | 76 | fragment float4 fragment_main(ProjectedVertex vert [[stage_in]], 77 | constant Uniforms &uniforms [[buffer(0)]]) 78 | { 79 | float3 ambientTerm = light.ambientColor * material.ambientColor; 80 | 81 | float3 normal = normalize(vert.normal); 82 | float diffuseIntensity = saturate(dot(normal, light.direction)); 83 | float3 diffuseTerm = light.diffuseColor * material.diffuseColor * diffuseIntensity; 84 | 85 | float3 specularTerm(0); 86 | if (diffuseIntensity > 0) 87 | { 88 | float3 eyeDirection = normalize(vert.eye); 89 | float3 halfway = normalize(light.direction + eyeDirection); 90 | float specularFactor = pow(saturate(dot(normal, halfway)), material.specularPower); 91 | specularTerm = light.specularColor * material.specularColor * specularFactor; 92 | } 93 | 94 | return float4(ambientTerm + diffuseTerm + specularTerm, 1); 95 | } 96 | 97 | 98 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/GaussianBlurFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // GaussianBlurFilter.m 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/5/1. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "Metal/Metal.h" 10 | #import "GaussianBlurFilter.h" 11 | 12 | @interface GaussianBlurFilter() 13 | 14 | @property (nonatomic, strong) id blurWeightTexture; 15 | 16 | @end 17 | 18 | @implementation GaussianBlurFilter 19 | 20 | 21 | + (instancetype) filterWithRadius:(float)radius :(IPContext *)context { 22 | return [[self alloc] initWithRadius :radius context:context]; 23 | } 24 | 25 | - (instancetype) initWithRadius :(float)radius context:(IPContext*)context { 26 | if( self = [super initWithFunctionName:@"gaussian_blur_2d" context:context] ){ 27 | _radius = radius; 28 | _sigma = 0.5f; 29 | } 30 | return self; 31 | } 32 | 33 | - (void) generateBlurWeightTexture { 34 | NSAssert(_radius > 0.0f, @"Blur radius must > 0"); 35 | 36 | const float radius = _radius; 37 | const float sigma = _sigma; 38 | const int size = (round(radius) * 2 + 1); 39 | float delta = 0; 40 | float expScale = 0; 41 | 42 | if( radius > 0.0f ){ 43 | delta = (radius * 2)/(size - 1); 44 | expScale = -1 / (2 * sigma * sigma); 45 | } 46 | 47 | float * weights = malloc(sizeof(float) * size * size); 48 | float weightSum = 0; 49 | float y = - radius; 50 | for( int j=0;j)commandEncoder { 86 | if( !_blurWeightTexture ) { 87 | [self generateBlurWeightTexture]; 88 | } 89 | [commandEncoder setTexture:_blurWeightTexture atIndex:2]; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ImageFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageFilter.m 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/4/24. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "ImageFilter.h" 10 | 11 | @interface ImageFilter() 12 | 13 | @property (nonatomic, strong) id kernalFunction; 14 | @property (nonatomic, strong) id texture; 15 | 16 | @end 17 | 18 | @implementation ImageFilter 19 | 20 | @synthesize dirty = _dirty; 21 | @synthesize provider = _provider; 22 | 23 | - (instancetype) initWithFunctionName:(NSString *)functionName context:(IPContext *)context { 24 | if( self = [super init] ){ 25 | NSError * error = nil; 26 | _context = context; 27 | _kernalFunction = [_context.library newFunctionWithName:functionName]; 28 | _pipeline = [_context.device newComputePipelineStateWithFunction:_kernalFunction error:&error]; 29 | 30 | if( !_pipeline ){ 31 | NSLog(@"Error occured when building compute pipeline for function %@", functionName); 32 | return nil; 33 | } 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (void) configureArgumentTableWithCommandEncoder:(id)commandEncoder { 40 | 41 | } 42 | 43 | - (void) applyFilter { 44 | id inputTexture = self.provider.texture; 45 | 46 | if( (!_internalTexture) || ([_internalTexture width] != [inputTexture width]) || 47 | ([_internalTexture height] != [_internalTexture height]) ) { 48 | MTLTextureDescriptor * textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:[inputTexture pixelFormat] width:[inputTexture width] height:[inputTexture height] mipmapped:NO]; 49 | _internalTexture = [_context.device newTextureWithDescriptor:textureDescriptor]; 50 | } 51 | 52 | MTLSize threadgroupCounts = MTLSizeMake(8, 8, 1); 53 | MTLSize threadgroups = MTLSizeMake([inputTexture width]/threadgroupCounts.width, 54 | [inputTexture height]/threadgroupCounts.height, 55 | 1); 56 | 57 | id commandBuffer = [_context.commandQuene commandBuffer]; 58 | id commandEncoder = [commandBuffer computeCommandEncoder]; 59 | [commandEncoder setComputePipelineState: _pipeline]; 60 | [commandEncoder setTexture:inputTexture atIndex:0]; 61 | [commandEncoder setTexture:_internalTexture atIndex:1]; 62 | [self configureArgumentTableWithCommandEncoder:commandEncoder]; 63 | [commandEncoder dispatchThreadgroups:threadgroups threadsPerThreadgroup:threadgroupCounts]; 64 | [commandEncoder endEncoding]; 65 | 66 | [commandBuffer commit]; 67 | [commandBuffer waitUntilCompleted]; 68 | } 69 | 70 | - (id) texture { 71 | if( _dirty ) { 72 | [self applyFilter]; 73 | _dirty = NO; 74 | } 75 | return self.internalTexture; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // MetalImage 4 | // 5 | // Created by Volvet Zhang on 16/4/23. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "IPContext.h" 11 | #import "ImageFilter.h" 12 | #import "GaussianBlurFilter.h" 13 | #import "SaturationAdjustmentFilter.h" 14 | #import "UIImage+TextureUtility.h" 15 | #import "MainBoundleTextureProvider.h" 16 | 17 | @interface ViewController () 18 | 19 | @property (nonatomic, strong) IPContext * context; 20 | @property (nonatomic, strong) id imageProvider; 21 | @property (nonatomic, strong) SaturationAdjustmentFilter * saturationFilter; 22 | @property (nonatomic, strong) GaussianBlurFilter * gaussionBlurFilter; 23 | 24 | @property (nonatomic, strong) dispatch_queue_t renderingQueue; 25 | @property (atomic, assign) uint64_t jobIndex; 26 | 27 | 28 | @end 29 | 30 | @implementation ViewController 31 | 32 | - (void)viewDidLoad { 33 | [super viewDidLoad]; 34 | // Do any additional setup after loading the view, typically from a nib. 35 | 36 | _renderingQueue = dispatch_queue_create("Rendering", DISPATCH_QUEUE_SERIAL); 37 | [self buildFilterGraph]; 38 | //[self updateImage]; 39 | } 40 | 41 | - (void)didReceiveMemoryWarning { 42 | [super didReceiveMemoryWarning]; 43 | // Dispose of any resources that can be recreated. 44 | } 45 | 46 | - (void)buildFilterGraph { 47 | _context = [IPContext newContext]; 48 | _imageProvider = [MainBoundleTextureProvider textureProviderWithImageNamed:@"mandrill" context:_context]; 49 | _saturationFilter = [SaturationAdjustmentFilter filterWithSaturationFactor:self.saturationSlider.value context:_context]; 50 | _saturationFilter.provider = _imageProvider; 51 | _gaussionBlurFilter = [GaussianBlurFilter filterWithRadius:self.blurRadiusSlider.value :_context]; 52 | _gaussionBlurFilter.provider = _saturationFilter; 53 | [self updateImage]; 54 | } 55 | 56 | - (void)updateImage { 57 | ++ _jobIndex; 58 | 59 | uint64_t currentJobIndex = _jobIndex; 60 | float blurRadius = _blurRadiusSlider.value; 61 | float saturation = _saturationSlider.value; 62 | 63 | NSLog(@"blurRadius = %f, saturation = %f", blurRadius, saturation); 64 | 65 | dispatch_async(_renderingQueue, ^{ 66 | if( currentJobIndex != _jobIndex ) return; 67 | _gaussionBlurFilter.radius = blurRadius; 68 | _saturationFilter.saturationFactor = saturation; 69 | 70 | id texture = _gaussionBlurFilter.texture; 71 | UIImage * image = [UIImage imageWithMTLTexture:texture]; 72 | 73 | dispatch_async(dispatch_get_main_queue(), ^{ 74 | _imageView.image = image; 75 | }); 76 | }); 77 | } 78 | 79 | - (IBAction)blurRadiusDidChange:(id)sender { 80 | [self updateImage]; 81 | } 82 | 83 | - (IBAction)saturationDidChange:(id)sender { 84 | [self updateImage]; 85 | } 86 | @end 87 | -------------------------------------------------------------------------------- /Teapot/Teapot/MathUtility.m: -------------------------------------------------------------------------------- 1 | // 2 | // MathUtility.m 3 | // Draw3d 4 | // 5 | // Created by Volvet Zhang on 16/3/19. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "MathUtility.h" 10 | 11 | 12 | // build a translation matrix 13 | matrix_float4x4 matrix_float4x4_translation(vector_float3 t) 14 | { 15 | vector_float4 X = { 1, 0, 0, 0 }; 16 | vector_float4 Y = { 0, 1, 0, 0 }; 17 | vector_float4 Z = { 0, 0, 1, 0 }; 18 | vector_float4 W = { t.x, t.y, t.z, 1 }; 19 | 20 | matrix_float4x4 mat = { X, Y, Z, W }; 21 | 22 | return mat; 23 | } 24 | 25 | // build a scale matrix 26 | matrix_float4x4 matrix_float4x4_uniform_scale(float scale) 27 | { 28 | vector_float4 X = { scale, 0, 0, 0 }; 29 | vector_float4 Y = { 0, scale, 0, 0 }; 30 | vector_float4 Z = { 0, 0, scale, 0 }; 31 | vector_float4 W = { 0, 0, 0, 1 }; 32 | 33 | matrix_float4x4 mat = { X, Y, Z, W }; 34 | 35 | return mat; 36 | } 37 | 38 | // build a rotation matrix 39 | matrix_float4x4 matrix_float4x4_rotation(vector_float3 axis, float angle) 40 | { 41 | float c = cos(angle); 42 | float s = sin(angle); 43 | 44 | vector_float4 X; 45 | X.x = axis.x * axis.x + (1 - axis.x * axis.x) * c; 46 | X.y = axis.x * axis.y * (1 - c) - axis.z * s; 47 | X.z = axis.x * axis.z * (1 - c) + axis.y * s; 48 | X.w = 0.0; 49 | 50 | vector_float4 Y; 51 | Y.x = axis.x * axis.y * (1 - c) + axis.z * s; 52 | Y.y = axis.y * axis.y + (1 - axis.y * axis.y) * c; 53 | Y.z = axis.y * axis.z * (1 - c) - axis.x * s; 54 | Y.w = 0.0; 55 | 56 | vector_float4 Z; 57 | Z.x = axis.x * axis.z * (1 - c) - axis.y * s; 58 | Z.y = axis.y * axis.z * (1 - c) + axis.x * s; 59 | Z.z = axis.z * axis.z + (1 - axis.z * axis.z) * c; 60 | Z.w = 0.0; 61 | 62 | vector_float4 W; 63 | W.x = 0.0; 64 | W.y = 0.0; 65 | W.z = 0.0; 66 | W.w = 1.0; 67 | 68 | matrix_float4x4 mat = { X, Y, Z, W }; 69 | 70 | return mat; 71 | } 72 | 73 | // build a symmetric perspective matrix 74 | matrix_float4x4 matrix_float4x4_perspective(float aspect, float fovy, float near, float far) 75 | { 76 | float yScale = 1 / tan(fovy * 0.5); 77 | float xScale = yScale / aspect; 78 | float zRange = far - near; 79 | float zScale = -(far + near) / zRange; 80 | float wzScale = -2 * far * near / zRange; 81 | 82 | vector_float4 P = { xScale, 0, 0, 0 }; 83 | vector_float4 Q = { 0, yScale, 0, 0 }; 84 | vector_float4 R = { 0, 0, zScale, -1 }; 85 | vector_float4 S = { 0, 0, wzScale, 0 }; 86 | 87 | matrix_float4x4 mat = { P, Q, R, S }; 88 | 89 | return mat; 90 | } 91 | 92 | matrix_float3x3 matrix_float4x4_extract_linear(matrix_float4x4 matrix) 93 | { 94 | vector_float3 X = matrix.columns[0].xyz; 95 | vector_float3 Y = matrix.columns[1].xyz; 96 | vector_float3 Z = matrix.columns[2].xyz; 97 | 98 | matrix_float3x3 extracted_matrix = { X, Y, Z }; 99 | 100 | return extracted_matrix; 101 | } 102 | -------------------------------------------------------------------------------- /Draw2d/Draw2d.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcschemes/Draw2d.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Draw3d/Draw3d.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcschemes/Draw3d.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Teapot/Teapot.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcschemes/Teapot.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /HelloMetal/HelloMetal.xcodeproj/xcuserdata/volvet.xcuserdatad/xcschemes/HelloMetal.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MetalImage/MetalImage.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcschemes/MetalImage.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen.xcodeproj/xcuserdata/volvet.xcuserdatad/xcschemes/ClearTheScreen.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ClearTheScreen/ClearTheScreen.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcschemes/ClearTheScreen.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /MetalImage/MetalImage/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 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Teapot/Teapot/UIMetalView.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIMetalView.m 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/4/2. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "UIMetalView.h" 10 | 11 | @interface UIMetalView() 12 | 13 | @property (nonatomic, strong) id depthTexture; 14 | 15 | @property (nonatomic) id currentDrawable; 16 | 17 | @property (nonatomic) NSTimeInterval frameDuration; 18 | 19 | @property (nonatomic, strong) CADisplayLink * displayLink; 20 | 21 | @end 22 | 23 | 24 | @implementation UIMetalView 25 | 26 | 27 | + (Class) layerClass { 28 | return [CAMetalLayer class]; 29 | } 30 | 31 | - (CAMetalLayer*) metalLayer { 32 | return (CAMetalLayer*)self.layer; 33 | } 34 | 35 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 36 | if( self = [super initWithCoder:aDecoder] ){ 37 | [self commonInit]; 38 | } 39 | 40 | return self; 41 | } 42 | 43 | - (instancetype) initWithFrame:(CGRect)frame { 44 | if( self = [super initWithFrame:frame] ){ 45 | [self commonInit]; 46 | } 47 | 48 | return self; 49 | } 50 | 51 | - (void) commonInit { 52 | self.preferredFramesPerSecond = 60; 53 | self.clearColor = MTLClearColorMake(1, 1, 1, 1); 54 | self.metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; 55 | self.metalLayer.device = MTLCreateSystemDefaultDevice(); 56 | } 57 | 58 | - (void) setColorPixelFormat:(MTLPixelFormat)colorPixelFormat { 59 | self.metalLayer.pixelFormat = colorPixelFormat; 60 | } 61 | 62 | - (MTLPixelFormat) colorPixelFormat { 63 | return self.metalLayer.pixelFormat; 64 | } 65 | 66 | - (void) makeDepthTexture { 67 | CGSize drawableSize = self.metalLayer.drawableSize; 68 | 69 | if( ([self.depthTexture width] != drawableSize.width) || 70 | ([self.depthTexture height] != drawableSize.height) ) { 71 | MTLTextureDescriptor * descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatDepth32Float width:drawableSize.width height:drawableSize.height mipmapped:NO]; 72 | self.depthTexture = [self.metalLayer.device newTextureWithDescriptor:descriptor]; 73 | } 74 | } 75 | 76 | - (void) setFrame :(CGRect)frame { 77 | [super setFrame :frame]; 78 | 79 | CGFloat scale = [UIScreen mainScreen].scale; 80 | 81 | if( self.window ){ 82 | scale = self.window.screen.scale; 83 | } 84 | 85 | CGSize drawableSize = self.bounds.size; 86 | 87 | drawableSize.width *= scale; 88 | drawableSize.height *= scale; 89 | 90 | self.metalLayer.drawableSize = drawableSize; 91 | 92 | [self makeDepthTexture]; 93 | } 94 | 95 | - (void) displayLinkDidFire :(CADisplayLink*) displayLink { 96 | self.currentDrawable = [self.metalLayer nextDrawable]; 97 | self.frameDuration = displayLink.duration; 98 | 99 | @autoreleasepool { 100 | if( [self.delegate respondsToSelector:@selector(drawInView:)] ){ 101 | [self.delegate drawInView:self]; 102 | } 103 | } 104 | } 105 | 106 | - (void) didMoveToWindow { 107 | const NSTimeInterval idealFrameDuration = (1.0/60); 108 | const NSTimeInterval targetFrameDuration = (1.0/self.preferredFramesPerSecond); 109 | const NSInteger frameInterval = round(targetFrameDuration/idealFrameDuration); 110 | 111 | if( self.window ){ 112 | [self.displayLink invalidate]; 113 | self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkDidFire:)]; 114 | self.displayLink.frameInterval = frameInterval; 115 | [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; 116 | } else { 117 | [self.displayLink invalidate]; 118 | self.displayLink = nil; 119 | } 120 | } 121 | 122 | - (MTLRenderPassDescriptor*) currentRenderPassDescriptor { 123 | MTLRenderPassDescriptor * descriptor = [MTLRenderPassDescriptor new]; 124 | 125 | descriptor.colorAttachments[0].texture = [self.currentDrawable texture]; 126 | descriptor.colorAttachments[0].clearColor = self.clearColor; 127 | descriptor.colorAttachments[0].storeAction = MTLStoreActionStore; 128 | descriptor.colorAttachments[0].loadAction = MTLLoadActionClear; 129 | 130 | descriptor.depthAttachment.texture = self.depthTexture; 131 | descriptor.depthAttachment.clearDepth = 1.0; 132 | descriptor.depthAttachment.loadAction = MTLLoadActionClear; 133 | descriptor.depthAttachment.storeAction = MTLStoreActionDontCare; 134 | 135 | return descriptor; 136 | } 137 | 138 | 139 | @end 140 | -------------------------------------------------------------------------------- /Draw3d/Draw3d/MetalView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MetalView.m 3 | // Draw3d 4 | // 5 | // Created by Volvet Zhang on 16/3/20. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "MetalView.h" 10 | 11 | 12 | @interface MetalView() 13 | 14 | @property (strong) id mCurrentDrawable; 15 | @property (assign) NSTimeInterval mFrameDuration; 16 | @property (strong) id mDepthTexture; 17 | @property (strong) CADisplayLink *mDisplayLink; 18 | 19 | @end 20 | 21 | 22 | @implementation MetalView 23 | 24 | + (Class) layerClass { 25 | return [CAMetalLayer class]; 26 | } 27 | 28 | - (CAMetalLayer*) metalLayer { 29 | return (CAMetalLayer*)self.layer; 30 | } 31 | 32 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 33 | if( self = [super initWithCoder:aDecoder] ){ 34 | [self mtlInit]; 35 | } 36 | 37 | return self; 38 | } 39 | 40 | - (instancetype) initWithFrame:(CGRect)frame { 41 | if( self = [super initWithFrame:frame] ){ 42 | [self mtlInit]; 43 | } 44 | 45 | return self; 46 | } 47 | 48 | - (void) dealloc { 49 | [self.mDisplayLink invalidate]; 50 | } 51 | 52 | - (void) mtlInit { 53 | self.metalLayer.device = MTLCreateSystemDefaultDevice(); 54 | self.metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; 55 | self.mClearColor = MTLClearColorMake(1.0, 1.0, 1.0, 1.0); 56 | self.mPreferredFramePerSecond = 60; 57 | } 58 | 59 | - (void) setFrame:(CGRect)frame { 60 | [super setFrame:frame]; 61 | 62 | CGFloat scale = [UIScreen mainScreen].scale; 63 | 64 | if( self.window ){ 65 | scale = self.window.screen.scale; 66 | } 67 | 68 | CGSize drawableSize = self.bounds.size; 69 | drawableSize.width *= scale; 70 | drawableSize.height *= scale; 71 | 72 | self.metalLayer.drawableSize = drawableSize; 73 | [self makeDepthTexture]; 74 | } 75 | 76 | - (void) makeDepthTexture { 77 | CGSize drawableSize = self.metalLayer.drawableSize; 78 | 79 | if( ([self.mDepthTexture width] != drawableSize.width) || 80 | ([self.mDepthTexture height] != drawableSize.height) ) { 81 | MTLTextureDescriptor * textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatDepth32Float width:drawableSize.width height:drawableSize.height mipmapped:NO]; 82 | self.mDepthTexture = [self.metalLayer.device newTextureWithDescriptor:textureDescriptor]; 83 | } 84 | 85 | return; 86 | } 87 | 88 | - (void) setPixelFormat: (MTLPixelFormat) pixelFormat { 89 | self.metalLayer.pixelFormat = pixelFormat; 90 | } 91 | 92 | - (MTLPixelFormat) pixelFormat { 93 | return self.metalLayer.pixelFormat; 94 | } 95 | 96 | - (void) didMoveToWindow { 97 | [super didMoveToWindow]; 98 | 99 | const NSTimeInterval idealFrameDuration = 1.0 / 60.0; 100 | const NSTimeInterval targetFrameDuration = (1.0 / self.mPreferredFramePerSecond); 101 | const NSInteger frameInterval = round(targetFrameDuration / idealFrameDuration); 102 | 103 | if( self.window ){ 104 | [self.mDisplayLink invalidate]; 105 | self.mDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkDidFire:)]; 106 | self.mDisplayLink.frameInterval = frameInterval; 107 | [self.mDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; 108 | } else { 109 | [self.mDisplayLink invalidate]; 110 | self.mDisplayLink = nil; 111 | } 112 | } 113 | 114 | - (void) displayLinkDidFire: (CADisplayLink*) displayLink { 115 | @autoreleasepool { 116 | self.mCurrentDrawable = self.metalLayer.nextDrawable; 117 | self.mFrameDuration = self.mDisplayLink.duration; 118 | 119 | if( [self.mDelegate respondsToSelector:@selector(drawInView:)] ) { 120 | [self.mDelegate drawInView:self]; 121 | } 122 | } 123 | } 124 | 125 | - (MTLRenderPassDescriptor *) currentRenderPassDescriptor { 126 | MTLRenderPassDescriptor * passDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; 127 | 128 | passDescriptor.colorAttachments[0].texture = [self.mCurrentDrawable texture]; 129 | passDescriptor.colorAttachments[0].clearColor = self.mClearColor; 130 | passDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; 131 | passDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; 132 | 133 | passDescriptor.depthAttachment.texture = self.mDepthTexture; 134 | passDescriptor.depthAttachment.clearDepth = 1.0; 135 | passDescriptor.depthAttachment.loadAction = MTLLoadActionClear; 136 | passDescriptor.depthAttachment.storeAction = MTLStoreActionDontCare; 137 | 138 | return passDescriptor; 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /Draw2d/Draw2d/MetalView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MetalView.m 3 | // Draw2d 4 | // 5 | // Created by Volvet Zhang on 16/3/18. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import "MetalView.h" 10 | 11 | @import simd; 12 | 13 | typedef struct { 14 | vector_float4 position; 15 | vector_float4 color; 16 | } MetalVertex; 17 | 18 | @interface MetalView() 19 | 20 | @property (nonatomic, strong) CADisplayLink * mDisplayLink; 21 | @property (nonatomic, strong) id mDevice; 22 | @property (nonatomic, strong) id mPipeline; 23 | @property (nonatomic, strong) id mCommandQueue; 24 | @property (nonatomic, strong) id mVertexBuffer; 25 | 26 | @end 27 | 28 | @implementation MetalView 29 | 30 | + (Class) layerClass { 31 | return [CAMetalLayer class]; 32 | } 33 | 34 | - (instancetype) initWithCoder:(NSCoder *)aDecoder { 35 | if( self = [super initWithCoder:aDecoder] ){ 36 | [self mtlDeviceInit]; 37 | [self mtlVertexBufferInit]; 38 | [self mtlPipelineInit]; 39 | } 40 | 41 | return self; 42 | } 43 | 44 | - (void) dealloc { 45 | [self.mDisplayLink invalidate]; 46 | } 47 | 48 | - (CAMetalLayer*) metalLayer { 49 | return (CAMetalLayer*)self.layer; 50 | } 51 | 52 | - (void) mtlDeviceInit { 53 | self.mDevice = MTLCreateSystemDefaultDevice(); 54 | self.metalLayer.device = self.mDevice; 55 | self.metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; 56 | } 57 | 58 | - (void) mtlVertexBufferInit { 59 | static const MetalVertex vertices[] = { 60 | { .position = { 0.0f, 0.8f, 0.0f, 1.0f }, .color = { 1.0f, 0.0f, 0.0f, 1.0f } }, 61 | { .position = { -0.8, -0.8f, 0.0f, 1.0f }, .color = { 0.0f, 1.0f, 0.0f, 1.0f } }, 62 | { .position = { 0.8f, -0.8f, 0.0f, 1.0f }, .color = { 0.0f, 0.0f, 1.0f, 1.0f } } 63 | }; 64 | 65 | self.mVertexBuffer = [self.mDevice newBufferWithBytes:vertices length:sizeof(vertices) options:MTLResourceCPUCacheModeDefaultCache]; 66 | } 67 | 68 | - (void) mtlPipelineInit { 69 | id library = [self.mDevice newDefaultLibrary]; 70 | id vertexFunc = [library newFunctionWithName:@"vertex_main"]; 71 | id fragmentFunc = [library newFunctionWithName:@"fragment_main"]; 72 | 73 | MTLRenderPipelineDescriptor * pipelineDescriptor = [MTLRenderPipelineDescriptor new]; 74 | pipelineDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; 75 | pipelineDescriptor.vertexFunction = vertexFunc; 76 | pipelineDescriptor.fragmentFunction = fragmentFunc; 77 | 78 | NSError * error = nil; 79 | self.mPipeline = [self.mDevice newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error]; 80 | 81 | if( self.mPipeline == nil ){ 82 | NSLog(@"mtlPipelineInit: fail to create pipeline"); 83 | } 84 | 85 | self.mCommandQueue = [self.mDevice newCommandQueue]; 86 | } 87 | 88 | - (void)didMoveToSuperview { 89 | [super didMoveToSuperview]; 90 | 91 | if( self.subviews ){ 92 | self.mDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkDidFire:)]; 93 | [self.mDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; 94 | } else { 95 | [self.mDisplayLink invalidate]; 96 | self.mDisplayLink = nil; 97 | } 98 | } 99 | 100 | - (void)displayLinkDidFire:(CADisplayLink*)displayLink { 101 | @autoreleasepool { 102 | [self redraw]; 103 | } 104 | } 105 | 106 | - (void) redraw { 107 | id drawable = [self.metalLayer nextDrawable]; 108 | id texture = drawable.texture; 109 | 110 | if( drawable ) { 111 | MTLRenderPassDescriptor * passDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; 112 | passDescriptor.colorAttachments[0].texture = texture; 113 | passDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.3, 0.3, 0.3, 1.0); 114 | passDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; 115 | passDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; 116 | 117 | id commandBuffer = [self.mCommandQueue commandBuffer]; 118 | id commandEncoder = [commandBuffer renderCommandEncoderWithDescriptor:passDescriptor]; 119 | [commandEncoder setRenderPipelineState:self.mPipeline]; 120 | [commandEncoder setVertexBuffer:self.mVertexBuffer offset:0 atIndex:0]; 121 | [commandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3]; 122 | [commandEncoder endEncoding]; 123 | 124 | [commandBuffer presentDrawable:drawable]; 125 | [commandBuffer commit]; 126 | } 127 | } 128 | 129 | 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /HelloMetal/HelloMetal/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // HelloMetal 4 | // 5 | // Created by Volvet Zhang on 16/3/5. 6 | // Copyright © 2016年 Volvet Zhang. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "VideoMetalView.h" 11 | 12 | @interface ViewController () { 13 | //AVCaptureSession *mCaptureSession; 14 | } 15 | 16 | @property(nonatomic, strong) VideoMetalView * mMetalView; 17 | 18 | @property(nonatomic, strong) id mMetalCommandQueue; 19 | 20 | @property(nonatomic, strong) id mSourceTexture; 21 | 22 | @end 23 | 24 | 25 | 26 | @implementation ViewController 27 | 28 | 29 | - (void)viewDidLoad { 30 | [super viewDidLoad]; 31 | // Do any additional setup after loading the view, typically from a nib. 32 | 33 | self.mMetalView = (VideoMetalView*) self.view; 34 | self.mMetalView.device = MTLCreateSystemDefaultDevice(); 35 | 36 | if( !MPSSupportsMTLDevice(self.mMetalView.device) ){ 37 | NSLog(@"This device can't support Metal Performance Shaders!"); 38 | return; 39 | } 40 | 41 | [self setupView]; 42 | 43 | [self setupMetal]; 44 | 45 | [self loadAssets]; 46 | 47 | //[self startCapture]; 48 | } 49 | 50 | - (void)viewWillDisappear:(BOOL)animated { 51 | [super viewWillDisappear :animated]; 52 | //[self stopCapture]; 53 | } 54 | 55 | - (void)didReceiveMemoryWarning { 56 | [super didReceiveMemoryWarning]; 57 | // Dispose of any resources that can be recreated. 58 | } 59 | 60 | - (void)setupView { 61 | self.mMetalView.delegate = self; 62 | self.mMetalView.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8; 63 | self.mMetalView.colorPixelFormat = MTLPixelFormatBGRA8Unorm; 64 | self.mMetalView.framebufferOnly = FALSE; 65 | } 66 | 67 | - (void)setupMetal { 68 | self.mMetalCommandQueue = [self.mMetalView.device newCommandQueue]; 69 | } 70 | 71 | - (void)loadAssets { 72 | MTKTextureLoader * loader = [[MTKTextureLoader alloc] initWithDevice:self.mMetalView.device]; 73 | NSBundle * mainBundle = [NSBundle mainBundle]; 74 | 75 | NSURL *url = [mainBundle URLForResource:@"photo_night" withExtension:@"jpg"]; 76 | 77 | self.mSourceTexture = [loader newTextureWithContentsOfURL:url options:nil error:nil]; 78 | } 79 | 80 | - (void)render { 81 | // Create a new command buffer for each renderpass to the current drawable. 82 | id commandBuffer = [self.mMetalCommandQueue commandBuffer]; 83 | 84 | // Initialize MetalPerformanceShaders gaussianBlur with Sigma = 10.0f. 85 | MPSImageGaussianBlur *gaussianblur = [[MPSImageGaussianBlur alloc] initWithDevice:self.mMetalView.device sigma:1.0f]; 86 | 87 | // Run MetalPerformanceShader gaussianblur 88 | [gaussianblur encodeToCommandBuffer:commandBuffer 89 | sourceTexture:self.mSourceTexture 90 | destinationTexture:self.mMetalView.currentDrawable.texture]; 91 | 92 | // Schedule a present using the current drawable. 93 | [commandBuffer presentDrawable:self.mMetalView.currentDrawable]; 94 | 95 | // Finalize command buffer. 96 | [commandBuffer commit]; 97 | [commandBuffer waitUntilCompleted]; 98 | } 99 | 100 | /* 101 | - (void) startCapture { 102 | mCaptureSession = [[AVCaptureSession alloc] init]; 103 | 104 | [mCaptureSession beginConfiguration]; 105 | [mCaptureSession setSessionPreset:AVCaptureSessionPresetHigh]; 106 | 107 | // Get the a video device with preference to the front facing camera 108 | AVCaptureDevice* videoDevice = nil; 109 | NSArray* devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; 110 | for (AVCaptureDevice* device in devices) 111 | { 112 | if ([device position] == AVCaptureDevicePositionFront) 113 | { 114 | videoDevice = device; 115 | } 116 | } 117 | 118 | if(videoDevice == nil) 119 | { 120 | videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 121 | } 122 | 123 | if(videoDevice == nil) 124 | { 125 | NSLog(@">> ERROR: Couldnt create a AVCaptureDevice"); 126 | assert(0); 127 | } 128 | 129 | NSError *error; 130 | 131 | // Device input 132 | AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error]; 133 | 134 | if (error) 135 | { 136 | NSLog(@">> ERROR: Couldnt create AVCaptureDeviceInput"); 137 | assert(0); 138 | } 139 | 140 | [mCaptureSession addInput:deviceInput]; 141 | 142 | // Create the output for the capture session. 143 | AVCaptureVideoDataOutput * dataOutput = [[AVCaptureVideoDataOutput alloc] init]; 144 | [dataOutput setAlwaysDiscardsLateVideoFrames:YES]; 145 | 146 | // Set the color space. 147 | [dataOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] 148 | forKey:(id)kCVPixelBufferPixelFormatTypeKey]]; 149 | 150 | // Set dispatch to be on the main thread to create the texture in memory and allow Metal to use it for rendering 151 | [dataOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()]; 152 | 153 | [mCaptureSession addOutput:dataOutput]; 154 | [mCaptureSession commitConfiguration]; 155 | 156 | // this will trigger capture on its own queue 157 | [mCaptureSession startRunning]; 158 | 159 | } 160 | 161 | - (void) stopCapture { 162 | [mCaptureSession stopRunning]; 163 | } 164 | 165 | - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { 166 | //NSLog(@"captureOutput"); 167 | }*/ 168 | 169 | - (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size { 170 | 171 | } 172 | 173 | - (void)drawInMTKView:(nonnull MTKView *)view { 174 | @autoreleasepool { 175 | [self render]; 176 | } 177 | } 178 | 179 | @end 180 | -------------------------------------------------------------------------------- /Teapot/Teapot/MetalViewRender.m: -------------------------------------------------------------------------------- 1 | // 2 | // MentalViewRender.m 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/4/2. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | @import Metal; 10 | @import simd; 11 | @import QuartzCore; 12 | 13 | #import "typedef.h" 14 | #import "MetalViewRender.h" 15 | #import "MathUtility.h" 16 | #import "OBJMesh.h" 17 | #import "OBJModel.h" 18 | 19 | static const NSInteger InFlightBufferCount = 3; 20 | 21 | @interface MetalViewRender() 22 | 23 | @property (nonatomic, strong) Mesh *mesh; 24 | @property (nonatomic, strong) id device; 25 | @property (nonatomic, strong) id uniformBuffer; 26 | @property (nonatomic, strong) id commandQueue; 27 | @property (nonatomic, strong) id renderPipelineState; 28 | @property (nonatomic, strong) id depthStencilState; 29 | @property (nonatomic, strong) dispatch_semaphore_t displaySemaphore; 30 | @property (nonatomic, assign) NSInteger bufferIndex; 31 | @property (nonatomic, assign) float rotationX, rotationY, rotionZ, time; 32 | 33 | @end 34 | 35 | @implementation MetalViewRender 36 | 37 | - (instancetype) init { 38 | if( self = [super init] ){ 39 | _device = MTLCreateSystemDefaultDevice(); 40 | _displaySemaphore = dispatch_semaphore_create(InFlightBufferCount); 41 | [self makePipeline]; 42 | [self makeResource]; 43 | } 44 | 45 | return self; 46 | } 47 | 48 | - (void) makePipeline { 49 | _commandQueue = [_device newCommandQueue]; 50 | id library = [_device newDefaultLibrary]; 51 | 52 | 53 | MTLRenderPipelineDescriptor * descriptor = [MTLRenderPipelineDescriptor new]; 54 | descriptor.vertexFunction = [library newFunctionWithName:@"vertex_main"]; 55 | descriptor.fragmentFunction = [library newFunctionWithName:@"fragment_main"]; 56 | descriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; 57 | descriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float; 58 | 59 | MTLDepthStencilDescriptor * depthStencilDescriptor = [MTLDepthStencilDescriptor new]; 60 | depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionLess; 61 | depthStencilDescriptor.depthWriteEnabled = YES; 62 | _depthStencilState = [_device newDepthStencilStateWithDescriptor:depthStencilDescriptor]; 63 | 64 | NSError * error = nil; 65 | _renderPipelineState = [_device newRenderPipelineStateWithDescriptor:descriptor error:&error]; 66 | 67 | if( !_renderPipelineState ){ 68 | NSLog(@"Fail to create pipeline"); 69 | } 70 | } 71 | 72 | - (void) makeResource { 73 | NSURL * modelURL = [[NSBundle mainBundle] URLForResource:@"teapot" withExtension:@"obj"]; 74 | OBJModel * model = [[OBJModel alloc] initWithContentsOfURL:modelURL generateNormals:YES]; 75 | OBJGroup * group = [model groupForName:@"teapot"]; 76 | 77 | _mesh = [[OBJMesh alloc] initWithGroup:group device:_device]; 78 | 79 | _uniformBuffer = [_device newBufferWithLength:sizeof(Uniforms) * InFlightBufferCount options:MTLResourceCPUCacheModeDefaultCache]; 80 | } 81 | 82 | - (void) updateUniformsForView :(UIMetalView*)view duration:(NSTimeInterval)duration { 83 | _time += duration; 84 | _rotationX += duration * (M_PI/2); 85 | _rotationY += duration * (M_PI/3); 86 | float scaleFactor = 1; 87 | static const vector_float3 xAxis = { 1, 0, 0 }; 88 | static const vector_float3 yAxis = { 0, 1, 0 }; 89 | const matrix_float4x4 xRot = matrix_float4x4_rotation(xAxis, _rotationX); 90 | const matrix_float4x4 yRot = matrix_float4x4_rotation(yAxis, _rotationY); 91 | const matrix_float4x4 scale = matrix_float4x4_uniform_scale(scaleFactor); 92 | const matrix_float4x4 modelMatrix = matrix_multiply(matrix_multiply(xRot, yRot), scale); 93 | 94 | const vector_float3 cameraTranslation = { 0, 0, -1.5 }; 95 | const matrix_float4x4 viewMatrix = matrix_float4x4_translation(cameraTranslation); 96 | 97 | const CGSize drawableSize = view.metalLayer.drawableSize; 98 | const float aspect = drawableSize.width / drawableSize.height; 99 | const float fov = 2 * M_PI / 5; 100 | const float near = 0.1; 101 | const float far = 100; 102 | const matrix_float4x4 projectionMatrix = matrix_float4x4_perspective(aspect, fov, near, far); 103 | 104 | Uniforms uniforms; 105 | uniforms.modelViewMatrix = matrix_multiply(viewMatrix, modelMatrix); 106 | uniforms.modelViewProjectionMatrix = matrix_multiply(projectionMatrix, uniforms.modelViewMatrix); 107 | uniforms.normalMatrix = matrix_float4x4_extract_linear(uniforms.modelViewMatrix); 108 | 109 | const NSUInteger uniformBufferOffset = sizeof(Uniforms) * _bufferIndex; 110 | memcpy([_uniformBuffer contents] + uniformBufferOffset, &uniforms, sizeof(uniforms)); 111 | } 112 | 113 | - (void) drawInView:(UIMetalView *)view { 114 | dispatch_semaphore_wait(_displaySemaphore, DISPATCH_TIME_FOREVER); 115 | 116 | view.clearColor = MTLClearColorMake(0.95, 0.95, 0.95, 1); 117 | [self updateUniformsForView:view duration:view.frameDuration]; 118 | 119 | id commandBuffer = [_commandQueue commandBuffer]; 120 | MTLRenderPassDescriptor * renderPassDescriptor = [view currentRenderPassDescriptor]; 121 | id renderCommandEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; 122 | 123 | [renderCommandEncoder setRenderPipelineState:_renderPipelineState]; 124 | [renderCommandEncoder setDepthStencilState:_depthStencilState]; 125 | [renderCommandEncoder setFrontFacingWinding:MTLWindingCounterClockwise]; 126 | [renderCommandEncoder setCullMode:MTLCullModeBack]; 127 | 128 | const NSUInteger uniformBufferOffset = sizeof(Uniforms) * _bufferIndex; 129 | [renderCommandEncoder setVertexBuffer:_mesh.vertexBuffer offset:0 atIndex:0]; 130 | [renderCommandEncoder setVertexBuffer:self.uniformBuffer offset:uniformBufferOffset atIndex:1]; 131 | 132 | [renderCommandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:[_mesh.indexBuffer length]/sizeof(VertexIndex) indexType:VertexIndexType indexBuffer:_mesh.indexBuffer indexBufferOffset:0]; 133 | [renderCommandEncoder endEncoding]; 134 | 135 | [commandBuffer presentDrawable:view.currentDrawable]; 136 | 137 | [commandBuffer addCompletedHandler:^(id commandBuffer) { 138 | self.bufferIndex = (self.bufferIndex + 1) % InFlightBufferCount; 139 | dispatch_semaphore_signal(_displaySemaphore); 140 | }]; 141 | 142 | [commandBuffer commit]; 143 | } 144 | 145 | @end 146 | -------------------------------------------------------------------------------- /Draw3d/Draw3d/MetalRender.m: -------------------------------------------------------------------------------- 1 | // 2 | // MetalRender.m 3 | // Draw3d 4 | // 5 | // Created by Volvet Zhang on 16/3/20. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | 10 | @import QuartzCore; 11 | @import Metal; 12 | @import simd; 13 | 14 | #import "MetalRender.h" 15 | #import "MathUtility.h" 16 | 17 | const static NSInteger InFlightBufferCount = 3; 18 | 19 | typedef uint16_t VerticeIndex; 20 | 21 | typedef struct 22 | { 23 | vector_float4 position; 24 | vector_float4 color; 25 | } Vertex; 26 | 27 | typedef struct 28 | { 29 | matrix_float4x4 modelViewProjectionMatrix; 30 | } Uniforms; 31 | 32 | @interface MetalRender() 33 | 34 | @property (strong) id mDevice; 35 | @property (strong) id mVertexBuffer; 36 | @property (strong) id mIndexBuffer; 37 | @property (strong) id mUniformBuffer; 38 | @property (strong) id mCommandQueue; 39 | @property (strong) id mPipeline; 40 | @property (strong) id mDepthStencilState; 41 | @property (strong) dispatch_semaphore_t mDisplaySemaphore; 42 | @property (assign) NSInteger mBufferIndex; 43 | @property (assign) float mRotateX, mRotateY, mTime; 44 | 45 | @end 46 | 47 | @implementation MetalRender 48 | 49 | 50 | - (instancetype) init { 51 | if( self = [super init] ){ 52 | _mDevice = MTLCreateSystemDefaultDevice(); 53 | _mDisplaySemaphore = dispatch_semaphore_create(InFlightBufferCount); 54 | _mTime = 0.0; 55 | 56 | [self mtlPipelineInit]; 57 | [self mtlBufferInit]; 58 | } 59 | 60 | return self; 61 | } 62 | 63 | - (void) mtlPipelineInit { 64 | _mCommandQueue = [_mDevice newCommandQueue]; 65 | 66 | id library = [_mDevice newDefaultLibrary]; 67 | 68 | MTLRenderPipelineDescriptor * pipeDescriptor = [MTLRenderPipelineDescriptor new]; 69 | 70 | pipeDescriptor.vertexFunction = [library newFunctionWithName:@"vertex_main"]; 71 | pipeDescriptor.fragmentFunction = [library newFunctionWithName:@"fragment_main"]; 72 | pipeDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; 73 | pipeDescriptor.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float; 74 | NSError * error = nil; 75 | _mPipeline = [_mDevice newRenderPipelineStateWithDescriptor:pipeDescriptor error:&error]; 76 | 77 | MTLDepthStencilDescriptor * depthStencilDescriptor = [MTLDepthStencilDescriptor new]; 78 | depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionLess; 79 | depthStencilDescriptor.depthWriteEnabled = YES; 80 | _mDepthStencilState = [_mDevice newDepthStencilStateWithDescriptor:depthStencilDescriptor]; 81 | 82 | if( !_mPipeline ){ 83 | NSLog(@"mtlPipelineInit: fail to create render pipeline, error: %@", error); 84 | } 85 | } 86 | 87 | - (void) mtlBufferInit { 88 | static const Vertex vertices[] = 89 | { 90 | { .position = { -1, 1, 1, 1 }, .color = { 0, 1, 1, 1 } }, 91 | { .position = { -1, -1, 1, 1 }, .color = { 0, 0, 1, 1 } }, 92 | { .position = { 1, -1, 1, 1 }, .color = { 1, 0, 1, 1 } }, 93 | { .position = { 1, 1, 1, 1 }, .color = { 1, 1, 1, 1 } }, 94 | { .position = { -1, 1, -1, 1 }, .color = { 0, 1, 0, 1 } }, 95 | { .position = { -1, -1, -1, 1 }, .color = { 0, 0, 0, 1 } }, 96 | { .position = { 1, -1, -1, 1 }, .color = { 1, 0, 0, 1 } }, 97 | { .position = { 1, 1, -1, 1 }, .color = { 1, 1, 0, 1 } } 98 | }; 99 | 100 | static const VerticeIndex indices[] = 101 | { 102 | 3, 2, 6, 6, 7, 3, 103 | 4, 5, 1, 1, 0, 4, 104 | 4, 0, 3, 3, 7, 4, 105 | 1, 5, 6, 6, 2, 1, 106 | 0, 1, 2, 2, 3, 0, 107 | 7, 6, 5, 5, 4, 7 108 | }; 109 | 110 | _mVertexBuffer = [_mDevice newBufferWithBytes:vertices 111 | length:sizeof(vertices) 112 | options:MTLResourceOptionCPUCacheModeDefault]; 113 | [_mVertexBuffer setLabel:@"Vertices"]; 114 | 115 | _mIndexBuffer = [_mDevice newBufferWithBytes:indices 116 | length:sizeof(indices) 117 | options:MTLResourceOptionCPUCacheModeDefault]; 118 | [_mIndexBuffer setLabel:@"Indices"]; 119 | 120 | _mUniformBuffer = [_mDevice newBufferWithLength:sizeof(Uniforms) * InFlightBufferCount 121 | options:MTLResourceOptionCPUCacheModeDefault]; 122 | [_mUniformBuffer setLabel:@"Uniforms"]; 123 | } 124 | 125 | - (void)updateUniformsForView:(MetalView *)view duration:(NSTimeInterval)duration 126 | { 127 | _mTime += duration; 128 | _mRotateX += duration * (M_PI / 4); 129 | _mRotateY += duration * (M_PI / 5); 130 | float scaleFactor = sinf(0.5 * _mTime) * 0.25 + 1; 131 | const vector_float3 xAxis = { 1, 0, 0 }; 132 | const vector_float3 yAxis = { 0, 1, 0 }; 133 | const matrix_float4x4 xRot = matrix_float4x4_rotation(xAxis, _mRotateX); 134 | const matrix_float4x4 yRot = matrix_float4x4_rotation(yAxis, _mRotateY); 135 | const matrix_float4x4 scale = matrix_float4x4_uniform_scale(scaleFactor); 136 | const matrix_float4x4 modelMatrix = matrix_multiply(matrix_multiply(xRot, yRot), scale); 137 | 138 | const vector_float3 cameraTranslation = { 0, 0, -5 }; 139 | const matrix_float4x4 viewMatrix = matrix_float4x4_translation(cameraTranslation); 140 | 141 | const CGSize drawableSize = view.metalLayer.drawableSize; 142 | const float aspect = drawableSize.width / drawableSize.height; 143 | const float fov = (2 * M_PI) / 5; 144 | const float near = 1; 145 | const float far = 100; 146 | const matrix_float4x4 projectionMatrix = matrix_float4x4_perspective(aspect, fov, near, far); 147 | 148 | Uniforms uniforms; 149 | uniforms.modelViewProjectionMatrix = matrix_multiply(projectionMatrix, matrix_multiply(viewMatrix, modelMatrix)); 150 | 151 | const NSUInteger uniformBufferOffset = sizeof(Uniforms) * _mBufferIndex; 152 | memcpy([_mUniformBuffer contents] + uniformBufferOffset, &uniforms, sizeof(uniforms)); 153 | } 154 | 155 | - (void)drawInView:(MetalView *)view 156 | { 157 | dispatch_semaphore_wait(_mDisplaySemaphore, DISPATCH_TIME_FOREVER); 158 | 159 | view.mClearColor = MTLClearColorMake(0.3, 0.3, 0.3, 1); 160 | 161 | [self updateUniformsForView:view duration:view.mFrameDuration]; 162 | 163 | id commandBuffer = [_mCommandQueue commandBuffer]; 164 | 165 | MTLRenderPassDescriptor *passDescriptor = [view currentRenderPassDescriptor]; 166 | 167 | id renderPass = [commandBuffer renderCommandEncoderWithDescriptor:passDescriptor]; 168 | [renderPass setRenderPipelineState:_mPipeline]; 169 | [renderPass setDepthStencilState:_mDepthStencilState]; 170 | [renderPass setFrontFacingWinding:MTLWindingCounterClockwise]; 171 | [renderPass setCullMode:MTLCullModeBack]; 172 | 173 | const NSUInteger uniformBufferOffset = sizeof(Uniforms) * _mBufferIndex; 174 | 175 | [renderPass setVertexBuffer:_mVertexBuffer offset:0 atIndex:0]; 176 | [renderPass setVertexBuffer:_mUniformBuffer offset:uniformBufferOffset atIndex:1]; 177 | 178 | [renderPass drawIndexedPrimitives:MTLPrimitiveTypeTriangle 179 | indexCount:[_mIndexBuffer length] / sizeof(VerticeIndex) 180 | indexType:MTLIndexTypeUInt16 181 | indexBuffer:_mIndexBuffer 182 | indexBufferOffset:0]; 183 | 184 | [renderPass endEncoding]; 185 | 186 | [commandBuffer presentDrawable:view.mCurrentDrawable]; 187 | 188 | [commandBuffer addCompletedHandler:^(id commandBuffer) { 189 | _mBufferIndex = (_mBufferIndex + 1) % InFlightBufferCount; 190 | dispatch_semaphore_signal(_mDisplaySemaphore); 191 | }]; 192 | 193 | [commandBuffer commit]; 194 | } 195 | 196 | 197 | @end -------------------------------------------------------------------------------- /Teapot/Teapot/OBJModel.mm: -------------------------------------------------------------------------------- 1 | // 2 | // OBJModel.m 3 | // Teapot 4 | // 5 | // Created by Volvet Zhang on 16/3/27. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | #import "typedef.h" 17 | #import "OBJGroup.h" 18 | #import "OBJModel.h" 19 | 20 | struct FaceVertex 21 | { 22 | FaceVertex() { 23 | vi = ti = ni = 0; 24 | } 25 | 26 | uint16_t vi, ti, ni; 27 | }; 28 | 29 | static bool operator < (const FaceVertex & left, const FaceVertex & right) { 30 | if( left.vi < right.vi ) return true; 31 | else if( left.vi > right.vi ) return false; 32 | else if( left.ti < right.ti ) return true; 33 | else if( left.ti > right.ti ) return false; 34 | else if( left.ni < right.ni ) return true; 35 | else if( left.ni > right.ni ) return false; 36 | else return false; 37 | } 38 | 39 | //static bool operator > (const FaceVertex & left, const FaceVertex & right) { 40 | // return ! (left < right); 41 | //} 42 | 43 | 44 | @interface OBJModel() 45 | { 46 | std::vector vertices; 47 | std::vector normals; 48 | std::vector texCoords; 49 | std::vector groupVertices; 50 | std::vector groupIndices; 51 | std::map vertexToGrupIndexMap; 52 | } 53 | 54 | @property (nonatomic, strong) NSMutableArray * mutableGroups; 55 | @property (nonatomic, weak) OBJGroup * currentGroup; 56 | @property (nonatomic, assign) BOOL shouldGenerateNormals; 57 | 58 | @end 59 | 60 | @implementation OBJModel 61 | 62 | - (instancetype) initWithContentsOfURL :(NSURL*)fileUrl generateNormals:(BOOL)generateNormals { 63 | if( self = [super init] ){ 64 | _shouldGenerateNormals = generateNormals; 65 | _mutableGroups = [NSMutableArray array]; 66 | [self parseModelAtURL :fileUrl]; 67 | } 68 | 69 | return self; 70 | } 71 | 72 | - (OBJGroup*) groupForName :(NSString*)groupName { 73 | __block OBJGroup * group = nil; 74 | 75 | [_mutableGroups enumerateObjectsUsingBlock:^(OBJGroup * objGroup, NSUInteger idx, BOOL * stop){ 76 | if( [objGroup.name isEqualToString:groupName] ){ 77 | group = objGroup; 78 | *stop = YES; 79 | } 80 | }]; 81 | 82 | return group; 83 | } 84 | 85 | 86 | - (void) addVertexToCurrentGroup :(FaceVertex)fv { 87 | static const vector_float4 UP = { 0, 1, 0, 0 }; 88 | static const uint16_t INVALID_INDEX = 0xffff; 89 | 90 | uint16_t groupIndex; 91 | auto it = vertexToGrupIndexMap.find(fv); 92 | if( it != vertexToGrupIndexMap.end() ){ 93 | groupIndex = (*it).second; 94 | } else { 95 | Vertex vertex; 96 | vertex.position = vertices[fv.vi]; 97 | vertex.normal = (fv.ni != INVALID_INDEX) ? normals[fv.ni] : UP; 98 | 99 | groupVertices.push_back(vertex); 100 | groupIndex = groupVertices.size() - 1; 101 | vertexToGrupIndexMap[fv] = groupIndex; 102 | } 103 | 104 | groupIndices.push_back(groupIndex); 105 | } 106 | 107 | - (void) addFaceWithFaceVertices :(const std::vector &)faceVertices { 108 | for( size_t i = 0; i < faceVertices.size() - 2; i++ ) { 109 | [self addVertexToCurrentGroup :faceVertices[i]]; 110 | [self addVertexToCurrentGroup :faceVertices[i+1]]; 111 | [self addVertexToCurrentGroup :faceVertices[i+2]]; 112 | } 113 | } 114 | 115 | - (void) generateNormalsForCurrentGroup { 116 | static const vector_float4 ZERO = { 0, 0, 0, 0 }; 117 | 118 | size_t i; 119 | size_t vertexCount = groupVertices.size(); 120 | 121 | for( i=0;iposition.xyz; 136 | vector_float3 p1 = v1->position.xyz; 137 | vector_float3 p2 = v2->position.xyz; 138 | 139 | vector_float3 cross = vector_cross(p1-p0, p2-p0); 140 | vector_float4 cross4 = { cross.x, cross.y, cross.z, 0 }; 141 | 142 | v0->normal += cross4; 143 | v1->normal += cross4; 144 | v2->normal += cross4; 145 | } 146 | 147 | for( i=0;i faceVertices; 232 | faceVertices.reserve(4); 233 | 234 | while(true) { 235 | int32_t vi = 0, ti = 0, ni = 0; 236 | if( ![scanner scanInt:&vi] ){ 237 | break; 238 | } 239 | if( [scanner scanString:@"/" intoString:nil] ){ 240 | [scanner scanInt:&ti]; 241 | 242 | if( [scanner scanString:@"/" intoString:nil] ) { 243 | [scanner scanInt:&ni]; 244 | } 245 | } 246 | FaceVertex faceVertex; 247 | faceVertex.vi = (vi<0) ? (vertices.size() + vi - 1) : (vi - 1); 248 | faceVertex.ti = (ti<0) ? (texCoords.size() + ti - 1) : (ti - 1); 249 | faceVertex.ni = (ni<0) ? (vertices.size() + ni - 1) : (ni - 1); 250 | 251 | faceVertices.push_back(faceVertex); 252 | } 253 | [self addFaceWithFaceVertices:faceVertices]; 254 | } else if( [token isEqualToString:@"g"] ){ 255 | NSString * groupName = nil; 256 | if( [scanner scanUpToCharactersFromSet:endlineSet intoString:&groupName] ){ 257 | [self beginGroupWithName:groupName]; 258 | } 259 | } 260 | } 261 | [self endCurrentGroup]; 262 | } 263 | 264 | 265 | @end 266 | -------------------------------------------------------------------------------- /HelloMetal/HelloMetal.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1483CCC91C8A9622003E8891 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1483CCC81C8A9622003E8891 /* main.m */; }; 11 | 1483CCCC1C8A9622003E8891 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1483CCCB1C8A9622003E8891 /* AppDelegate.m */; }; 12 | 1483CCCF1C8A9622003E8891 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1483CCCE1C8A9622003E8891 /* ViewController.m */; }; 13 | 1483CCD21C8A9622003E8891 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1483CCD01C8A9622003E8891 /* Main.storyboard */; }; 14 | 1483CCD41C8A9622003E8891 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1483CCD31C8A9622003E8891 /* Assets.xcassets */; }; 15 | 1483CCD71C8A9622003E8891 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1483CCD51C8A9622003E8891 /* LaunchScreen.storyboard */; }; 16 | 1483CD131C8ADEFF003E8891 /* VideoMetalView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1483CD121C8ADEFF003E8891 /* VideoMetalView.m */; }; 17 | 1483CD151C8C6721003E8891 /* photo_night.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1483CD141C8C6721003E8891 /* photo_night.jpg */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 1483CCC41C8A9622003E8891 /* HelloMetal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HelloMetal.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 1483CCC81C8A9622003E8891 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 23 | 1483CCCA1C8A9622003E8891 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 24 | 1483CCCB1C8A9622003E8891 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 25 | 1483CCCD1C8A9622003E8891 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 26 | 1483CCCE1C8A9622003E8891 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 27 | 1483CCD11C8A9622003E8891 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 28 | 1483CCD31C8A9622003E8891 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 29 | 1483CCD61C8A9622003E8891 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 30 | 1483CCD81C8A9622003E8891 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | 1483CD111C8ADEFE003E8891 /* VideoMetalView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoMetalView.h; sourceTree = ""; }; 32 | 1483CD121C8ADEFF003E8891 /* VideoMetalView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VideoMetalView.m; sourceTree = ""; }; 33 | 1483CD141C8C6721003E8891 /* photo_night.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = photo_night.jpg; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 1483CCC11C8A9622003E8891 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 1483CCBB1C8A9621003E8891 = { 48 | isa = PBXGroup; 49 | children = ( 50 | 1483CCC61C8A9622003E8891 /* HelloMetal */, 51 | 1483CCC51C8A9622003E8891 /* Products */, 52 | ); 53 | sourceTree = ""; 54 | }; 55 | 1483CCC51C8A9622003E8891 /* Products */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | 1483CCC41C8A9622003E8891 /* HelloMetal.app */, 59 | ); 60 | name = Products; 61 | sourceTree = ""; 62 | }; 63 | 1483CCC61C8A9622003E8891 /* HelloMetal */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 1483CD141C8C6721003E8891 /* photo_night.jpg */, 67 | 1483CCCA1C8A9622003E8891 /* AppDelegate.h */, 68 | 1483CCCB1C8A9622003E8891 /* AppDelegate.m */, 69 | 1483CCCD1C8A9622003E8891 /* ViewController.h */, 70 | 1483CCCE1C8A9622003E8891 /* ViewController.m */, 71 | 1483CCD01C8A9622003E8891 /* Main.storyboard */, 72 | 1483CCD31C8A9622003E8891 /* Assets.xcassets */, 73 | 1483CCD51C8A9622003E8891 /* LaunchScreen.storyboard */, 74 | 1483CCD81C8A9622003E8891 /* Info.plist */, 75 | 1483CCC71C8A9622003E8891 /* Supporting Files */, 76 | 1483CD111C8ADEFE003E8891 /* VideoMetalView.h */, 77 | 1483CD121C8ADEFF003E8891 /* VideoMetalView.m */, 78 | ); 79 | path = HelloMetal; 80 | sourceTree = ""; 81 | }; 82 | 1483CCC71C8A9622003E8891 /* Supporting Files */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 1483CCC81C8A9622003E8891 /* main.m */, 86 | ); 87 | name = "Supporting Files"; 88 | sourceTree = ""; 89 | }; 90 | /* End PBXGroup section */ 91 | 92 | /* Begin PBXNativeTarget section */ 93 | 1483CCC31C8A9622003E8891 /* HelloMetal */ = { 94 | isa = PBXNativeTarget; 95 | buildConfigurationList = 1483CCDB1C8A9622003E8891 /* Build configuration list for PBXNativeTarget "HelloMetal" */; 96 | buildPhases = ( 97 | 1483CCC01C8A9622003E8891 /* Sources */, 98 | 1483CCC11C8A9622003E8891 /* Frameworks */, 99 | 1483CCC21C8A9622003E8891 /* Resources */, 100 | ); 101 | buildRules = ( 102 | ); 103 | dependencies = ( 104 | ); 105 | name = HelloMetal; 106 | productName = HelloMetal; 107 | productReference = 1483CCC41C8A9622003E8891 /* HelloMetal.app */; 108 | productType = "com.apple.product-type.application"; 109 | }; 110 | /* End PBXNativeTarget section */ 111 | 112 | /* Begin PBXProject section */ 113 | 1483CCBC1C8A9621003E8891 /* Project object */ = { 114 | isa = PBXProject; 115 | attributes = { 116 | LastUpgradeCheck = 0720; 117 | ORGANIZATIONNAME = "Volvet Zhang"; 118 | TargetAttributes = { 119 | 1483CCC31C8A9622003E8891 = { 120 | CreatedOnToolsVersion = 7.2.1; 121 | DevelopmentTeam = E6HMU725M5; 122 | }; 123 | }; 124 | }; 125 | buildConfigurationList = 1483CCBF1C8A9621003E8891 /* Build configuration list for PBXProject "HelloMetal" */; 126 | compatibilityVersion = "Xcode 3.2"; 127 | developmentRegion = English; 128 | hasScannedForEncodings = 0; 129 | knownRegions = ( 130 | en, 131 | Base, 132 | ); 133 | mainGroup = 1483CCBB1C8A9621003E8891; 134 | productRefGroup = 1483CCC51C8A9622003E8891 /* Products */; 135 | projectDirPath = ""; 136 | projectRoot = ""; 137 | targets = ( 138 | 1483CCC31C8A9622003E8891 /* HelloMetal */, 139 | ); 140 | }; 141 | /* End PBXProject section */ 142 | 143 | /* Begin PBXResourcesBuildPhase section */ 144 | 1483CCC21C8A9622003E8891 /* Resources */ = { 145 | isa = PBXResourcesBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | 1483CCD71C8A9622003E8891 /* LaunchScreen.storyboard in Resources */, 149 | 1483CD151C8C6721003E8891 /* photo_night.jpg in Resources */, 150 | 1483CCD41C8A9622003E8891 /* Assets.xcassets in Resources */, 151 | 1483CCD21C8A9622003E8891 /* Main.storyboard in Resources */, 152 | ); 153 | runOnlyForDeploymentPostprocessing = 0; 154 | }; 155 | /* End PBXResourcesBuildPhase section */ 156 | 157 | /* Begin PBXSourcesBuildPhase section */ 158 | 1483CCC01C8A9622003E8891 /* Sources */ = { 159 | isa = PBXSourcesBuildPhase; 160 | buildActionMask = 2147483647; 161 | files = ( 162 | 1483CD131C8ADEFF003E8891 /* VideoMetalView.m in Sources */, 163 | 1483CCCF1C8A9622003E8891 /* ViewController.m in Sources */, 164 | 1483CCCC1C8A9622003E8891 /* AppDelegate.m in Sources */, 165 | 1483CCC91C8A9622003E8891 /* main.m in Sources */, 166 | ); 167 | runOnlyForDeploymentPostprocessing = 0; 168 | }; 169 | /* End PBXSourcesBuildPhase section */ 170 | 171 | /* Begin PBXVariantGroup section */ 172 | 1483CCD01C8A9622003E8891 /* Main.storyboard */ = { 173 | isa = PBXVariantGroup; 174 | children = ( 175 | 1483CCD11C8A9622003E8891 /* Base */, 176 | ); 177 | name = Main.storyboard; 178 | sourceTree = ""; 179 | }; 180 | 1483CCD51C8A9622003E8891 /* LaunchScreen.storyboard */ = { 181 | isa = PBXVariantGroup; 182 | children = ( 183 | 1483CCD61C8A9622003E8891 /* Base */, 184 | ); 185 | name = LaunchScreen.storyboard; 186 | sourceTree = ""; 187 | }; 188 | /* End PBXVariantGroup section */ 189 | 190 | /* Begin XCBuildConfiguration section */ 191 | 1483CCD91C8A9622003E8891 /* Debug */ = { 192 | isa = XCBuildConfiguration; 193 | buildSettings = { 194 | ALWAYS_SEARCH_USER_PATHS = NO; 195 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 196 | CLANG_CXX_LIBRARY = "libc++"; 197 | CLANG_ENABLE_MODULES = YES; 198 | CLANG_ENABLE_OBJC_ARC = YES; 199 | CLANG_WARN_BOOL_CONVERSION = YES; 200 | CLANG_WARN_CONSTANT_CONVERSION = YES; 201 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 202 | CLANG_WARN_EMPTY_BODY = YES; 203 | CLANG_WARN_ENUM_CONVERSION = YES; 204 | CLANG_WARN_INT_CONVERSION = YES; 205 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 206 | CLANG_WARN_UNREACHABLE_CODE = YES; 207 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 208 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 209 | COPY_PHASE_STRIP = NO; 210 | DEBUG_INFORMATION_FORMAT = dwarf; 211 | ENABLE_STRICT_OBJC_MSGSEND = YES; 212 | ENABLE_TESTABILITY = YES; 213 | GCC_C_LANGUAGE_STANDARD = gnu99; 214 | GCC_DYNAMIC_NO_PIC = NO; 215 | GCC_NO_COMMON_BLOCKS = YES; 216 | GCC_OPTIMIZATION_LEVEL = 0; 217 | GCC_PREPROCESSOR_DEFINITIONS = ( 218 | "DEBUG=1", 219 | "$(inherited)", 220 | ); 221 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 222 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 223 | GCC_WARN_UNDECLARED_SELECTOR = YES; 224 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 225 | GCC_WARN_UNUSED_FUNCTION = YES; 226 | GCC_WARN_UNUSED_VARIABLE = YES; 227 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 228 | MTL_ENABLE_DEBUG_INFO = YES; 229 | ONLY_ACTIVE_ARCH = YES; 230 | SDKROOT = iphoneos; 231 | TARGETED_DEVICE_FAMILY = "1,2"; 232 | }; 233 | name = Debug; 234 | }; 235 | 1483CCDA1C8A9622003E8891 /* Release */ = { 236 | isa = XCBuildConfiguration; 237 | buildSettings = { 238 | ALWAYS_SEARCH_USER_PATHS = NO; 239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 240 | CLANG_CXX_LIBRARY = "libc++"; 241 | CLANG_ENABLE_MODULES = YES; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | CLANG_WARN_BOOL_CONVERSION = YES; 244 | CLANG_WARN_CONSTANT_CONVERSION = YES; 245 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 246 | CLANG_WARN_EMPTY_BODY = YES; 247 | CLANG_WARN_ENUM_CONVERSION = YES; 248 | CLANG_WARN_INT_CONVERSION = YES; 249 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 250 | CLANG_WARN_UNREACHABLE_CODE = YES; 251 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 252 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 253 | COPY_PHASE_STRIP = NO; 254 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 255 | ENABLE_NS_ASSERTIONS = NO; 256 | ENABLE_STRICT_OBJC_MSGSEND = YES; 257 | GCC_C_LANGUAGE_STANDARD = gnu99; 258 | GCC_NO_COMMON_BLOCKS = YES; 259 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 260 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 261 | GCC_WARN_UNDECLARED_SELECTOR = YES; 262 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 263 | GCC_WARN_UNUSED_FUNCTION = YES; 264 | GCC_WARN_UNUSED_VARIABLE = YES; 265 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 266 | MTL_ENABLE_DEBUG_INFO = NO; 267 | SDKROOT = iphoneos; 268 | TARGETED_DEVICE_FAMILY = "1,2"; 269 | VALIDATE_PRODUCT = YES; 270 | }; 271 | name = Release; 272 | }; 273 | 1483CCDC1C8A9622003E8891 /* Debug */ = { 274 | isa = XCBuildConfiguration; 275 | buildSettings = { 276 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 277 | INFOPLIST_FILE = HelloMetal/Info.plist; 278 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 279 | PRODUCT_BUNDLE_IDENTIFIER = Volvet.HelloMetal; 280 | PRODUCT_NAME = "$(TARGET_NAME)"; 281 | }; 282 | name = Debug; 283 | }; 284 | 1483CCDD1C8A9622003E8891 /* Release */ = { 285 | isa = XCBuildConfiguration; 286 | buildSettings = { 287 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 288 | INFOPLIST_FILE = HelloMetal/Info.plist; 289 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 290 | PRODUCT_BUNDLE_IDENTIFIER = Volvet.HelloMetal; 291 | PRODUCT_NAME = "$(TARGET_NAME)"; 292 | }; 293 | name = Release; 294 | }; 295 | /* End XCBuildConfiguration section */ 296 | 297 | /* Begin XCConfigurationList section */ 298 | 1483CCBF1C8A9621003E8891 /* Build configuration list for PBXProject "HelloMetal" */ = { 299 | isa = XCConfigurationList; 300 | buildConfigurations = ( 301 | 1483CCD91C8A9622003E8891 /* Debug */, 302 | 1483CCDA1C8A9622003E8891 /* Release */, 303 | ); 304 | defaultConfigurationIsVisible = 0; 305 | defaultConfigurationName = Release; 306 | }; 307 | 1483CCDB1C8A9622003E8891 /* Build configuration list for PBXNativeTarget "HelloMetal" */ = { 308 | isa = XCConfigurationList; 309 | buildConfigurations = ( 310 | 1483CCDC1C8A9622003E8891 /* Debug */, 311 | 1483CCDD1C8A9622003E8891 /* Release */, 312 | ); 313 | defaultConfigurationIsVisible = 0; 314 | }; 315 | /* End XCConfigurationList section */ 316 | }; 317 | rootObject = 1483CCBC1C8A9621003E8891 /* Project object */; 318 | } 319 | --------------------------------------------------------------------------------