├── .gitignore ├── screenshots └── 01.png ├── ScenekitStarter ├── EnvMap.png ├── FringeMap.png ├── EnvMapInterior.png ├── GameView.h ├── CWHLightingView.h ├── main.m ├── GameView.m ├── CWHLightingView.m ├── AppDelegate.h ├── CWHParameterViewProtocol.h ├── CWHHemisphereProgram.h ├── CWHLightingViewController.h ├── CWHParameterViewController.h ├── GameViewController.h ├── CWHBlinnProgram.h ├── CWHThinFilmProgram.h ├── CWHEnvMapProgram.h ├── CWHVelvetProgram.h ├── CWHLambSkinProgram.h ├── CWHPhongPointLightProgram.h ├── CWHGoochProgram.h ├── CWHLUTSkinProgram.h ├── CWHEdgeFuzzProgram.h ├── CWHLightingProgram.h ├── CWHGlossyWetHighlightProgram.h ├── CWHBlinnParameterViewController.h ├── CWHHemisphereParameterViewController.h ├── CWHThinFilmParameterViewController.h ├── CWHLightingModelWindowController.h ├── CWHVelvetParameterViewController.h ├── CWHParameterViewController.m ├── CWHEnvMapParameterViewController.h ├── CWHLambSkinParameterViewController.h ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── CWHLUTSkinParameterViewController.h ├── AppDelegate.m ├── CWHPhongPointLightParameterViewController.h ├── CWHGoochParameterViewController.h ├── CWHHemisphereParameterViewController.m ├── CWHGlossyWetHighlightParameterViewController.h ├── CWHEdgeFuzzParameterViewController.h ├── CWHBlinnParameterViewController.m ├── Hemisphere.metal ├── CWHThinFilmParameterViewController.m ├── CWHLightingView.xib ├── Blinn.metal ├── Gooch.metal ├── CWHLightingViewController.m ├── LambSkin.metal ├── GameViewController.m ├── CWHVelvetParameterViewController.m ├── Velvet.metal ├── CWHLambSkinParameterViewController.m ├── LUTSkin.metal ├── Phong.metal ├── CWHLightingProgram.m ├── CWHEnvMapParameterViewController.m ├── CWHHemisphereProgram.m ├── CWHPhongPointLightParameterViewController.m ├── EnvMap.metal ├── CWHBlinnProgram.m ├── CWHGoochParameterViewController.m ├── ThinFilm.metal ├── CWHLUTSkinParameterViewController.m ├── HemisphereParameterView.xib ├── BlinnParameterView.xib ├── CWHThinFilmProgram.m ├── EdgeFuzz.metal ├── CWHEnvMapProgram.m ├── CWHEdgeFuzzParameterViewController.m ├── CWHPhongPointLightProgram.m ├── CWHLambSkinProgram.m ├── CWHVelvetProgram.m ├── CWHLUTSkinProgram.m ├── CWHGoochProgram.m ├── ThinFilmParameterView.xib ├── CWHGlossyWetHighlightParameterViewController.m ├── GlossyWetHighlight.metal ├── CWHLightingModelWindowController.m ├── CWHGlossyWetHighlightProgram.m ├── CWHEdgeFuzzProgram.m ├── LambSkinParameterView.xib ├── LightingModelWindow.xib └── VelvetParameterView.xib ├── ScenekitStarter.xcodeproj ├── xcuserdata │ └── super.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── ScenekitStarter.xcscheme ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── ScenekitStarter.xccheckout │ └── xcuserdata │ │ └── super.xcuserdatad │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ └── xcschemes │ └── ScenekitStarter.xcscheme └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | xcuserdata 2 | -------------------------------------------------------------------------------- /screenshots/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metal-by-example/scenekit-lighting-models/HEAD/screenshots/01.png -------------------------------------------------------------------------------- /ScenekitStarter/EnvMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metal-by-example/scenekit-lighting-models/HEAD/ScenekitStarter/EnvMap.png -------------------------------------------------------------------------------- /ScenekitStarter/FringeMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metal-by-example/scenekit-lighting-models/HEAD/ScenekitStarter/FringeMap.png -------------------------------------------------------------------------------- /ScenekitStarter/EnvMapInterior.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/metal-by-example/scenekit-lighting-models/HEAD/ScenekitStarter/EnvMapInterior.png -------------------------------------------------------------------------------- /ScenekitStarter.xcodeproj/xcuserdata/super.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /ScenekitStarter.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ScenekitStarter/GameView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GameView.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/24/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GameView : SCNView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLightingView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GameView.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/24/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CWHLightingView : SCNView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ScenekitStarter.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ScenekitStarter/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/24/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /ScenekitStarter/GameView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GameView.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/24/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "GameView.h" 10 | 11 | @implementation GameView 12 | 13 | -(void)mouseDown:(NSEvent *)theEvent 14 | { 15 | 16 | [super mouseDown:theEvent]; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLightingView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GameView.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/24/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHLightingView.h" 10 | 11 | @implementation CWHLightingView 12 | 13 | -(void)mouseDown:(NSEvent *)theEvent 14 | { 15 | [super mouseDown:theEvent]; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ScenekitStarter/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/24/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class CWHLightingModelWindowController; 12 | 13 | @interface AppDelegate : NSObject 14 | { 15 | CWHLightingModelWindowController *windowController; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHParameterViewProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // ParameterViewProtocol.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/4/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @protocol CWHParameterViewProtocol 13 | - (void)parameterViewWillClose; 14 | - (void)updateProgram:(SCNProgram *)program shadableProperties:(NSDictionary *)properties; 15 | @end 16 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHHemisphereProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHHemisphereProgram.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/31/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHLightingProgram.h" 11 | 12 | @interface CWHHemisphereProgram : CWHLightingProgram 13 | 14 | @property (strong) NSColor *skyColor; 15 | @property (strong) NSColor *groundColor; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLightingViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/24/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "CWHLightingView.h" 12 | 13 | @interface CWHLightingViewController : NSViewController 14 | 15 | @property (weak) IBOutlet CWHLightingView *lightingView; 16 | @property (nonatomic, retain) SCNNode *geometryNode; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHParameterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHParameterViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/14/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "CWHParameterViewProtocol.h" 12 | 13 | @interface CWHParameterViewController : NSViewController 14 | @property (nonatomic, retain) id delegate; 15 | @property (strong) SCNProgram *program; 16 | @end 17 | -------------------------------------------------------------------------------- /ScenekitStarter/GameViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/24/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "GameView.h" 12 | #import "CWHShadingNode.h" 13 | 14 | @interface GameViewController : NSViewController 15 | 16 | @property (assign) IBOutlet GameView *gameView; 17 | @property (nonatomic, retain) CWHShadingNode *torusNode; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHBlinnProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHBlinnProgram.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/29/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHLightingProgram.h" 11 | 12 | @interface CWHBlinnProgram : CWHLightingProgram 13 | 14 | @property (nonatomic, strong) NSColor *lightColor; 15 | @property (nonatomic, strong) NSColor *ambientColor; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | scenekit-lighting-models 2 | ======================== 3 | 4 | Alternate lighting models using custom SCNProgram for SceneKit 5 | 6 | 7 | A demo app for previewing alternate lighting models using a custom SCNProgram with SceneKit. Based on a Quartz Composer conversion of NVIDIA samples from toneburst([machinesdontcare.wordpress.com](http://machinesdontcare.wordpress.com)). 8 | 9 | A [short video](https://vimeo.com/106634143) of the app in action. 10 | 11 | ![A screenshot showing the app in action](screenshots/01.png) -------------------------------------------------------------------------------- /ScenekitStarter/CWHThinFilmProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHThinFilmProgram.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/28/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHLightingProgram.h" 11 | 12 | @interface CWHThinFilmProgram : CWHLightingProgram 13 | 14 | @property (assign) double filmDepth; 15 | @property (strong) NSColor *diffuseColor; 16 | @property (strong) NSString *imagePath; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHEnvMapProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHEnvMapProgram.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/25/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHLightingProgram.h" 11 | 12 | @interface CWHEnvMapProgram : CWHLightingProgram 13 | 14 | @property (strong) NSColor *diffuseColor; 15 | @property (strong) NSColor *ambientColor; 16 | @property (assign) double ratio; 17 | @property (strong) NSString *imagePath; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHVelvetProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHVelvetProgram.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/30/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHLightingProgram.h" 11 | 12 | @interface CWHVelvetProgram : CWHLightingProgram 13 | 14 | @property (strong) NSColor *underColor; 15 | @property (strong) NSColor *fuzzColor; 16 | @property (assign) double rolloff; 17 | @property (strong) NSColor *primaryColor; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLambSkinProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHLambSkinProgram.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/31/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHLightingProgram.h" 11 | 12 | @interface CWHLambSkinProgram : CWHLightingProgram 13 | 14 | @property (strong) NSColor *diffuseColor; 15 | @property (strong) NSColor *ambientColor; 16 | @property (strong) NSColor *subColor; 17 | @property (assign) double rolloff; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHPhongPointLightProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHBlinnProgram.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/29/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHLightingProgram.h" 11 | 12 | @interface CWHPhongPointLightProgram: CWHLightingProgram 13 | 14 | @property (strong) NSColor *lightColor; 15 | @property (strong) NSColor *ambientColor; 16 | 17 | @property (assign) double shininess; 18 | @property (assign) double materialSpecularity; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHGoochProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHBlinnProgram.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/29/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHLightingProgram.h" 11 | 12 | @interface CWHGoochProgram : CWHLightingProgram 13 | 14 | @property (strong) NSColor *surfaceColor; 15 | @property (strong) NSColor *warmColor; 16 | @property (strong) NSColor *coolColor; 17 | @property (assign) double diffuseWarm; 18 | @property (assign) double diffuseCool; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLUTSkinProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHLUTSkinProgram.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/31/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHLightingProgram.h" 11 | 12 | @interface CWHLUTSkinProgram : CWHLightingProgram 13 | 14 | @property (strong) NSColor *diffuseColor; 15 | @property (strong) NSColor *specularColor; 16 | @property (strong) NSColor *scatterColor; 17 | @property (assign) double wrap; 18 | @property (assign) double scatterWidth; 19 | @property (assign) double shininess; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHEdgeFuzzProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHEdgeFuzzProgram.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/31/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHLightingProgram.h" 11 | 12 | @interface CWHEdgeFuzzProgram : CWHLightingProgram 13 | 14 | @property (strong) NSColor *surfaceColor; 15 | @property (strong) NSColor *edgeColor; 16 | @property (strong) NSColor *lightColor; 17 | @property (strong) NSColor *ambientColor; 18 | @property (assign) double fuzziness; 19 | @property (assign) double edgeFade; 20 | @property (assign) double specularity; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLightingProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHLightingProgram.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 9/9/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CWHLightingProgram : SCNProgram 12 | 13 | - (id)initWithProgram:(NSString *)program; 14 | 15 | - (instancetype)initWithLibrary:(id)library 16 | vertexFunctionName:(NSString *)vertexFunctionName 17 | fragmentFunctionName:(NSString *)fragmentFunctionName; 18 | 19 | @property (nonatomic, readonly, copy) NSDictionary *shadableProperties; 20 | 21 | @property (nonatomic, assign) SCNVector3 lightPosition; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ScenekitStarter.xcodeproj/xcuserdata/super.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ScenekitStarter.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | BFB813C51981646100E09822 16 | 17 | primary 18 | 19 | 20 | BFB813E01981646200E09822 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHGlossyWetHighlightProgram.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHGlossyWetHighlightProgram.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/31/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHLightingProgram.h" 11 | 12 | @interface CWHGlossyWetHighlightProgram : CWHLightingProgram 13 | 14 | @property (strong) NSColor *ambientColor; 15 | @property (strong) NSColor *diffuseColor; 16 | @property (strong) NSColor *specularColor; 17 | @property (assign) double specularity; 18 | @property (assign) double specularExponent; 19 | @property (assign) double glossMax; 20 | @property (assign) double glossMin; 21 | @property (assign) double glossDrop; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHBlinnParameterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHBlinnParameterViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/15/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHParameterViewProtocol.h" 11 | #import "CWHParameterViewController.h" 12 | #import "CWHBlinnProgram.h" 13 | 14 | @interface CWHBlinnParameterViewController : CWHParameterViewController 15 | 16 | @property (weak) IBOutlet NSColorWell *ambientColorWell; 17 | @property (strong) NSColor *ambientColor; 18 | - (IBAction)updateAmbientColor:(id)sender; 19 | 20 | @property (weak) IBOutlet NSColorWell *lightColorWell; 21 | @property (strong) NSColor *lightColor; 22 | - (IBAction)updateLightColor:(id)sender; 23 | 24 | 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHHemisphereParameterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHHemisphereParameterViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/21/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHParameterViewProtocol.h" 11 | #import "CWHHemisphereProgram.h" 12 | #import "CWHParameterViewController.h" 13 | 14 | @interface CWHHemisphereParameterViewController : CWHParameterViewController 15 | 16 | @property (weak) IBOutlet NSColorWell *skyColorWell; 17 | @property (strong) NSColor *skyColor; 18 | - (IBAction)updateSkyColor:(id)sender; 19 | 20 | @property (weak) IBOutlet NSColorWell *groundColorWell; 21 | @property (strong) NSColor *groundColor; 22 | - (IBAction)updateGroundColor:(id)sender; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHThinFilmParameterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHThinFilmParameterViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 9/4/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | #import "CWHParameterViewProtocol.h" 12 | #import "CWHThinFilmProgram.h" 13 | #import "CWHParameterViewController.h" 14 | 15 | @interface CWHThinFilmParameterViewController : CWHParameterViewController 16 | 17 | @property (weak) IBOutlet NSSlider *filmDepthSlider; 18 | @property (weak) IBOutlet NSTextField *filmDepthTextField; 19 | @property (weak) IBOutlet NSColorWell *diffuseColorWell; 20 | 21 | @property (assign) double filmDepth; 22 | - (IBAction)updateFilmDepth:(id)sender; 23 | 24 | @property (strong) NSColor *diffuseColor; 25 | - (IBAction)updateDiffuseColor:(id)sender; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ScenekitStarter.xcodeproj/project.xcworkspace/xcuserdata/super.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 12 | 13 | IssueFilterStyle 14 | ShowActiveSchemeOnly 15 | LiveSourceIssuesEnabled 16 | 17 | SnapshotAutomaticallyBeforeSignificantChanges 18 | 19 | SnapshotLocationStyle 20 | Default 21 | 22 | 23 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLightingModelWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHLightingModelWindowController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/1/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHPhongPointLightParameterViewController.h" 11 | @class CWHLightingViewController; 12 | 13 | @interface CWHLightingModelWindowController : NSWindowController 14 | { 15 | __weak IBOutlet NSView *targetView; 16 | } 17 | 18 | @property (weak) IBOutlet NSMenu *lightingModelMenu; 19 | @property (weak) IBOutlet NSPopUpButton *lightingModelPopupButton; 20 | @property (weak) IBOutlet NSToolbarItem *parameterToolbarItem; 21 | -(IBAction)showInputParameters:(id)sender; 22 | -(IBAction)updateLightingModel:(id)sender; 23 | 24 | @property (strong) IBOutlet CWHLightingViewController *lightingViewController; 25 | @property (assign) BOOL lightingParameterState; 26 | @property (strong) NSString *currentLightingModel; 27 | @property (strong) SCNProgram *currentProgram; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHVelvetParameterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHVelvetParamterViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/15/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHVelvetProgram.h" 11 | #import "CWHParameterViewController.h" 12 | 13 | @interface CWHVelvetParameterViewController : CWHParameterViewController 14 | 15 | @property (weak) IBOutlet NSTextField *rolloffTextField; 16 | @property (weak) IBOutlet NSSlider *rolloffCircularSlider; 17 | @property (weak) IBOutlet NSColorWell *underColorWell; 18 | @property (weak) IBOutlet NSColorWell *fuzzColorWell; 19 | @property (weak) IBOutlet NSColorWell *primaryColorWell; 20 | 21 | @property (assign) double rolloff; 22 | - (IBAction)updateRolloff:(id)sender; 23 | 24 | @property (strong) NSColor *underColor; 25 | - (IBAction)updateUnderColor:(id)sender; 26 | 27 | @property (strong) NSColor *fuzzColor; 28 | - (IBAction)updateFuzzColor:(id)sender; 29 | 30 | @property (strong) NSColor *primaryColor; 31 | - (IBAction)updatePrimaryColor:(id)sender; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHParameterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHParameterViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/14/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHParameterViewController.h" 10 | 11 | 12 | @interface CWHParameterViewController () 13 | 14 | @end 15 | 16 | @implementation CWHParameterViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | // Do view setup here. 21 | } 22 | 23 | - (void)popoverWillClose:(NSNotification *)notification 24 | { 25 | 26 | if ([self.delegate respondsToSelector:@selector(parameterViewWillClose)]) { 27 | [self.delegate parameterViewWillClose]; 28 | } 29 | 30 | NSString *closeReason = [[notification userInfo] valueForKey:NSPopoverCloseReasonKey]; 31 | if (closeReason) 32 | { 33 | // closeReason can be: 34 | // NSPopoverCloseReasonStandard 35 | // NSPopoverCloseReasonDetachToWindow 36 | // 37 | // add new code here if you want to respond "before" the popover closes 38 | // 39 | } 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHEnvMapParameterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHEnvMapParameterViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/25/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHParameterViewProtocol.h" 11 | #import "CWHEnvMapProgram.h" 12 | #import "CWHParameterViewController.h" 13 | 14 | @interface CWHEnvMapParameterViewController : CWHParameterViewController 15 | @property (weak) IBOutlet NSSlider *ratioSlider; 16 | @property (weak) IBOutlet NSTextField *ratioTextField; 17 | @property (weak) IBOutlet NSColorWell *ambientColorWell; 18 | @property (weak) IBOutlet NSColorWell *diffuseColorWell; 19 | @property (weak) IBOutlet NSPopUpButton *envMapMenu; 20 | 21 | @property (assign) double ratio; 22 | - (IBAction)updateRatio:(id)sender; 23 | 24 | @property (strong) NSColor *ambientColor; 25 | - (IBAction)updateAmbientColor:(NSColorWell *)sender; 26 | 27 | @property (strong) NSColor *diffuseColor; 28 | - (IBAction)updateDiffuseColor:(NSColorWell *)sender; 29 | 30 | @property (strong) NSString *imagePath; 31 | - (IBAction)updateEnvMap:(id)sender; 32 | @end 33 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLambSkinParameterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHLambSkinParameterViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/21/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHParameterViewProtocol.h" 11 | #import "CWHLambSkinProgram.h" 12 | #import "CWHParameterViewController.h" 13 | 14 | @interface CWHLambSkinParameterViewController : CWHParameterViewController 15 | 16 | @property (assign) double rolloff; 17 | - (IBAction)updateRolloff:(id)sender; 18 | @property (weak) IBOutlet NSSlider *rolloffSlider; 19 | @property (weak) IBOutlet NSTextField *rolloffTextField; 20 | 21 | @property (weak) IBOutlet NSColorWell *ambientColorWell; 22 | @property (strong) NSColor *ambientColor; 23 | - (IBAction)updateAmbientColor:(id)sender; 24 | 25 | @property (weak) IBOutlet NSColorWell *diffuseColorWell; 26 | @property (strong) NSColor *diffuseColor; 27 | - (IBAction)updateDiffuseColor:(id)sender; 28 | 29 | 30 | @property (weak) IBOutlet NSColorWell *subColorWell; 31 | @property (strong) NSColor *subColor; 32 | - (IBAction)updateSubColor:(id)sender; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ScenekitStarter/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /ScenekitStarter/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2014 Creative Workflow Hacks. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLUTSkinParameterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHLUTSkinParameterViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 9/12/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHParameterViewController.h" 10 | #import "CWHLUTSkinProgram.h" 11 | 12 | @interface CWHLUTSkinParameterViewController : CWHParameterViewController 13 | @property (weak) IBOutlet NSSlider *wrapSlider; 14 | @property (weak) IBOutlet NSTextField *wrapTextField; 15 | @property (weak) IBOutlet NSSlider *scatterWidthSlider; 16 | @property (weak) IBOutlet NSTextField *scatterWidthTextField; 17 | @property (weak) IBOutlet NSSlider *shininessSlider; 18 | @property (weak) IBOutlet NSTextField *shininessTextField; 19 | @property (weak) IBOutlet NSColorWell *diffuseColorWell; 20 | @property (weak) IBOutlet NSColorWell *specularColorWell; 21 | @property (weak) IBOutlet NSColorWell *scatterColorWell; 22 | 23 | 24 | - (IBAction)updateWrap:(id)sender; 25 | - (IBAction)updateScatterWidth:(id)sender; 26 | - (IBAction)updateShininess:(id)sender; 27 | - (IBAction)updateDiffuseColor:(id)sender; 28 | - (IBAction)updateSpecularColor:(id)sender; 29 | - (IBAction)updateScatterColor:(id)sender; 30 | 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /ScenekitStarter/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/24/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "CWHLightingModelWindowController.h" 11 | 12 | @implementation AppDelegate 13 | 14 | - (IBAction)newDocument:(id)sender 15 | { 16 | if(windowController == nil) 17 | { 18 | windowController = [[CWHLightingModelWindowController alloc] initWithWindowNibName:@"LightingModelWindow"]; 19 | } 20 | 21 | [windowController showWindow:self]; 22 | } 23 | 24 | - (void)applicationDidFinishLaunching:(NSNotification*)notification 25 | { 26 | [self newDocument:self]; 27 | } 28 | 29 | - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { 30 | return YES; 31 | } 32 | 33 | - (BOOL)validateMenuItem:(NSMenuItem *)theMenuItem 34 | { 35 | BOOL enable = [self respondsToSelector:[theMenuItem action]]; 36 | 37 | // disable "New" if the window is already up 38 | if ([theMenuItem action] == @selector(newDocument:)) 39 | { 40 | if ([[windowController window] isKeyWindow]) 41 | { 42 | enable = NO; 43 | } 44 | } 45 | return enable; 46 | } 47 | 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHPhongPointLightParameterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHPhongPointLightParameterViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/1/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHParameterViewProtocol.h" 11 | #import "CWHPhongPointLightProgram.h" 12 | #import "CWHParameterViewController.h" 13 | 14 | @interface CWHPhongPointLightParameterViewController : CWHParameterViewController 15 | 16 | 17 | @property (weak) IBOutlet NSSlider *specularitySlider; 18 | @property (weak) IBOutlet NSSlider *shininessSlider; 19 | 20 | @property (weak) IBOutlet NSTextField *specularityTextField; 21 | @property (weak) IBOutlet NSTextField *shininessTextField; 22 | 23 | @property (weak) IBOutlet NSColorWell *ambientColorWell; 24 | @property (weak) IBOutlet NSColorWell *lightColorWell; 25 | 26 | @property (assign) double materialSpecularity; 27 | -(IBAction)updateMaterialSpecularity:(id)sender; 28 | 29 | @property (assign) double shininess; 30 | -(IBAction)updateShininess:(id)sender; 31 | 32 | @property (strong) NSColor *ambientColor; 33 | -(IBAction)updateAmbientColor:(id)sender; 34 | 35 | @property (strong) NSColor *lightColor; 36 | -(IBAction)updateLightColor:(id)sender; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHGoochParameterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHGoochParameterViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/12/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHParameterViewProtocol.h" 11 | #import "CWHGoochProgram.h" 12 | #import "CWHParameterViewController.h" 13 | 14 | @interface CWHGoochParameterViewController : CWHParameterViewController 15 | 16 | @property (weak) IBOutlet NSTextField *diffuseWarmTextField; 17 | @property (weak) IBOutlet NSTextField *diffuseCoolTextField; 18 | 19 | @property (weak) IBOutlet NSSlider *diffuseWarmSlider; 20 | @property (weak) IBOutlet NSSlider *diffuseCoolSlider; 21 | 22 | @property (weak) IBOutlet NSColorWell *surfaceColorWell; 23 | @property (weak) IBOutlet NSColorWell *warmColorWell; 24 | @property (weak) IBOutlet NSColorWell *coolColorWell; 25 | 26 | @property (assign) double diffuseWarm; 27 | - (IBAction)updateDiffuseWarm:(id)sender; 28 | 29 | @property (assign) double diffuseCool; 30 | - (IBAction)updateDiffuseCool:(id)sender; 31 | 32 | @property (strong) NSColor *surfaceColor; 33 | - (IBAction)updateSurfaceColor:(id)sender; 34 | 35 | @property (strong) NSColor *warmColor; 36 | - (IBAction)updateWarmColor:(id)sender; 37 | 38 | @property (strong) NSColor *coolColor; 39 | - (IBAction)updateCoolColor:(id)sender; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHHemisphereParameterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHHemisphereParameterViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/21/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHHemisphereParameterViewController.h" 10 | 11 | @interface CWHHemisphereParameterViewController () 12 | 13 | @end 14 | 15 | @implementation CWHHemisphereParameterViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do view setup here. 20 | if(self.program){ 21 | NSColor *skyColor = [self.program valueForKey:@"skyColor"]; 22 | 23 | if (skyColor) { 24 | [self.skyColorWell setColor:skyColor]; 25 | self.skyColor = skyColor; 26 | } 27 | 28 | NSColor *groundColor = [self.program valueForKey:@"groundColor"]; 29 | 30 | if(groundColor){ 31 | [self.groundColorWell setColor:groundColor]; 32 | self.groundColor = groundColor; 33 | } 34 | } 35 | } 36 | 37 | - (IBAction)updateSkyColor:(id)sender { 38 | self.skyColor = [sender color]; 39 | [self updateShaderValues]; 40 | } 41 | 42 | - (IBAction)updateGroundColor:(id)sender { 43 | self.groundColor = [sender color]; 44 | [self updateShaderValues]; 45 | } 46 | 47 | -(void)updateShaderValues 48 | { 49 | 50 | CWHHemisphereProgram *program = (CWHHemisphereProgram *)self.program; 51 | 52 | program.skyColor = self.skyColor; 53 | program.groundColor = self.groundColor; 54 | 55 | [self.delegate updateProgram:program shadableProperties:nil]; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHGlossyWetHighlightParameterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHGlossyWetHighlightParameterViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 9/12/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | #import 9 | #import "CWHGlossyWetHighlightProgram.h" 10 | #import "CWHParameterViewController.h" 11 | 12 | 13 | @interface CWHGlossyWetHighlightParameterViewController : CWHParameterViewController 14 | @property (weak) IBOutlet NSSlider *glossMinSlider; 15 | @property (weak) IBOutlet NSTextField *glossMinTextField; 16 | @property (weak) IBOutlet NSSlider *glossMaxSlider; 17 | @property (weak) IBOutlet NSTextField *glossMaxTextField; 18 | @property (weak) IBOutlet NSSlider *glossDropSlider; 19 | @property (weak) IBOutlet NSTextField *glossDropTextField; 20 | @property (weak) IBOutlet NSSlider *specularExponentSlider; 21 | @property (weak) IBOutlet NSTextField *specularExponentTextField; 22 | @property (weak) IBOutlet NSSlider *specularitySlider; 23 | @property (weak) IBOutlet NSTextField *specularityTextField; 24 | @property (weak) IBOutlet NSColorWell *diffuseColorWell; 25 | @property (weak) IBOutlet NSColorWell *ambientColorWell; 26 | @property (weak) IBOutlet NSColorWell *specularColorWell; 27 | 28 | 29 | - (IBAction)updateGlossMin:(id)sender; 30 | - (IBAction)updateGlossMax:(id)sender; 31 | - (IBAction)updateGlossDrop:(id)sender; 32 | - (IBAction)updateSpecularExponent:(id)sender; 33 | - (IBAction)updateSpecularity:(id)sender; 34 | - (IBAction)updateDiffuseColor:(id)sender; 35 | - (IBAction)updateAmbientColor:(id)sender; 36 | - (IBAction)updateSpecularColor:(id)sender; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ScenekitStarter.xcodeproj/project.xcworkspace/xcshareddata/ScenekitStarter.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 1BD5EB16-086D-4C67-B2FF-E637C53F6FF3 9 | IDESourceControlProjectName 10 | ScenekitStarter 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | A91601920B3F1208C5E892E32836B83870B353A1 14 | ssh://creative-workflow-hacks.com/~/ScenekitStarter.git 15 | 16 | IDESourceControlProjectPath 17 | ScenekitStarter.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | A91601920B3F1208C5E892E32836B83870B353A1 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | ssh://creative-workflow-hacks.com/~/ScenekitStarter.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | A91601920B3F1208C5E892E32836B83870B353A1 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | A91601920B3F1208C5E892E32836B83870B353A1 36 | IDESourceControlWCCName 37 | ScenekitStarter 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHEdgeFuzzParameterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CWHEdgeFuzzParameterViewController.h 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/15/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHParameterViewProtocol.h" 11 | #import "CWHEdgeFuzzProgram.h" 12 | #import "CWHParameterViewController.h" 13 | 14 | @interface CWHEdgeFuzzParameterViewController : CWHParameterViewController 15 | 16 | @property (weak) IBOutlet NSTextField *fuzzinessTextField; 17 | @property (weak) IBOutlet NSSlider *fuzzinessCircularSlider; 18 | @property (weak) IBOutlet NSColorWell *surfaceColorWell; 19 | @property (weak) IBOutlet NSTextField *edgeFadeTextField; 20 | @property (weak) IBOutlet NSSlider *edgeFadeCircularSlider; 21 | @property (weak) IBOutlet NSTextField *specularityTextField; 22 | @property (weak) IBOutlet NSSlider *specularityCircularSlider; 23 | @property (weak) IBOutlet NSColorWell *edgeColorWell; 24 | @property (weak) IBOutlet NSColorWell *lightColorWell; 25 | @property (weak) IBOutlet NSColorWell *ambientColorWell; 26 | 27 | @property (assign) double fuzziness; 28 | - (IBAction)updateFuzziness:(id)sender; 29 | 30 | @property (strong) NSColor *surfaceColor; 31 | - (IBAction)updateSurfaceColor:(id)sender; 32 | 33 | @property (assign) double edgeFade; 34 | - (IBAction)updateEdgeFade:(id)sender; 35 | 36 | @property (assign) double specularity; 37 | - (IBAction)updateSpecularity:(id)sender; 38 | 39 | @property (strong) NSColor *edgeColor; 40 | - (IBAction)updateEdgeColor:(id)sender; 41 | 42 | @property (strong) NSColor *lightColor; 43 | - (IBAction)lightColor:(id)sender; 44 | 45 | @property (strong) NSColor *ambientColor; 46 | - (IBAction)updateAmbientColor:(id)sender; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHBlinnParameterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHBlinnParameterViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/15/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHBlinnParameterViewController.h" 10 | 11 | @interface CWHBlinnParameterViewController () 12 | 13 | @end 14 | 15 | @implementation CWHBlinnParameterViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | if (self.program) { 20 | NSColor *ambientColor = [self.program valueForKey:@"ambientColor"]; 21 | 22 | if (ambientColor) { 23 | [self.ambientColorWell setColor:ambientColor]; 24 | self.ambientColor = ambientColor; 25 | } 26 | 27 | NSColor *lightColor = [self.program valueForKey:@"lightColor"]; 28 | 29 | if(lightColor){ 30 | [self.lightColorWell setColor:lightColor]; 31 | self.lightColor = lightColor; 32 | } 33 | } 34 | } 35 | 36 | - (IBAction)updateAmbientColor:(id)sender { 37 | 38 | NSColorWell *colorWell = sender; 39 | NSColor *color = [colorWell color]; 40 | 41 | self.ambientColor = color; 42 | [self updateShaderValues]; 43 | 44 | } 45 | 46 | - (IBAction)updateLightColor:(id)sender { 47 | NSColorWell *colorWell = sender; 48 | NSColor *color = [colorWell color]; 49 | 50 | self.lightColor = color; 51 | [self updateShaderValues]; 52 | } 53 | 54 | -(void)updateShaderValues 55 | { 56 | CWHBlinnProgram *program = (CWHBlinnProgram *)self.program; 57 | 58 | program.lightColor = self.lightColor; 59 | program.ambientColor = self.ambientColor; 60 | 61 | [self.delegate updateProgram:program shadableProperties:nil]; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /ScenekitStarter/Hemisphere.metal: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace metal; 4 | 5 | #include 6 | 7 | struct VertexIn { 8 | float4 position [[attribute(SCNVertexSemanticPosition)]]; 9 | float3 normal [[attribute(SCNVertexSemanticNormal)]]; 10 | //float2 texCoords [[attribute(SCNVertexSemanticTexcoord0)]]; 11 | }; 12 | 13 | struct NodeConstants { 14 | float4x4 modelViewTransform; 15 | float4x4 modelViewProjectionTransform; 16 | float4x4 normalTransform; 17 | }; 18 | 19 | struct LightConstants { 20 | packed_float3 position; 21 | packed_float3 skyColor; 22 | packed_float3 groundColor; 23 | }; 24 | 25 | struct VertexOut { 26 | float4 position [[position]]; 27 | float4 color; 28 | }; 29 | 30 | /* 31 | From the GLSL Orange Book 32 | Randi J. Rost 33 | */ 34 | 35 | vertex VertexOut HemisphereVertex(VertexIn in [[stage_in]], 36 | constant SCNSceneBuffer &scn_frame [[buffer(0)]], 37 | constant NodeConstants &scn_node [[buffer(1)]], 38 | constant LightConstants &light [[buffer(2)]]) 39 | { 40 | float4 Nm = scn_node.normalTransform * float4(in.normal, 0.0f); 41 | float3 N = normalize(Nm.xyz); 42 | float3 V = (scn_node.modelViewTransform * in.position).xyz; 43 | float3 lightVec = normalize(light.position.xyz - V); 44 | float costheta = dot(N, lightVec); 45 | float a = 0.5 + 0.5 * costheta; 46 | float3 litColor = mix(light.groundColor, light.skyColor, a); 47 | 48 | VertexOut out; 49 | out.position = scn_node.modelViewProjectionTransform * in.position; 50 | out.color = float4(litColor, 1.0f); 51 | return out; 52 | } 53 | 54 | fragment float4 HemisphereFragment(VertexOut in [[stage_in]]) 55 | { 56 | return in.color; 57 | } 58 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHThinFilmParameterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHThinFilmParameterViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 9/4/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHThinFilmParameterViewController.h" 10 | 11 | @interface CWHThinFilmParameterViewController () 12 | 13 | @end 14 | 15 | @implementation CWHThinFilmParameterViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | if(self.program){ 20 | NSColor *diffuseColor = [self.program valueForKey:@"diffuseColor"]; 21 | 22 | if (diffuseColor) { 23 | [self.diffuseColorWell setColor:diffuseColor]; 24 | self.diffuseColor = diffuseColor; 25 | } 26 | 27 | double filmDepth = [[self.program valueForKey:@"filmDepth"] doubleValue]; 28 | if (filmDepth >= 0) { 29 | [self.filmDepthSlider setDoubleValue:filmDepth]; 30 | [self.filmDepthTextField setDoubleValue:filmDepth]; 31 | self.filmDepth = filmDepth; 32 | } 33 | } 34 | } 35 | 36 | - (IBAction)updateFilmDepth:(id)sender { 37 | self.filmDepth = [sender doubleValue]; 38 | if ([sender isKindOfClass:[NSSlider class]]) { 39 | [self.filmDepthTextField setDoubleValue:[sender doubleValue]]; 40 | }else{ 41 | [self.filmDepthSlider setDoubleValue:[sender doubleValue]]; 42 | } 43 | [self updateShaderValues]; 44 | } 45 | 46 | - (IBAction)updateDiffuseColor:(id)sender { 47 | NSColorWell *colorWell = sender; 48 | NSColor *color = [colorWell color]; 49 | 50 | self.diffuseColor = color; 51 | [self updateShaderValues]; 52 | } 53 | 54 | -(void)updateShaderValues 55 | { 56 | CWHThinFilmProgram *program = (CWHThinFilmProgram *)self.program; 57 | 58 | program.filmDepth= self.filmDepth; 59 | program.diffuseColor = self.diffuseColor; 60 | 61 | [self.delegate updateProgram:program shadableProperties:program.shadableProperties]; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLightingView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ScenekitStarter/Blinn.metal: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace metal; 3 | 4 | #include 5 | 6 | struct VertexIn { 7 | float4 position [[attribute(SCNVertexSemanticPosition)]]; 8 | float3 normal [[attribute(SCNVertexSemanticNormal)]]; 9 | float2 texCoords [[attribute(SCNVertexSemanticTexcoord0)]]; 10 | }; 11 | 12 | struct NodeConstants { 13 | float4x4 modelViewTransform; 14 | float4x4 modelViewProjectionTransform; 15 | float4x4 normalTransform; 16 | }; 17 | 18 | struct LightConstants { 19 | packed_float3 diffuseIntensity; 20 | packed_float3 ambientIntensity; 21 | packed_float3 position; 22 | }; 23 | 24 | struct VertexOut { 25 | float4 position [[position]]; 26 | float3 normal; 27 | float3 lightDir; 28 | }; 29 | 30 | vertex VertexOut BlinnVertex(VertexIn in [[stage_in]], 31 | constant SCNSceneBuffer &scn_frame [[buffer(0)]], 32 | constant NodeConstants &scn_node [[buffer(1)]], 33 | constant LightConstants &vertexLight [[buffer(2)]]) 34 | { 35 | float4 viewPosition = scn_node.modelViewTransform * in.position; 36 | float3 v = float3(viewPosition.xyz / viewPosition.w); 37 | float4 n = scn_node.normalTransform * float4(in.normal, 0.0f); 38 | float3 normal = normalize(n.xyz); 39 | 40 | VertexOut out; 41 | out.position = scn_node.modelViewProjectionTransform * in.position; 42 | out.normal = normal; 43 | out.lightDir = float3(vertexLight.position.xyz - v); 44 | 45 | return out; 46 | } 47 | 48 | fragment float4 BlinnFragment(VertexOut in [[stage_in]], 49 | constant LightConstants &fragmentLight [[buffer(2)]]) 50 | { 51 | const float3 emissionColor(0.0f, 0.0f, 0.0f); 52 | const float3 ambientColor(1.0f, 1.0f, 1.0f); 53 | const float3 diffuseColor(1.0f, 1.0f, 1.0f); 54 | 55 | // Ambient contribution 56 | float3 surfaceColor = emissionColor + ambientColor * fragmentLight.ambientIntensity; 57 | float3 N = normalize(in.normal); 58 | float3 L = normalize(in.lightDir); 59 | float lambertTerm = dot(N,L); 60 | if(lambertTerm > 0.0) { 61 | // Diffuse contribution 62 | surfaceColor += fragmentLight.diffuseIntensity * diffuseColor * lambertTerm; 63 | } 64 | return float4(surfaceColor, 1.0f); 65 | } 66 | -------------------------------------------------------------------------------- /ScenekitStarter/Gooch.metal: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace metal; 4 | 5 | #include 6 | 7 | struct VertexIn { 8 | float4 position [[attribute(SCNVertexSemanticPosition)]]; 9 | float3 normal [[attribute(SCNVertexSemanticNormal)]]; 10 | float2 texCoords [[attribute(SCNVertexSemanticTexcoord0)]]; 11 | }; 12 | 13 | struct NodeConstants { 14 | float4x4 modelViewTransform; 15 | float4x4 modelViewProjectionTransform; 16 | float4x4 normalTransform; 17 | }; 18 | 19 | struct LightConstants { 20 | packed_float3 position; 21 | }; 22 | 23 | struct MaterialConstants { 24 | packed_float4 surfaceColor; 25 | packed_float4 warmColor; 26 | packed_float4 coolColor; 27 | float diffuseWarm; 28 | float diffuseCool; 29 | }; 30 | 31 | struct VertexOut { 32 | float4 position [[position]]; 33 | float3 reflectVec; 34 | float3 viewVec; 35 | float NdotL; 36 | }; 37 | 38 | vertex VertexOut GoochVertex(VertexIn in [[stage_in]], 39 | constant SCNSceneBuffer &scn_frame [[buffer(0)]], 40 | constant NodeConstants &scn_node [[buffer(1)]], 41 | constant LightConstants &light [[buffer(2)]]) 42 | { 43 | float4 eyePosition = scn_node.modelViewTransform * in.position; 44 | float3 v = eyePosition.xyz / eyePosition.w; 45 | float4 n = scn_node.normalTransform * float4(in.normal, 0.0f); 46 | float3 tnorm = normalize(n.xyz); 47 | float3 lightVec = normalize(light.position - v); 48 | 49 | VertexOut out; 50 | out.reflectVec = normalize(reflect(-lightVec, tnorm)); 51 | out.viewVec = normalize(-v); 52 | out.NdotL = (dot(lightVec, tnorm) + 1.0f) * 0.5f; 53 | out.position = scn_node.modelViewProjectionTransform * in.position; 54 | return out; 55 | } 56 | 57 | fragment float4 GoochFragment(VertexOut in [[stage_in]], 58 | constant MaterialConstants &material [[buffer(0)]]) 59 | { 60 | float3 kcool = min(material.coolColor.rgb + material.diffuseCool * material.surfaceColor.rgb, 1.0f); 61 | float3 kwarm = min(material.warmColor.rgb + material.diffuseWarm * material.surfaceColor.rgb, 1.0f); 62 | float3 kfinal = mix(kcool, kwarm, in.NdotL); 63 | 64 | float3 nreflect = normalize(in.reflectVec); 65 | float3 nview = normalize(in.viewVec); 66 | 67 | float spec = max(dot(nreflect, nview), 0.0f); 68 | spec = powr(spec, 32.0f); 69 | 70 | return float4(min(kfinal + spec, 1.0), 1.0); 71 | } 72 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLightingViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // lightingViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/24/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHLightingViewController.h" 10 | 11 | @interface CWHLightingViewController () 12 | @property (strong) SCNNode *lightNode; 13 | @end 14 | 15 | @implementation CWHLightingViewController 16 | 17 | -(void)awakeFromNib 18 | { 19 | // create a new scene 20 | SCNScene *scene = [SCNScene scene]; 21 | 22 | // create and add a camera to the scene 23 | SCNNode *cameraNode = [SCNNode node]; 24 | cameraNode.camera = [SCNCamera camera]; 25 | [scene.rootNode addChildNode:cameraNode]; 26 | 27 | // place the camera 28 | cameraNode.position = SCNVector3Make(0, 0, 15); 29 | 30 | // create and add a light to the scene 31 | SCNNode *ambientLightNode = [SCNNode node]; 32 | ambientLightNode.name = @"light"; 33 | ambientLightNode.light = [SCNLight light]; 34 | ambientLightNode.position = SCNVector3Make(0, 10, 10); 35 | ambientLightNode.light.type = SCNLightTypeAmbient; 36 | ambientLightNode.light.color = [NSColor redColor]; 37 | [scene.rootNode addChildNode:ambientLightNode]; 38 | self.lightNode = ambientLightNode; 39 | 40 | SCNAction *moveByAction = [SCNAction moveBy:SCNVector3Make(20, 30, 10) duration:2]; 41 | moveByAction.timingMode = SCNActionTimingModeEaseInEaseOut; 42 | SCNAction *reversed = [moveByAction reversedAction]; 43 | 44 | [ambientLightNode runAction:[SCNAction repeatActionForever:[SCNAction sequence:@[moveByAction, reversed]]]]; 45 | 46 | SCNTorus *torusShape = [SCNTorus torusWithRingRadius:3 pipeRadius:1]; 47 | 48 | SCNNode *torusNode = [SCNNode nodeWithGeometry:torusShape]; 49 | torusNode.position = SCNVector3Make(0, 0, 0); 50 | torusNode.scale = SCNVector3Make(1, 1, 1); 51 | 52 | [torusNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:2 y:0 z:0 duration:1]]]; 53 | 54 | self.geometryNode = torusNode; 55 | 56 | [scene.rootNode addChildNode:self.geometryNode]; 57 | 58 | // set the scene to the view 59 | self.lightingView.scene = scene; 60 | 61 | // allows the user to manipulate the camera 62 | self.lightingView.allowsCameraControl = YES; 63 | 64 | // show statistics such as fps and timing information 65 | self.lightingView.showsStatistics = YES; 66 | 67 | // configure the view 68 | self.lightingView.backgroundColor = [NSColor blackColor]; 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /ScenekitStarter/LambSkin.metal: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace metal; 4 | 5 | #include 6 | 7 | struct VertexIn { 8 | float4 position [[attribute(SCNVertexSemanticPosition)]]; 9 | float3 normal [[attribute(SCNVertexSemanticNormal)]]; 10 | }; 11 | 12 | struct NodeConstants { 13 | float4x4 modelViewTransform; 14 | float4x4 modelViewProjectionTransform; 15 | float4x4 normalTransform; 16 | }; 17 | 18 | struct LightConstants { 19 | packed_float3 position; 20 | }; 21 | 22 | struct MaterialConstants { 23 | packed_float3 ambientColor; 24 | packed_float3 diffuseColor; 25 | packed_float3 subColor; 26 | float rolloff; 27 | }; 28 | 29 | struct VertexOut { 30 | float4 position [[position]]; 31 | float3 lightVec; 32 | float3 eyeNormal; 33 | }; 34 | 35 | /* 36 | Adapted from: 37 | 'lambSkin' shader from NVIDIA shader library 38 | http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html 39 | 40 | "A lambertian-like surface with light 'bleed-through'." 41 | */ 42 | 43 | vertex VertexOut LambSkinVertex(VertexIn in [[stage_in]], 44 | constant SCNSceneBuffer &scn_frame [[buffer(0)]], 45 | constant NodeConstants &scn_node [[buffer(1)]], 46 | constant LightConstants &light [[buffer(2)]]) 47 | { 48 | VertexOut out; 49 | 50 | float4 V = scn_node.modelViewTransform * in.position; 51 | float4 N = normalize(scn_node.normalTransform * float4(in.normal, 0.0f)); 52 | 53 | out.lightVec = light.position - V.xyz; 54 | out.eyeNormal = N.xyz; 55 | 56 | out.position = scn_node.modelViewProjectionTransform * in.position; 57 | return out; 58 | } 59 | 60 | fragment float4 LambSkinFragment(VertexOut in [[stage_in]], 61 | constant MaterialConstants &material [[buffer(0)]]) 62 | { 63 | // Normalize normal and light vector 64 | float3 Ln = normalize(in.lightVec); 65 | float3 Nn = normalize(in.eyeNormal); 66 | 67 | float ldn = dot(Ln, Nn); 68 | 69 | // Calculate diffuse contribution 70 | float diffComp = max(0.0f, ldn); 71 | float3 diffuse = (diffComp * material.diffuseColor).xyz; 72 | 73 | // Calculate simulated subsurface contribution 74 | float subLamb = smoothstep(-material.rolloff, 1.0f, ldn) - smoothstep(0.0f, 1.0f, ldn); 75 | subLamb = max(0.0f, subLamb); 76 | float3 subsurface = subLamb * material.subColor.xyz; 77 | 78 | float3 surfaceColor = material.ambientColor.xyz + diffuse + subsurface; 79 | return float4(surfaceColor, 1.0f); 80 | } 81 | -------------------------------------------------------------------------------- /ScenekitStarter/GameViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/24/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "GameViewController.h" 10 | 11 | @implementation GameViewController 12 | 13 | -(void)awakeFromNib 14 | { 15 | NSLog(@"awakeFromNib"); 16 | // create a new scene 17 | SCNScene *scene = [SCNScene scene]; 18 | 19 | // create and add a camera to the scene 20 | SCNNode *cameraNode = [SCNNode node]; 21 | cameraNode.camera = [SCNCamera camera]; 22 | [scene.rootNode addChildNode:cameraNode]; 23 | 24 | // place the camera 25 | cameraNode.position = SCNVector3Make(0, 0, 15); 26 | 27 | // create and add a light to the scene 28 | SCNNode *ambientLightNode = [SCNNode node]; 29 | ambientLightNode.name = @"light"; 30 | ambientLightNode.light = [SCNLight light]; 31 | ambientLightNode.position = SCNVector3Make(0, 10, 10); 32 | ambientLightNode.light.type = SCNLightTypeAmbient; 33 | ambientLightNode.light.color = [NSColor redColor]; 34 | [scene.rootNode addChildNode:ambientLightNode]; 35 | 36 | 37 | SCNAction *moveByAction = [SCNAction moveBy:SCNVector3Make(20, 30, 10) duration:2]; 38 | moveByAction.timingMode = SCNActionTimingModeEaseInEaseOut; 39 | SCNAction *reversed = [moveByAction reversedAction]; 40 | 41 | [ambientLightNode runAction:[SCNAction repeatActionForever:[SCNAction sequence:@[moveByAction, reversed]]]]; 42 | 43 | SCNTorus *torusShape = [SCNTorus torusWithRingRadius:3. 44 | pipeRadius:1.]; 45 | 46 | 47 | CWHShadingNode *torusNode = [[CWHShadingNode alloc] initWithGeometry:torusShape 48 | light:ambientLightNode]; 49 | torusNode.position = SCNVector3Make(0., 0., 0.); 50 | torusNode.scale = SCNVector3Make(1., 1., 1.); 51 | 52 | [torusNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:2 y:0 z:0 duration:1]]]; 53 | 54 | self.torusNode = torusNode; 55 | 56 | [scene.rootNode addChildNode:self.torusNode]; 57 | 58 | 59 | // set the scene to the view 60 | self.gameView.scene = scene; 61 | 62 | // allows the user to manipulate the camera 63 | self.gameView.allowsCameraControl = YES; 64 | 65 | // show statistics such as fps and timing information 66 | self.gameView.showsStatistics = YES; 67 | 68 | // configure the view 69 | self.gameView.backgroundColor = [NSColor blackColor]; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHVelvetParameterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHVelvetParamterViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/15/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHVelvetParameterViewController.h" 10 | 11 | @interface CWHVelvetParameterViewController () 12 | 13 | @end 14 | 15 | @implementation CWHVelvetParameterViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | if(self.program){ 21 | double rolloff = [[self.program valueForKey:@"rolloff"] doubleValue]; 22 | if (rolloff >= 0) { 23 | [self.rolloffCircularSlider setDoubleValue:rolloff]; 24 | [self.rolloffTextField setDoubleValue:rolloff]; 25 | self.rolloff = rolloff; 26 | } 27 | 28 | NSColor *underColor = [self.program valueForKey:@"underColor"]; 29 | 30 | if (underColor) { 31 | [self.underColorWell setColor:underColor]; 32 | self.underColor = underColor; 33 | } 34 | 35 | NSColor *fuzzColor = [self.program valueForKey:@"fuzzColor"]; 36 | 37 | if(fuzzColor){ 38 | [self.fuzzColorWell setColor:fuzzColor]; 39 | self.fuzzColor= fuzzColor; 40 | } 41 | 42 | NSColor *primaryColor = [self.program valueForKey:@"primaryColor"]; 43 | 44 | if(primaryColor){ 45 | [self.primaryColorWell setColor:primaryColor]; 46 | self.primaryColor = primaryColor; 47 | } 48 | } 49 | } 50 | 51 | - (IBAction)updateRolloff:(id)sender { 52 | self.rolloff = [sender doubleValue]; 53 | if ([sender isKindOfClass:[NSSlider class]]) { 54 | [self.rolloffTextField setDoubleValue:[sender doubleValue]]; 55 | } 56 | 57 | [self updateShaderValues]; 58 | } 59 | 60 | - (IBAction)updateUnderColor:(id)sender { 61 | self.underColor = [sender color]; 62 | [self updateShaderValues]; 63 | } 64 | 65 | - (IBAction)updateFuzzColor:(id)sender { 66 | self.fuzzColor = [sender color]; 67 | [self updateShaderValues]; 68 | } 69 | 70 | - (IBAction)updatePrimaryColor:(id)sender { 71 | self.primaryColor = [sender color]; 72 | [self updateShaderValues]; 73 | } 74 | 75 | -(void)updateShaderValues 76 | { 77 | CWHVelvetProgram *program = (CWHVelvetProgram *)self.program; 78 | 79 | program.rolloff = self.rolloff; 80 | program.underColor = self.underColor; 81 | program.fuzzColor = self.fuzzColor; 82 | program.primaryColor = self.primaryColor; 83 | 84 | [self.delegate updateProgram:program shadableProperties:nil]; 85 | } 86 | @end 87 | -------------------------------------------------------------------------------- /ScenekitStarter/Velvet.metal: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace metal; 4 | 5 | #include 6 | 7 | struct VertexIn { 8 | float4 position [[attribute(SCNVertexSemanticPosition)]]; 9 | float3 normal [[attribute(SCNVertexSemanticNormal)]]; 10 | float2 texCoords [[attribute(SCNVertexSemanticTexcoord0)]]; 11 | }; 12 | 13 | struct NodeConstants { 14 | float4x4 modelViewTransform; 15 | float4x4 modelViewProjectionTransform; 16 | float4x4 normalTransform; 17 | }; 18 | 19 | struct LightConstants { 20 | packed_float3 position; 21 | }; 22 | 23 | struct MaterialConstants { 24 | packed_float4 primaryColor; 25 | packed_float4 fuzzColor; 26 | packed_float4 underColor; 27 | float rolloff; 28 | }; 29 | 30 | struct VertexOut { 31 | float4 position [[position]]; 32 | float4 color; 33 | }; 34 | 35 | /* 36 | Translated from HLSL shader for VVVV 37 | vNoiseVelvety.fx 38 | by Desaxismundi 2008 39 | 40 | Velvet shader originally by NVIDIA 41 | 42 | GLSL conversion toneburst 2008 43 | */ 44 | 45 | vertex VertexOut VelvetVertex(VertexIn in [[stage_in]], 46 | constant SCNSceneBuffer &scn_frame [[buffer(0)]], 47 | constant NodeConstants &scn_node [[buffer(1)]], 48 | constant LightConstants &light [[buffer(2)]], 49 | constant MaterialConstants &material [[buffer(3)]]) 50 | 51 | { 52 | // Transform normal into Eye Space 53 | float4 Nm = normalize(scn_node.normalTransform * float4(in.normal, 0.0f)); 54 | float3 Nn = Nm.xyz; 55 | // Transform vertex into Eye Space 56 | float4 Po = in.position; 57 | float3 Pe = (scn_node.modelViewTransform * Po).xyz; 58 | float3 Ln = normalize(light.position - Pe); 59 | float ldn = dot(Ln, Nn); 60 | float diffComp = max(0.0f, ldn); 61 | float3 diffContrib = diffComp * material.primaryColor.rgb; 62 | float subLamb = smoothstep(-material.rolloff, 1.0f, ldn) - smoothstep(0.0f, 1.0f, ldn); 63 | subLamb = max(0.0f, subLamb); 64 | float3 subContrib = subLamb * material.underColor.rgb; 65 | float3 cameraPos = float3(0.0f, 0.0f, 1.0f); 66 | float3 Vn = normalize(cameraPos - Pe); 67 | float vdn = 1.0f -dot(Vn, Nn); 68 | float3 vecColor = float3(vdn, vdn, vdn); 69 | float3 diffColor = subContrib + diffContrib; 70 | float3 specColor = vecColor * material.fuzzColor.rgb; 71 | float3 surfaceColor = diffColor + specColor; 72 | 73 | VertexOut out; 74 | out.position = scn_node.modelViewProjectionTransform * in.position; 75 | out.color = float4(surfaceColor, 1.0f); 76 | return out; 77 | } 78 | 79 | fragment float4 VelvetFragment(VertexOut in [[stage_in]]) 80 | { 81 | return in.color; 82 | } 83 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLambSkinParameterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHLambSkinParameterViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/21/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHLambSkinParameterViewController.h" 10 | 11 | @interface CWHLambSkinParameterViewController () 12 | 13 | @end 14 | 15 | @implementation CWHLambSkinParameterViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do view setup here. 20 | 21 | if(self.program){ 22 | NSColor *ambientColor = [self.program valueForKey:@"ambientColor"]; 23 | 24 | if (ambientColor) { 25 | [self.ambientColorWell setColor:ambientColor]; 26 | self.ambientColor = ambientColor; 27 | } 28 | 29 | NSColor *diffuseColor = [self.program valueForKey:@"diffuseColor"]; 30 | 31 | if(diffuseColor){ 32 | [self.diffuseColorWell setColor:diffuseColor]; 33 | self.diffuseColor = diffuseColor; 34 | } 35 | 36 | NSColor *subColor = [self.program valueForKey:@"subColor"]; 37 | 38 | if(subColor){ 39 | [self.subColorWell setColor:subColor]; 40 | self.subColor= subColor; 41 | } 42 | 43 | double rolloff = [[self.program valueForKey:@"rolloff" ] doubleValue]; 44 | if (rolloff >= 0) { 45 | [self.rolloffSlider setDoubleValue:rolloff]; 46 | [self.rolloffTextField setDoubleValue:rolloff]; 47 | self.rolloff = rolloff; 48 | } 49 | 50 | } 51 | } 52 | 53 | - (IBAction)updateRolloff:(id)sender { 54 | self.rolloff = [sender doubleValue]; 55 | if ([sender isKindOfClass:[NSSlider class]]) { 56 | [self.rolloffTextField setDoubleValue:[sender doubleValue]]; 57 | }else{ 58 | [self.rolloffSlider setDoubleValue:[sender doubleValue]]; 59 | } 60 | 61 | [self updateShaderValues]; 62 | } 63 | 64 | - (IBAction)updateAmbientColor:(id)sender { 65 | self.ambientColor = [sender color]; 66 | [self updateShaderValues]; 67 | } 68 | 69 | - (IBAction)updateDiffuseColor:(id)sender { 70 | self.diffuseColor = [sender color]; 71 | [self updateShaderValues]; 72 | } 73 | 74 | - (IBAction)updateSubColor:(id)sender { 75 | self.subColor = [sender color]; 76 | [self updateShaderValues]; 77 | } 78 | 79 | -(void)updateShaderValues 80 | { 81 | 82 | CWHLambSkinProgram *program = (CWHLambSkinProgram *)self.program; 83 | 84 | program.rolloff = self.rolloff; 85 | program.ambientColor = self.ambientColor; 86 | program.diffuseColor = self.diffuseColor; 87 | program.subColor = self.subColor; 88 | 89 | [self.delegate updateProgram:program shadableProperties:nil]; 90 | } 91 | @end 92 | -------------------------------------------------------------------------------- /ScenekitStarter/LUTSkin.metal: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace metal; 4 | 5 | #include 6 | 7 | struct VertexIn { 8 | float4 position [[attribute(SCNVertexSemanticPosition)]]; 9 | float3 normal [[attribute(SCNVertexSemanticNormal)]]; 10 | float2 texCoords [[attribute(SCNVertexSemanticTexcoord0)]]; 11 | }; 12 | 13 | struct NodeConstants { 14 | float4x4 modelViewTransform; 15 | float4x4 modelViewProjectionTransform; 16 | float4x4 normalTransform; 17 | }; 18 | 19 | struct LightConstants { 20 | packed_float3 position; 21 | }; 22 | 23 | struct MaterialConstants { 24 | packed_float4 diffuseColor; 25 | packed_float4 specularColor; 26 | }; 27 | 28 | struct VertexOut { 29 | float4 position [[position]]; 30 | float3 normal; 31 | float3 lightVec; 32 | float3 halfVec; 33 | }; 34 | 35 | /* 36 | Subsurface scattering approximation 37 | Adapted from GPU Gems Vol.1 38 | Chapter 16. 'Real-Time Approximations to Subsurface Scattering' 39 | by Simon Green 40 | 41 | Available online at 42 | http://http.developer.nvidia.com/GPUGems/gpugems_ch16.html 43 | */ 44 | 45 | vertex VertexOut LUTSkinVertex(VertexIn in [[stage_in]], 46 | constant SCNSceneBuffer &scn_frame [[buffer(0)]], 47 | constant NodeConstants &scn_node [[buffer(1)]], 48 | constant LightConstants &light [[buffer(2)]]) 49 | { 50 | const float3 eye(0.0f, 0.0f, 1.0f); 51 | float4 eyeNormal = scn_node.normalTransform * float4(in.normal, 0.0f); 52 | 53 | float4 v = scn_node.modelViewTransform * in.position; 54 | float3 V = v.xyz / v.w; 55 | 56 | VertexOut out; 57 | out.position = scn_node.modelViewProjectionTransform * in.position; 58 | out.normal = normalize(eyeNormal.xyz); 59 | out.lightVec = normalize(light.position.xyz - V.xyz); 60 | out.halfVec = normalize(out.lightVec + eye); 61 | return out; 62 | } 63 | 64 | fragment float4 LUTSkinFragment(VertexOut in [[stage_in]], 65 | texture2d skinLUT [[texture(0)]], 66 | constant MaterialConstants &material [[buffer(0)]]) 67 | { 68 | constexpr sampler bilinearClampedSampler(coord::normalized, 69 | min_filter::linear, 70 | mag_filter::linear, 71 | mip_filter::none, 72 | address::clamp_to_edge); 73 | float2 s { 74 | dot(in.normal, in.lightVec), 75 | dot(in.normal, in.halfVec) 76 | }; 77 | s = s * 0.5f + 0.5f; 78 | s.x = min(0.996f, s.x); 79 | float4 light = skinLUT.sample(bilinearClampedSampler, s); 80 | return material.diffuseColor * light + material.specularColor * light.a; 81 | } 82 | -------------------------------------------------------------------------------- /ScenekitStarter/Phong.metal: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace metal; 4 | 5 | #include 6 | 7 | struct VertexIn { 8 | float4 position [[attribute(SCNVertexSemanticPosition)]]; 9 | float3 normal [[attribute(SCNVertexSemanticNormal)]]; 10 | float2 texCoords [[attribute(SCNVertexSemanticTexcoord0)]]; 11 | }; 12 | 13 | struct NodeConstants { 14 | float4x4 modelViewTransform; 15 | float4x4 modelViewProjectionTransform; 16 | float4x4 normalTransform; 17 | }; 18 | 19 | struct LightConstants { 20 | packed_float3 position; 21 | packed_float3 diffuseIntensity; 22 | packed_float3 ambientIntensity; 23 | }; 24 | 25 | struct MaterialConstants { 26 | packed_float3 specularColor; 27 | float shininess; 28 | }; 29 | 30 | struct VertexOut { 31 | float4 position [[position]]; 32 | float3 normal; 33 | float3 lightDir; 34 | float3 eyeVec; 35 | }; 36 | 37 | vertex VertexOut PhongVertex(VertexIn in [[stage_in]], 38 | constant SCNSceneBuffer &scn_frame [[buffer(0)]], 39 | constant NodeConstants &scn_node [[buffer(1)]], 40 | constant LightConstants &vertexLight [[buffer(2)]]) 41 | { 42 | float4 viewPosition = scn_node.modelViewTransform * in.position; 43 | float3 V = viewPosition.xyz / viewPosition.w; 44 | float4 N = scn_node.normalTransform * float4(in.normal, 0.0f); 45 | 46 | VertexOut out; 47 | out.position = scn_node.modelViewProjectionTransform * in.position; 48 | out.normal = normalize(N.xyz); 49 | out.lightDir = vertexLight.position.xyz - V; 50 | out.eyeVec = -V; 51 | 52 | return out; 53 | } 54 | 55 | fragment float4 PhongFragment(VertexOut in [[stage_in]], 56 | constant LightConstants &fragmentLight [[buffer(2)]], 57 | constant MaterialConstants &material [[buffer(3)]]) 58 | { 59 | float3 specularIntensity(1.0f, 1.0f, 1.0f); 60 | 61 | float3 emissiveIntensity(0.0f, 0.0f, 0.0f); 62 | float3 ambientColor(1.0f, 1.0f, 1.0f); 63 | float3 diffuseColor(1.0f, 1.0f, 1.0f); 64 | float3 specularColor(material.specularColor.rgb); 65 | 66 | // Ambient contribution 67 | float3 surfaceColor = emissiveIntensity + ambientColor * fragmentLight.ambientIntensity.rgb; 68 | 69 | float3 N = normalize(in.normal); 70 | float3 L = normalize(in.lightDir); 71 | float diffuseFactor = saturate(dot(N,L)); 72 | if(diffuseFactor > 0.0) 73 | { 74 | // Diffuse contribution 75 | surfaceColor += fragmentLight.diffuseIntensity.rgb * diffuseColor * diffuseFactor; 76 | 77 | // Specular contribution 78 | float3 E = normalize(in.eyeVec); 79 | float3 R = reflect(-L, N); 80 | float specularFactor = powr(max(dot(R, E), 0.0), material.shininess); 81 | surfaceColor += specularIntensity * specularColor * specularFactor; 82 | } 83 | 84 | return float4(surfaceColor, 1.0f); 85 | } 86 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLightingProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHLightingProgram.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 9/9/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHLightingProgram.h" 10 | 11 | @implementation CWHLightingProgram 12 | 13 | - (id)init { 14 | return [self initWithProgram:@"PhongPointLight"]; 15 | } 16 | 17 | - (id)initWithProgram:(NSString *)program { 18 | self = [super init]; 19 | if (self) { 20 | _lightPosition = SCNVector3Make(0, 10, 10); 21 | 22 | NSURL *vertexShaderURL = [[NSBundle mainBundle] URLForResource:program withExtension:@"vsh"]; 23 | NSURL *fragmentShaderURL = [[NSBundle mainBundle] URLForResource:program withExtension:@"fsh"]; 24 | 25 | NSString *vertexShader = [[NSString alloc] initWithContentsOfURL:vertexShaderURL 26 | encoding:NSUTF8StringEncoding 27 | error:NULL]; 28 | NSString *fragmentShader = [[NSString alloc] initWithContentsOfURL:fragmentShaderURL 29 | encoding:NSUTF8StringEncoding 30 | error:NULL]; 31 | //// Assign the shader 32 | self.vertexShader = vertexShader; 33 | self.fragmentShader = fragmentShader; 34 | 35 | // Bind geometry source semantics to the vertex shader attributes 36 | [self setSemantic:SCNGeometrySourceSemanticVertex forSymbol:@"a_srcPos" options:nil]; 37 | [self setSemantic:SCNGeometrySourceSemanticNormal forSymbol:@"a_normPos" options:nil]; 38 | [self setSemantic:SCNGeometrySourceSemanticTexcoord forSymbol:@"a_texcoord" options:nil]; 39 | 40 | // Bind the uniforms that can benefit from "automatic" values, computed and assigned by Scene Kit at each frame 41 | [self setSemantic:SCNModelViewTransform forSymbol:@"u_mv" options:nil]; 42 | [self setSemantic:SCNModelViewProjectionTransform forSymbol:@"u_mvproj" options:nil]; 43 | [self setSemantic:SCNProjectionTransform forSymbol:@"u_proj" options:nil]; 44 | [self setSemantic:SCNNormalTransform forSymbol:@"u_norm" options:nil]; 45 | 46 | // Become the program delegate so that you get the binding callback 47 | self.delegate = self; 48 | } 49 | return self; 50 | } 51 | 52 | - (instancetype)initWithLibrary:(id)library 53 | vertexFunctionName:(NSString *)vertexFunctionName 54 | fragmentFunctionName:(NSString *)fragmentFunctionName 55 | { 56 | if ((self = [super init])) { 57 | _lightPosition = SCNVector3Make(0, 10, 10); 58 | 59 | self.library = library; 60 | self.vertexFunctionName = vertexFunctionName; 61 | self.fragmentFunctionName = fragmentFunctionName; 62 | 63 | self.delegate = self; 64 | } 65 | return self; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHEnvMapParameterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHEnvMapParameterViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/25/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CWHEnvMapParameterViewController.h" 11 | #import "CWHParameterViewProtocol.h" 12 | #import "CWHEnvMapProgram.h" 13 | #import "CWHParameterViewController.h" 14 | 15 | @interface CWHEnvMapParameterViewController () 16 | 17 | @end 18 | 19 | @implementation CWHEnvMapParameterViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | 24 | double ratio = 0.875; 25 | NSColor *ambientColor = [NSColor colorWithRed:0. green:0. blue:0. alpha:1.]; 26 | NSColor *diffuseColor = [NSColor colorWithRed:1. green:1. blue:1. alpha:1.]; 27 | NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"EnvMapInterior" ofType:@"png"]; 28 | 29 | if (self.program) { 30 | ratio = [[self.program valueForKey:@"ratio"] doubleValue]; 31 | ambientColor = [self.program valueForKey:@"ambientColor"]; 32 | diffuseColor = [self.program valueForKey:@"diffuseColor"]; 33 | imagePath = [self.program valueForKey:@"imagePath"]; 34 | } 35 | 36 | if (imagePath == nil) { 37 | imagePath = [[NSBundle mainBundle] pathForResource:@"EnvMapInterior" ofType:@"png"]; 38 | } 39 | 40 | NSString *envMapTitle = [[imagePath lastPathComponent] stringByDeletingPathExtension]; 41 | 42 | self.ratio = ratio; 43 | [self.ratioTextField setDoubleValue:self.ratio]; 44 | [self.ratioSlider setDoubleValue:self.ratio]; 45 | 46 | self.ambientColor = ambientColor; 47 | [self.ambientColorWell setColor:ambientColor]; 48 | 49 | self.diffuseColor = diffuseColor; 50 | [self.diffuseColorWell setColor:diffuseColor]; 51 | 52 | self.imagePath = imagePath; 53 | [self.envMapMenu selectItemWithTitle:envMapTitle]; 54 | } 55 | 56 | - (IBAction)updateRatio:(id)sender { 57 | self.ratio = [sender doubleValue]; 58 | if ([sender isKindOfClass:[NSSlider class]]) { 59 | [self.ratioTextField setDoubleValue:[sender doubleValue]]; 60 | }else{ 61 | [self.ratioSlider setDoubleValue:[sender doubleValue]]; 62 | } 63 | [self updateShaderValues]; 64 | } 65 | 66 | - (IBAction)updateAmbientColor:(NSColorWell *)sender { 67 | self.ambientColor = [sender color]; 68 | [self updateShaderValues]; 69 | } 70 | 71 | - (IBAction)updateDiffuseColor:(NSColorWell *)sender { 72 | self.diffuseColor = [(NSColorWell *)sender color]; 73 | [self updateShaderValues]; 74 | } 75 | 76 | - (IBAction)updateEnvMap:(id)sender { 77 | NSString *updatedMap = [sender titleOfSelectedItem]; 78 | self.imagePath = [[NSBundle mainBundle] pathForResource:updatedMap ofType:@"png"]; 79 | 80 | [self updateShaderValues]; 81 | } 82 | 83 | -(void)updateShaderValues 84 | { 85 | CWHEnvMapProgram *program = (CWHEnvMapProgram *)self.program; 86 | 87 | program.ratio = self.ratio; 88 | program.ambientColor = self.ambientColor; 89 | program.diffuseColor = self.diffuseColor; 90 | program.imagePath = self.imagePath; 91 | 92 | [self.delegate updateProgram:program shadableProperties:program.shadableProperties]; 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHHemisphereProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHHemisphereProgram 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/30/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHHemisphereProgram.h" 10 | 11 | @implementation CWHHemisphereProgram 12 | 13 | +(BOOL) supportsSecureCoding { 14 | return YES; 15 | } 16 | 17 | -(instancetype)init 18 | { 19 | id device = MTLCreateSystemDefaultDevice(); 20 | id library = [device newDefaultLibrary]; 21 | 22 | self = [super initWithLibrary:library vertexFunctionName:@"HemisphereVertex" fragmentFunctionName:@"HemisphereFragment"]; 23 | 24 | if ( self != nil ) 25 | { 26 | self.delegate = self; 27 | 28 | [self bindBuffers]; 29 | 30 | NSColor *skyColor = [NSColor colorWithRed:0.0 green:0.7 blue:1.0 alpha:1.0]; 31 | self.skyColor = skyColor; 32 | NSColor *groundColor = [NSColor colorWithRed:0.7 green:0.5 blue:0.2 alpha:1.0]; 33 | self.groundColor = groundColor; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (id)initWithCoder:(NSCoder *)decoder { 40 | id device = MTLCreateSystemDefaultDevice(); 41 | id library = [device newDefaultLibrary]; 42 | 43 | self = [super initWithLibrary:library vertexFunctionName:@"HemisphereVertex" fragmentFunctionName:@"HemisphereFragment"]; 44 | 45 | if ( self != nil ) 46 | { 47 | self.delegate = self; 48 | 49 | [self bindBuffers]; 50 | 51 | self.skyColor =[decoder decodeObjectOfClass:[NSColor class] forKey:@"skyColor"]; 52 | self.groundColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"groundColor"]; 53 | 54 | } 55 | return self; 56 | } 57 | 58 | - (void)encodeWithCoder:(NSCoder *)encoder { 59 | [encoder encodeObject:_skyColor forKey:@"skyColor"]; 60 | [encoder encodeObject:_groundColor forKey:@"groundColor"]; 61 | } 62 | 63 | - (void)bindBuffers { 64 | SCNBufferBindingBlock lightBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 65 | { 66 | struct LightConstants { 67 | float position[3]; 68 | float skyColor[3]; 69 | float groundColor[3]; 70 | } light; 71 | 72 | light.position[0] = self.lightPosition.x; 73 | light.position[1] = self.lightPosition.y; 74 | light.position[2] = self.lightPosition.z; 75 | 76 | if (self.skyColor) { 77 | light.skyColor[0] = self.skyColor.redComponent; 78 | light.skyColor[1] = self.skyColor.greenComponent; 79 | light.skyColor[2] = self.skyColor.blueComponent; 80 | } 81 | 82 | if (self.groundColor) { 83 | light.groundColor[0] = self.groundColor.redComponent; 84 | light.groundColor[1] = self.groundColor.greenComponent; 85 | light.groundColor[2] = self.groundColor.blueComponent; 86 | } 87 | 88 | [buffer writeBytes:&light length:sizeof(light)]; 89 | }; 90 | 91 | [self handleBindingOfBufferNamed:@"light" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 92 | } 93 | 94 | #pragma mark - SCNProgramDelegate Protocol Methods 95 | 96 | - (void)program:(SCNProgram*)program handleError:(NSError*)error { 97 | // Log the shader compilation error 98 | NSLog(@"SceneKit compilation error: %@", error); 99 | } 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHPhongPointLightParameterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHPhongPointLightParameterViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/1/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHPhongPointLightParameterViewController.h" 10 | 11 | @interface CWHPhongPointLightParameterViewController () 12 | 13 | @end 14 | 15 | @implementation CWHPhongPointLightParameterViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do view setup here. 20 | if(self.program){ 21 | NSColor *ambientColor = [self.program valueForKey:@"ambientColor"]; 22 | 23 | if (ambientColor) { 24 | [self.ambientColorWell setColor:ambientColor]; 25 | self.ambientColor = ambientColor; 26 | } 27 | 28 | NSColor *lightColor = [self.program valueForKey:@"lightColor"]; 29 | 30 | if(lightColor){ 31 | [self.lightColorWell setColor:lightColor]; 32 | self.lightColor = lightColor; 33 | } 34 | 35 | double shininess = [[self.program valueForKey:@"shininess"] doubleValue]; 36 | if (shininess) { 37 | [self.shininessSlider setDoubleValue:shininess]; 38 | [self.shininessTextField setDoubleValue:shininess]; 39 | self.shininess = shininess; 40 | } 41 | 42 | double materialSpecularity = [[self.program valueForKey:@"materialSpecularity"] doubleValue]; 43 | if (materialSpecularity >= 0) { 44 | [self.specularitySlider setDoubleValue:materialSpecularity]; 45 | [self.specularityTextField setDoubleValue:materialSpecularity]; 46 | self.materialSpecularity = materialSpecularity; 47 | } 48 | } 49 | 50 | } 51 | 52 | - (void)viewDidAppear 53 | { 54 | 55 | } 56 | 57 | -(void)viewWillDisappear 58 | { 59 | 60 | } 61 | 62 | -(IBAction)updateMaterialSpecularity:(id)sender 63 | { 64 | NSSlider *slider = sender; 65 | double value = [slider doubleValue]; 66 | 67 | [self.specularityTextField setDoubleValue:value]; 68 | self.materialSpecularity = value; 69 | 70 | [self updateShaderValues]; 71 | } 72 | 73 | -(IBAction)updateShininess:(id)sender 74 | { 75 | NSSlider *slider = sender; 76 | double value = [slider doubleValue]; 77 | 78 | self.shininess = value; 79 | [self.shininessTextField setDoubleValue:value]; 80 | 81 | [self updateShaderValues]; 82 | } 83 | 84 | -(IBAction)updateAmbientColor:(id)sender 85 | { 86 | NSColorWell *colorWell = sender; 87 | NSColor *color = [colorWell color]; 88 | 89 | self.ambientColor = color; 90 | [self updateShaderValues]; 91 | } 92 | 93 | -(IBAction)updateLightColor:(id)sender 94 | { 95 | NSColorWell *colorWell = sender; 96 | NSColor *color = [colorWell color]; 97 | 98 | self.lightColor = color; 99 | [self updateShaderValues]; 100 | } 101 | 102 | -(void)updateShaderValues 103 | { 104 | CWHPhongPointLightProgram *program = (CWHPhongPointLightProgram *)self.program; 105 | 106 | program.lightColor = self.lightColor; 107 | program.ambientColor = self.ambientColor; 108 | program.shininess = self.shininess; 109 | program.materialSpecularity = self.materialSpecularity; 110 | 111 | [self.delegate updateProgram:program shadableProperties:nil]; 112 | } 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /ScenekitStarter/EnvMap.metal: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace metal; 4 | 5 | #include 6 | 7 | struct VertexIn { 8 | float4 position [[attribute(SCNVertexSemanticPosition)]]; 9 | float3 normal [[attribute(SCNVertexSemanticNormal)]]; 10 | float2 texCoords [[attribute(SCNVertexSemanticTexcoord0)]]; 11 | }; 12 | 13 | struct NodeConstants { 14 | float4x4 modelViewTransform; 15 | float4x4 modelViewProjectionTransform; 16 | float4x4 normalTransform; 17 | }; 18 | 19 | struct LightConstants { 20 | packed_float3 position; 21 | packed_float3 ambientIntensity; 22 | packed_float3 diffuseIntensity; 23 | }; 24 | 25 | struct VertexOut { 26 | float4 position [[position]]; 27 | float4 color; 28 | float2 texCoords; 29 | }; 30 | 31 | /* 32 | Adapted from: 33 | /Developer/Examples/Quartz Composer/Compositions/GLSL/Environment Map.qtz 34 | More environment maps can be found here 35 | http://www.codemonsters.de/home/content.php?show=spheremaps 36 | */ 37 | 38 | void envMapVS(VertexIn in, thread VertexOut &out, constant NodeConstants &scn_node, constant LightConstants &light) 39 | { 40 | // (@warrenm) In spite of the naming of the variables below, they are mostly in eye space. 41 | // I have left the original names for posterity, but there is some confusion in this code 42 | // about which space we're in. 43 | 44 | float4 vWorld = scn_node.modelViewTransform * in.position; 45 | float4 Nm = normalize(scn_node.normalTransform * float4(in.normal, 0.0f)); 46 | float3 nWorld = Nm.xyz; 47 | 48 | // Diffuse 49 | float3 vertToLight = normalize(light.position - vWorld.xyz); 50 | float diffuseLight = max(dot(vertToLight, nWorld), 0.0); 51 | out.color = float4(light.ambientIntensity.rgb + (diffuseLight * light.diffuseIntensity.xyz), 1.0f); 52 | 53 | // Environment mapping texture coordinates 54 | float3 vWorldUnit = normalize(vWorld.xyz); 55 | float3 f = reflect(vWorldUnit, nWorld); 56 | float m = 2.0 * sqrt(f.x * f.x + f.y * f.y + (f.z + 1.0) * (f.z + 1.0)); 57 | out.texCoords = float2(f.x / m + 0.5, -f.y / m + 0.5); 58 | } 59 | 60 | vertex VertexOut EnvMapVertex(VertexIn in [[stage_in]], 61 | constant SCNSceneBuffer &scn_frame [[buffer(0)]], 62 | constant NodeConstants &scn_node [[buffer(1)]], 63 | constant LightConstants &vertexLights [[buffer(2)]]) 64 | { 65 | VertexOut out; 66 | envMapVS(in, out, scn_node, vertexLights); 67 | 68 | out.position = scn_node.modelViewProjectionTransform * in.position; 69 | 70 | return out; 71 | } 72 | 73 | /* 74 | Adapted from: 75 | /Developer/Examples/Quartz Composer/Compositions/GLSL/Environment Map.qtz 76 | */ 77 | 78 | fragment float4 EnvMapFragment(VertexOut in [[stage_in]], 79 | texture2d environmentMap [[texture(0)]], 80 | constant float &ratio [[buffer(0)]]) 81 | { 82 | constexpr sampler bilinearClampedSampler(coord::normalized, 83 | min_filter::linear, 84 | mag_filter::linear, 85 | mip_filter::none, 86 | address::clamp_to_edge); 87 | float2 tex = in.texCoords; 88 | tex.y = 1.0f - tex.y; 89 | float4 environmentColor = environmentMap.sample(bilinearClampedSampler, tex); 90 | float4 finalColor = mix(in.color, environmentColor, ratio); 91 | return finalColor; 92 | } 93 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHBlinnProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHBlinnProgram.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/29/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHBlinnProgram.h" 10 | 11 | @implementation CWHBlinnProgram 12 | 13 | +(BOOL) supportsSecureCoding { 14 | return YES; 15 | } 16 | 17 | -(instancetype)init 18 | { 19 | id device = MTLCreateSystemDefaultDevice(); 20 | id library = [device newDefaultLibrary]; 21 | 22 | self = [super initWithLibrary:library vertexFunctionName:@"BlinnVertex" fragmentFunctionName:@"BlinnFragment"]; 23 | 24 | if ( self != nil ) 25 | { 26 | self.delegate = self; 27 | 28 | [self bindBuffers]; 29 | 30 | self.ambientColor = [NSColor colorWithRed:0 green:0 blue:0 alpha:1]; 31 | self.lightColor = [NSColor redColor]; 32 | } 33 | 34 | return self; 35 | } 36 | 37 | - (id)initWithCoder:(NSCoder *)decoder { 38 | id device = MTLCreateSystemDefaultDevice(); 39 | id library = [device newDefaultLibrary]; 40 | 41 | self = [super initWithLibrary:library vertexFunctionName:@"BlinnVertex" fragmentFunctionName:@"BlinnFragment"]; 42 | 43 | if (self != nil) { 44 | self.ambientColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"ambientColor"]; 45 | self.lightColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"lightColor"]; 46 | 47 | [self bindBuffers]; 48 | 49 | self.delegate = self; 50 | } 51 | return self; 52 | } 53 | 54 | - (void)encodeWithCoder:(NSCoder *)encoder { 55 | [encoder encodeObject:_ambientColor forKey:@"ambientColor"]; 56 | [encoder encodeObject:_lightColor forKey:@"lightColor"]; 57 | } 58 | 59 | - (void)bindBuffers { 60 | SCNBufferBindingBlock lightBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 61 | { 62 | struct LightUniforms { 63 | float diffuseIntensity[3]; 64 | float ambientIntensity[3]; 65 | float position[3]; 66 | } lights; 67 | 68 | memset(&lights, 0, sizeof(lights)); 69 | 70 | lights.position[0] = self.lightPosition.x; 71 | lights.position[1] = self.lightPosition.y; 72 | lights.position[2] = self.lightPosition.z; 73 | 74 | if (self.lightColor) { 75 | lights.diffuseIntensity[0] = [self.lightColor redComponent]; 76 | lights.diffuseIntensity[1] = [self.lightColor greenComponent]; 77 | lights.diffuseIntensity[2] = [self.lightColor blueComponent]; 78 | } 79 | 80 | if (self.ambientColor) { 81 | lights.ambientIntensity[0] = [self.ambientColor redComponent]; 82 | lights.ambientIntensity[1] = [self.ambientColor greenComponent]; 83 | lights.ambientIntensity[2] = [self.ambientColor blueComponent]; 84 | } 85 | 86 | [buffer writeBytes:&lights length:sizeof(lights)]; 87 | }; 88 | 89 | [self handleBindingOfBufferNamed:@"vertexLight" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 90 | [self handleBindingOfBufferNamed:@"fragmentLight" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 91 | } 92 | 93 | #pragma mark - SCNProgramDelegate Protocol Methods 94 | 95 | - (void)program:(SCNProgram*)program handleError:(NSError*)error { 96 | // Log the shader compilation error 97 | NSLog(@"SceneKit compilation error: %@", error); 98 | } 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHGoochParameterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHGoochParameterViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/12/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHGoochParameterViewController.h" 10 | 11 | @interface CWHGoochParameterViewController () 12 | 13 | @end 14 | 15 | @implementation CWHGoochParameterViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | if(self.program){ 21 | NSColor *surfaceColor = [self.program valueForKey:@"surfaceColor"]; 22 | if (surfaceColor) { 23 | [self.surfaceColorWell setColor:surfaceColor]; 24 | self.surfaceColor= surfaceColor; 25 | } 26 | 27 | double diffuseWarm= [[self.program valueForKey:@"diffuseWarm"] doubleValue]; 28 | if (diffuseWarm) { 29 | [self.diffuseWarmSlider setDoubleValue:diffuseWarm]; 30 | [self.diffuseWarmTextField setDoubleValue:diffuseWarm]; 31 | self.diffuseWarm = diffuseWarm; 32 | } 33 | 34 | double diffuseCool = [[self.program valueForKey:@"diffuseCool"] doubleValue]; 35 | 36 | [self.diffuseCoolSlider setDoubleValue:diffuseCool]; 37 | [self.diffuseCoolTextField setDoubleValue:diffuseCool]; 38 | self.diffuseCool = diffuseCool; 39 | 40 | NSColor *warmColor = [self.program valueForKey:@"warmColor"]; 41 | if (warmColor) { 42 | [self.warmColorWell setColor:warmColor ]; 43 | self.warmColor = warmColor ; 44 | } 45 | 46 | NSColor *coolColor = [self.program valueForKey:@"coolColor"]; 47 | if (coolColor) { 48 | [self.coolColorWell setColor:coolColor]; 49 | self.coolColor = coolColor; 50 | } 51 | } 52 | } 53 | 54 | - (IBAction)updateSurfaceColor:(id)sender { 55 | 56 | NSColorWell *colorWell = sender; 57 | NSColor *color = [colorWell color]; 58 | 59 | self.surfaceColor = color; 60 | [self updateShaderValues]; 61 | } 62 | 63 | - (IBAction)updateCoolColor:(id)sender { 64 | NSColorWell *colorWell = sender; 65 | NSColor *color = [colorWell color]; 66 | 67 | self.coolColor = color; 68 | [self updateShaderValues]; 69 | } 70 | 71 | - (IBAction)updateWarmColor:(id)sender { 72 | NSColorWell *colorWell = sender; 73 | NSColor *color = [colorWell color]; 74 | 75 | self.warmColor = color; 76 | [self updateShaderValues]; 77 | } 78 | 79 | - (IBAction)updateDiffuseCool:(id)sender { 80 | 81 | NSSlider *slider = sender; 82 | double value = [slider doubleValue]; 83 | 84 | self.diffuseCool = value; 85 | [self.diffuseCoolTextField setDoubleValue:value]; 86 | 87 | [self updateShaderValues]; 88 | } 89 | 90 | - (IBAction)updateDiffuseWarm:(id)sender { 91 | NSSlider *slider = sender; 92 | double value = [slider doubleValue]; 93 | 94 | self.diffuseWarm = value; 95 | [self.diffuseWarmTextField setDoubleValue:value]; 96 | 97 | [self updateShaderValues]; 98 | } 99 | 100 | -(void)updateShaderValues 101 | { 102 | CWHGoochProgram *program = (CWHGoochProgram *)self.program; 103 | 104 | program.surfaceColor = self.surfaceColor; 105 | program.warmColor = self.warmColor; 106 | program.coolColor = self.coolColor; 107 | program.diffuseCool = self.diffuseCool; 108 | program.diffuseWarm = self.diffuseWarm; 109 | 110 | [self.delegate updateProgram:program shadableProperties:nil]; 111 | } 112 | 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /ScenekitStarter.xcodeproj/xcshareddata/xcschemes/ScenekitStarter.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /ScenekitStarter/ThinFilm.metal: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | using namespace metal; 4 | 5 | #include 6 | 7 | struct VertexIn { 8 | float4 position [[attribute(SCNVertexSemanticPosition)]]; 9 | float3 normal [[attribute(SCNVertexSemanticNormal)]]; 10 | float2 texCoords [[attribute(SCNVertexSemanticTexcoord0)]]; 11 | }; 12 | 13 | struct NodeConstants { 14 | float4x4 modelViewTransform; 15 | float4x4 modelViewProjectionTransform; 16 | float4x4 normalTransform; 17 | }; 18 | 19 | struct LightConstants { 20 | packed_float3 position; 21 | }; 22 | 23 | struct MaterialConstants { 24 | packed_float4 diffuseColor; 25 | float filmDepth; 26 | }; 27 | 28 | struct VertexOut { 29 | float4 position [[position]]; 30 | float2 texCoords; 31 | float3 diffColor; 32 | float3 specColor; 33 | float2 viewDepth; 34 | }; 35 | 36 | /* 37 | Extracted and adapted from NVIDIA 'Thinfilm' demo 38 | ftp://download.nvidia.com/developer/SDK/Individual_Samples/3dgraphics_samples.html 39 | */ 40 | 41 | vertex VertexOut ThinFilmVertex(VertexIn in [[stage_in]], 42 | constant SCNSceneBuffer &scn_frame [[buffer(0)]], 43 | constant NodeConstants &scn_node [[buffer(1)]], 44 | constant LightConstants &light [[buffer(2)]], 45 | constant MaterialConstants &vertexMaterial [[buffer(3)]]) 46 | { 47 | // Transform normal from model-space to view-space 48 | float4 n = scn_node.normalTransform * float4(in.normal, 0.0f); 49 | float3 normalVec = normalize(n.xyz); 50 | 51 | // Compute the eye->vertex vector 52 | const float3 eyeVector = float3(0.0f, 0.0f, 1.0f); 53 | float3 eyeVec = eyeVector; // Assume infinite viewer 54 | float3 lightVec = normalize(light.position); 55 | 56 | // Calculate half-angle vector 57 | float3 halfAngleVec = normalize(lightVec + eyeVec); 58 | 59 | // Calculate diffuse component 60 | float diffuse = max(dot(normalVec, lightVec), 0.0f); 61 | 62 | // Calculate specular component 63 | float specular = max(dot(normalVec, halfAngleVec), 0.0f); 64 | specular = powr(specular, 32.0f); 65 | 66 | VertexOut out; 67 | out.position = scn_node.modelViewProjectionTransform * in.position; 68 | out.texCoords = in.texCoords; 69 | 70 | // Compute the view depth for the thin film 71 | out.viewDepth = float2((1.0f / dot(normalVec, eyeVec)) * vertexMaterial.filmDepth); 72 | 73 | // Output final lighting results 74 | out.diffColor = diffuse; 75 | out.specColor = specular; 76 | 77 | return out; 78 | } 79 | 80 | fragment float4 ThinFilmFragment(VertexOut in [[stage_in]], 81 | constant MaterialConstants &fragmentMaterial [[buffer(0)]], 82 | /*texture2d diffuseMap [[texture(0)]],*/ 83 | texture2d fringeMap [[texture(1)]]) 84 | { 85 | constexpr sampler bilinearClampedSampler(coord::normalized, 86 | min_filter::linear, 87 | mag_filter::linear, 88 | mip_filter::none, 89 | address::clamp_to_edge); 90 | 91 | // Diffuse material color 92 | //float3 diffMaterial = diffuseMap.sample(bilinearClampedSampler, in.texCoords).rgb; 93 | float3 diffMaterial = fragmentMaterial.diffuseColor.rgb; 94 | 95 | // Lookup fringe value based on view depth 96 | float3 fringeColor = fringeMap.sample(bilinearClampedSampler, in.viewDepth).rgb; 97 | 98 | // modulate specular lighting by fringe color, combine with regular lighting 99 | return float4(in.diffColor * diffMaterial + fringeColor * in.specColor, 1.0f); 100 | } 101 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLUTSkinParameterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHLUTSkinParameterViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 9/12/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHLUTSkinParameterViewController.h" 10 | 11 | @interface CWHLUTSkinParameterViewController () 12 | 13 | @end 14 | 15 | @implementation CWHLUTSkinParameterViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | if(self.program){ 20 | NSColor *diffuseColor = [self.program valueForKey:@"diffuseColor"]; 21 | 22 | if (diffuseColor) { 23 | [self.diffuseColorWell setColor:diffuseColor]; 24 | 25 | } 26 | 27 | NSColor *specularColor = [self.program valueForKey:@"specularColor"]; 28 | 29 | if (specularColor) { 30 | [self.diffuseColorWell setColor:specularColor]; 31 | 32 | } 33 | NSColor *scatterColor = [self.program valueForKey:@"scatterColor"]; 34 | 35 | if (scatterColor) { 36 | [self.diffuseColorWell setColor:scatterColor]; 37 | 38 | } 39 | 40 | double wrap = [[self.program valueForKey:@"wrap"] doubleValue]; 41 | 42 | if (wrap >= 0) { 43 | [self.wrapSlider setDoubleValue:wrap]; 44 | [self.wrapTextField setDoubleValue:wrap]; 45 | 46 | } 47 | 48 | 49 | double scatterWidth = [[self.program valueForKey:@"scatterWidth"] doubleValue]; 50 | if (scatterWidth >= 0) { 51 | [self.scatterWidthSlider setDoubleValue:scatterWidth]; 52 | [self.scatterWidthTextField setDoubleValue:scatterWidth]; 53 | 54 | } 55 | 56 | double shininess = [[self.program valueForKey:@"shininess"] doubleValue]; 57 | if (shininess) { 58 | [self.shininessSlider setDoubleValue:shininess]; 59 | [self.shininessTextField setDoubleValue:shininess]; 60 | 61 | } 62 | } 63 | } 64 | 65 | - (IBAction)updateWrap:(id)sender { 66 | if ([sender isKindOfClass:[NSSlider class]]) { 67 | [self.wrapTextField setDoubleValue:[sender doubleValue]]; 68 | }else{ 69 | [self.wrapSlider setDoubleValue:[sender doubleValue]]; 70 | } 71 | 72 | [self updateShaderValues]; 73 | } 74 | 75 | - (IBAction)updateScatterWidth:(id)sender { 76 | if ([sender isKindOfClass:[NSSlider class]]) { 77 | [self.scatterWidthTextField setDoubleValue:[sender doubleValue]]; 78 | }else{ 79 | [self.scatterWidthSlider setDoubleValue:[sender doubleValue]]; 80 | } 81 | 82 | [self updateShaderValues]; 83 | } 84 | 85 | - (IBAction)updateShininess:(id)sender { 86 | if ([sender isKindOfClass:[NSSlider class]]) { 87 | [self.shininessTextField setDoubleValue:[sender doubleValue]]; 88 | }else{ 89 | [self.shininessSlider setDoubleValue:[sender doubleValue]]; 90 | } 91 | [self updateShaderValues]; 92 | } 93 | 94 | - (IBAction)updateDiffuseColor:(id)sender { 95 | [self updateShaderValues]; 96 | } 97 | 98 | - (IBAction)updateSpecularColor:(id)sender { 99 | [self updateShaderValues]; 100 | } 101 | 102 | - (IBAction)updateScatterColor:(id)sender { 103 | [self updateShaderValues]; 104 | } 105 | 106 | -(void)updateShaderValues 107 | { 108 | CWHLUTSkinProgram *program = (CWHLUTSkinProgram *)self.program; 109 | 110 | program.diffuseColor = [self.diffuseColorWell color]; 111 | program.specularColor = [self.specularColorWell color]; 112 | program.scatterColor = [self.scatterColorWell color]; 113 | program.wrap = [self.wrapSlider doubleValue]; 114 | program.scatterWidth = [self.scatterWidthSlider doubleValue]; 115 | program.shininess = [self.shininessSlider doubleValue]; 116 | 117 | [self.delegate updateProgram:program shadableProperties:nil]; 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /ScenekitStarter/HemisphereParameterView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /ScenekitStarter/BlinnParameterView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /ScenekitStarter.xcodeproj/xcuserdata/super.xcuserdatad/xcschemes/ScenekitStarter.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHThinFilmProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHThinFilmProgram.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/28/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHThinFilmProgram.h" 10 | 11 | @implementation CWHThinFilmProgram 12 | 13 | +(BOOL) supportsSecureCoding { 14 | return YES; 15 | } 16 | 17 | - (instancetype)init 18 | { 19 | id device = MTLCreateSystemDefaultDevice(); 20 | id library = [device newDefaultLibrary]; 21 | 22 | self = [super initWithLibrary:library vertexFunctionName:@"ThinFilmVertex" fragmentFunctionName:@"ThinFilmFragment"]; 23 | 24 | if ( self != nil ) 25 | { 26 | self.delegate = self; 27 | 28 | self.imagePath = [[NSBundle mainBundle] pathForResource:@"FringeMap" ofType:@"png"]; 29 | 30 | [self bindBuffers]; 31 | 32 | self.filmDepth = 0.75; 33 | self.diffuseColor = [NSColor grayColor]; 34 | 35 | } 36 | return self; 37 | } 38 | - (id)initWithCoder:(NSCoder *)decoder { 39 | id device = MTLCreateSystemDefaultDevice(); 40 | id library = [device newDefaultLibrary]; 41 | 42 | self = [super initWithLibrary:library vertexFunctionName:@"ThinFilmVertex" fragmentFunctionName:@"ThinFilmFragment"]; 43 | 44 | if ( self != nil ) 45 | { 46 | self.delegate = self; 47 | 48 | NSString *imagePath =[decoder decodeObjectOfClass:[NSString class] forKey:@"imagePath"]; 49 | if (imagePath) { 50 | self.imagePath = imagePath; 51 | } else { 52 | self.imagePath = [[NSBundle mainBundle] pathForResource:@"FringeMap" ofType:@"png"]; 53 | } 54 | 55 | [self bindBuffers]; 56 | 57 | self.diffuseColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"diffuseColor"]; 58 | self.filmDepth = [decoder decodeDoubleForKey:@"filmDepth"]; 59 | } 60 | return self; 61 | } 62 | 63 | - (void)encodeWithCoder:(NSCoder *)encoder { 64 | [encoder encodeObject:_imagePath forKey:@"imagePath"]; 65 | [encoder encodeObject:_diffuseColor forKey:@"diffuseColor"]; 66 | [encoder encodeDouble:_filmDepth forKey:@"filmDepth"]; 67 | } 68 | 69 | - (void)bindBuffers { 70 | SCNBufferBindingBlock lightBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 71 | { 72 | struct LightConstants { 73 | float position[3]; 74 | } lights; 75 | 76 | lights.position[0] = self.lightPosition.x; 77 | lights.position[1] = self.lightPosition.y; 78 | lights.position[2] = self.lightPosition.z; 79 | 80 | [buffer writeBytes:&lights length:sizeof(lights)]; 81 | }; 82 | 83 | SCNBufferBindingBlock materialBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 84 | { 85 | struct MaterialConstants { 86 | float diffuseColor[4]; 87 | float filmDepth; 88 | } material; 89 | 90 | if (self.diffuseColor) { 91 | material.diffuseColor[0] = self.diffuseColor.redComponent; 92 | material.diffuseColor[1] = self.diffuseColor.greenComponent; 93 | material.diffuseColor[2] = self.diffuseColor.blueComponent; 94 | material.diffuseColor[3] = self.diffuseColor.alphaComponent; 95 | } 96 | 97 | material.filmDepth = self.filmDepth; 98 | 99 | [buffer writeBytes:&material length:sizeof(material)]; 100 | }; 101 | 102 | [self handleBindingOfBufferNamed:@"light" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 103 | [self handleBindingOfBufferNamed:@"vertexMaterial" frequency:SCNBufferFrequencyPerFrame usingBlock:materialBlock]; 104 | [self handleBindingOfBufferNamed:@"fragmentMaterial" frequency:SCNBufferFrequencyPerFrame usingBlock:materialBlock]; 105 | } 106 | 107 | - (NSDictionary *)shadableProperties { 108 | NSDictionary *properties = @{ 109 | @"fringeMap" : [SCNMaterialProperty materialPropertyWithContents:self.imagePath] 110 | }; 111 | return properties; 112 | } 113 | 114 | #pragma mark - SCNProgramDelegate Protocol Methods 115 | - (void)program:(SCNProgram*)program handleError:(NSError*)error { 116 | // Log the shader compilation error 117 | NSLog(@"SceneKit compilation error: %@", error); 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /ScenekitStarter/EdgeFuzz.metal: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace metal; 3 | 4 | #include 5 | 6 | struct VertexIn { 7 | float4 position [[attribute(SCNVertexSemanticPosition)]]; 8 | float3 normal [[attribute(SCNVertexSemanticNormal)]]; 9 | float2 texCoords [[attribute(SCNVertexSemanticTexcoord0)]]; 10 | }; 11 | 12 | struct NodeConstants { 13 | float4x4 modelViewTransform; 14 | float4x4 modelViewProjectionTransform; 15 | float4x4 normalTransform; 16 | }; 17 | 18 | struct LightConstants { 19 | packed_float3 position; 20 | packed_float3 ambientIntensity; 21 | packed_float3 diffuseIntensity; 22 | }; 23 | 24 | struct MaterialConstants { 25 | packed_float4 edgeColor; 26 | packed_float4 surfaceColor; 27 | float specularity; 28 | float fuzziness; 29 | float edgeFade; 30 | }; 31 | 32 | struct VertexOut { 33 | float4 position [[position]]; 34 | float3 lightVec; 35 | float3 eyeView; 36 | float3 eyeNormal; 37 | }; 38 | 39 | ///////////////////////////////////// 40 | //// EDGE FUZZ VS //// 41 | ///////////////////////////////////// 42 | 43 | /* 44 | Adapted from: 45 | NVIDIA Shader Library effect 'EdgeFuzz.fx' 46 | http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html 47 | */ 48 | 49 | // Edge Fuzz Vertex Shader function 50 | void edgefuzzVS(constant NodeConstants &scn_node, float4 modelPosition, float4 N, float3 lightPosition, thread VertexOut &out) 51 | { 52 | float4 V = scn_node.modelViewTransform * modelPosition; 53 | float3 v = V.xyz / V.w; 54 | out.lightVec = lightPosition - v.xyz; 55 | out.eyeView = normalize(float3(0.0, 0.0, 2.0) - v.xyz); 56 | float4 n = scn_node.normalTransform * N; 57 | out.eyeNormal = normalize(n.xyz); 58 | } 59 | 60 | vertex VertexOut EdgeFuzzVertex(VertexIn in [[stage_in]], 61 | constant SCNSceneBuffer &scn_frame [[buffer(0)]], 62 | constant NodeConstants &scn_node [[buffer(1)]], 63 | constant LightConstants &vertexLights [[buffer(2)]]) 64 | { 65 | float4 n = float4(in.normal, 0.0f); 66 | 67 | VertexOut out; 68 | edgefuzzVS(scn_node, in.position, n, vertexLights.position, out); 69 | 70 | out.position = scn_node.modelViewProjectionTransform * in.position; 71 | 72 | return out; 73 | } 74 | 75 | ///////////////////////////////////// 76 | //// EDGE FUZZ FS //// 77 | ///////////////////////////////////// 78 | 79 | /* 80 | Adapted from: 81 | NVIDIA Shader Library effect 'EdgeFuzz.fx' 82 | */ 83 | 84 | float3 lit (float NdotL, float NdotH, float m) 85 | { 86 | float ambient = 1.0; 87 | float diffuse = max(NdotL, 0.0); 88 | float specular = step(0.0, NdotL) * max(NdotH * m, 1.0); 89 | return float3(ambient, diffuse, specular); 90 | } 91 | 92 | // Edge Fuzz Fragment Shader function 93 | float4 edgefuzzFS(VertexOut vert, constant LightConstants &light, constant MaterialConstants &material) 94 | { 95 | const float4 specularColor = float4(1.0, 1.0, 1.0, 1.0); 96 | float3 Ln = normalize(vert.lightVec); 97 | float3 Vn = normalize(vert.eyeView); 98 | float3 Nn = normalize(vert.eyeNormal); 99 | float3 Hn = normalize(Vn + Ln); 100 | float ldn = dot(Ln, Nn); 101 | float4 lv = float4(lit(ldn, dot(Hn, Nn), material.specularity), 1.0); 102 | float subd = abs(dot(Nn, Vn)); 103 | subd = powr(subd, material.fuzziness); 104 | float3 surfColor = mix(material.edgeColor.rgb, material.surfaceColor.rgb, subd); 105 | surfColor = mix(material.surfaceColor.rgb, surfColor, material.edgeFade); 106 | ldn = max(ldn,0.0); 107 | ldn = powr(ldn, material.fuzziness); 108 | float3 incidentColor = mix(material.edgeColor.rgb, light.diffuseIntensity.rgb, ldn); 109 | incidentColor = mix(light.diffuseIntensity.rgb, incidentColor, ldn); 110 | float3 diffContrib = surfColor * (lv.y * incidentColor + light.ambientIntensity.rgb); 111 | float3 specContrib = specularColor.rgb * lv.y * lv.z * incidentColor; 112 | 113 | return float4(diffContrib + specContrib, 1.0); 114 | } 115 | 116 | fragment float4 EdgeFuzzFragment(VertexOut in [[stage_in]], 117 | constant LightConstants &fragmentLights [[buffer(0)]], 118 | constant MaterialConstants &material [[buffer(1)]]) 119 | { 120 | return edgefuzzFS(in, fragmentLights, material); 121 | } 122 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHEnvMapProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHEnvMapProgram.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/25/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHEnvMapProgram.h" 10 | 11 | @interface CWHEnvMapProgram () 12 | @property (nonatomic, readonly) NSDictionary *shadableProperties; 13 | @end 14 | 15 | @implementation CWHEnvMapProgram 16 | 17 | +(BOOL) supportsSecureCoding { 18 | return YES; 19 | } 20 | 21 | - (instancetype)init 22 | { 23 | id device = MTLCreateSystemDefaultDevice(); 24 | id library = [device newDefaultLibrary]; 25 | 26 | self = [super initWithLibrary:library vertexFunctionName:@"EnvMapVertex" fragmentFunctionName:@"EnvMapFragment"]; 27 | 28 | if (self != nil) 29 | { 30 | self.delegate = self; 31 | 32 | [self bindBuffers]; 33 | 34 | NSColor *diffuseColor = [NSColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:1.]; 35 | self.diffuseColor = diffuseColor; 36 | NSColor *ambientColor = [NSColor colorWithRed:0. green:0. blue:0. alpha:1.]; 37 | self.ambientColor = ambientColor; 38 | self.ratio = 0.875; 39 | self.imagePath = [[NSBundle mainBundle] pathForResource:@"EnvMapInterior" ofType:@"png"]; 40 | } 41 | return self; 42 | } 43 | 44 | - (id)initWithCoder:(NSCoder *)decoder { 45 | id device = MTLCreateSystemDefaultDevice(); 46 | id library = [device newDefaultLibrary]; 47 | 48 | self = [super initWithLibrary:library vertexFunctionName:@"EnvMapVertex" fragmentFunctionName:@"EnvMapFragment"]; 49 | 50 | if (self != nil) { 51 | self.delegate = self; 52 | 53 | [self bindBuffers]; 54 | 55 | self.diffuseColor =[decoder decodeObjectOfClass:[NSColor class] forKey:@"diffuseColor"]; 56 | self.ambientColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"ambientColor"]; 57 | self.ratio = [decoder decodeDoubleForKey:@"ratio"]; 58 | self.imagePath = [decoder decodeObjectOfClass:[NSString class] forKey:@"imagePath"]; 59 | } 60 | return self; 61 | } 62 | 63 | - (void)encodeWithCoder:(NSCoder *)encoder { 64 | [encoder encodeObject:_diffuseColor forKey:@"diffuseColor"]; 65 | [encoder encodeObject:_ambientColor forKey:@"ambientColor"]; 66 | [encoder encodeDouble:_ratio forKey:@"ratio"]; 67 | [encoder encodeObject:_imagePath forKey:@"imagePath"]; 68 | } 69 | 70 | - (void)bindBuffers { 71 | SCNBufferBindingBlock lightBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 72 | { 73 | struct LightConstants { 74 | float position[3]; 75 | float ambientIntensity[3]; 76 | float diffuseIntensity[3]; 77 | } lights; 78 | 79 | lights.position[0] = self.lightPosition.x; 80 | lights.position[1] = self.lightPosition.y; 81 | lights.position[2] = self.lightPosition.z; 82 | 83 | if (self.diffuseColor) { 84 | lights.diffuseIntensity[0] = [self.diffuseColor redComponent]; 85 | lights.diffuseIntensity[1] = [self.diffuseColor greenComponent]; 86 | lights.diffuseIntensity[2] = [self.diffuseColor blueComponent]; 87 | } 88 | 89 | if (self.ambientColor) { 90 | lights.ambientIntensity[0] = [self.ambientColor redComponent]; 91 | lights.ambientIntensity[1] = [self.ambientColor greenComponent]; 92 | lights.ambientIntensity[2] = [self.ambientColor blueComponent]; 93 | } 94 | 95 | [buffer writeBytes:&lights length:sizeof(lights)]; 96 | }; 97 | 98 | [self handleBindingOfBufferNamed:@"vertexLights" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 99 | [self handleBindingOfBufferNamed:@"fragmentLights" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 100 | [self handleBindingOfBufferNamed:@"ratio" frequency:SCNBufferFrequencyPerFrame usingBlock: 101 | ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 102 | { 103 | float ratio = self.ratio; 104 | [buffer writeBytes:&ratio length:sizeof(float)]; 105 | }]; 106 | } 107 | 108 | - (NSDictionary *)shadableProperties { 109 | NSDictionary *properties = @{ 110 | @"environmentMap" : [SCNMaterialProperty materialPropertyWithContents:self.imagePath] 111 | }; 112 | return properties; 113 | } 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHEdgeFuzzParameterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHEdgeFuzzParameterViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/15/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHEdgeFuzzParameterViewController.h" 10 | 11 | @interface CWHEdgeFuzzParameterViewController () 12 | 13 | @end 14 | 15 | @implementation CWHEdgeFuzzParameterViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do view setup here. 20 | 21 | if(self.program){ 22 | 23 | NSColor *surfaceColor = [self.program valueForKey:@"surfaceColor"]; 24 | if (surfaceColor) { 25 | [self.surfaceColorWell setColor:surfaceColor]; 26 | self.surfaceColor= surfaceColor; 27 | } 28 | 29 | 30 | double fuzziness = [[self.program valueForKey:@"fuzziness"] doubleValue]; 31 | if (fuzziness) { 32 | [self.fuzzinessCircularSlider setDoubleValue:fuzziness]; 33 | [self.fuzzinessTextField setDoubleValue:fuzziness]; 34 | self.fuzziness = fuzziness; 35 | } 36 | 37 | double edgeFade = [[self.program valueForKey:@"edgeFade"] doubleValue]; 38 | if (edgeFade) { 39 | [self.edgeFadeCircularSlider setDoubleValue:edgeFade]; 40 | [self.edgeFadeTextField setDoubleValue:edgeFade]; 41 | self.edgeFade = edgeFade; 42 | } 43 | 44 | double specularity = [[self.program valueForKey:@"specularity"] doubleValue]; 45 | if (specularity) { 46 | [self.specularityCircularSlider setDoubleValue:specularity]; 47 | [self.specularityTextField setDoubleValue:specularity]; 48 | self.specularity = specularity; 49 | } 50 | 51 | NSColor *edgeColor = [self.program valueForKey:@"edgeColor"]; 52 | if (edgeColor) { 53 | [self.edgeColorWell setColor:edgeColor]; 54 | self.edgeColor= edgeColor; 55 | } 56 | 57 | NSColor *lightColor = [self.program valueForKey:@"lightColor"]; 58 | if (lightColor) { 59 | [self.lightColorWell setColor:lightColor]; 60 | self.lightColor = lightColor; 61 | } 62 | 63 | NSColor *ambientColor = [self.program valueForKey:@"ambientColor"]; 64 | if (ambientColor) { 65 | [self.ambientColorWell setColor:ambientColor]; 66 | self.ambientColor = ambientColor; 67 | } 68 | } 69 | 70 | } 71 | 72 | - (IBAction)updateFuzziness:(id)sender { 73 | //NSLog(@" update Fuzziness %f", [sender doubleValue]); 74 | self.fuzziness = [sender doubleValue]; 75 | if ([sender isKindOfClass:[NSSlider class]]) { 76 | [self.fuzzinessTextField setDoubleValue:[sender doubleValue]]; 77 | } 78 | 79 | [self updateShaderValues]; 80 | } 81 | 82 | - (IBAction)updateSurfaceColor:(id)sender { 83 | self.surfaceColor = [sender color]; 84 | [self updateShaderValues]; 85 | } 86 | 87 | - (IBAction)updateEdgeFade:(id)sender { 88 | self.edgeFade= [sender doubleValue]; 89 | if ([sender isKindOfClass:[NSSlider class]]) { 90 | [self.edgeFadeTextField setDoubleValue:[sender doubleValue]]; 91 | } 92 | [self updateShaderValues]; 93 | } 94 | 95 | - (IBAction)updateSpecularity:(id)sender { 96 | self.specularity = [sender doubleValue]; 97 | if ([sender isKindOfClass:[NSSlider class]]) { 98 | [self.specularityTextField setDoubleValue:[sender doubleValue]]; 99 | } 100 | 101 | [self updateShaderValues]; 102 | } 103 | 104 | - (IBAction)updateEdgeColor:(id)sender { 105 | self.edgeColor = [sender color]; 106 | [self updateShaderValues]; 107 | } 108 | 109 | - (IBAction)lightColor:(id)sender { 110 | self.lightColor = [sender color]; 111 | [self updateShaderValues]; 112 | } 113 | 114 | - (IBAction)updateAmbientColor:(id)sender { 115 | self.ambientColor = [sender color]; 116 | [self updateShaderValues]; 117 | } 118 | 119 | -(void)updateShaderValues 120 | { 121 | CWHEdgeFuzzProgram *program = (CWHEdgeFuzzProgram *)self.program; 122 | 123 | program.fuzziness = self.fuzziness; 124 | program.surfaceColor = self.surfaceColor; 125 | program.edgeFade = self.edgeFade; 126 | program.specularity = self.specularity; 127 | program.edgeColor = self.edgeColor; 128 | program.lightColor = self.lightColor; 129 | program.ambientColor = self.ambientColor; 130 | 131 | [self.delegate updateProgram:program shadableProperties:nil]; 132 | } 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHPhongPointLightProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHBlinnProgram.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/29/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHPhongPointLightProgram.h" 10 | 11 | @implementation CWHPhongPointLightProgram 12 | 13 | +(BOOL) supportsSecureCoding { 14 | return YES; 15 | } 16 | 17 | -(instancetype)init 18 | { 19 | id device = MTLCreateSystemDefaultDevice(); 20 | id library = [device newDefaultLibrary]; 21 | 22 | self = [super initWithLibrary:library vertexFunctionName:@"PhongVertex" fragmentFunctionName:@"PhongFragment"]; 23 | 24 | if ( self != nil ) 25 | { 26 | self.delegate = self; 27 | 28 | [self bindBuffers]; 29 | 30 | self.ambientColor = [NSColor colorWithRed:0. green:0. blue:0. alpha:1.]; 31 | self.lightColor = [NSColor redColor]; 32 | self.materialSpecularity = 1; 33 | self.shininess = 10.8; 34 | 35 | } 36 | 37 | return self; 38 | } 39 | 40 | - (id)initWithCoder:(NSCoder *)decoder { 41 | id device = MTLCreateSystemDefaultDevice(); 42 | id library = [device newDefaultLibrary]; 43 | 44 | self = [super initWithLibrary:library vertexFunctionName:@"PhongVertex" fragmentFunctionName:@"PhongFragment"]; 45 | 46 | if (self != nil) { 47 | self.ambientColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"ambientColor"]; 48 | self.lightColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"lightColor"]; 49 | self.materialSpecularity = [decoder decodeDoubleForKey:@"materialSpecularity"]; 50 | self.shininess = [decoder decodeDoubleForKey:@"shininess"]; 51 | 52 | [self bindBuffers]; 53 | 54 | self.delegate = self; 55 | } 56 | return self; 57 | } 58 | 59 | - (void)encodeWithCoder:(NSCoder *)encoder { 60 | [encoder encodeObject:_ambientColor forKey:@"ambientColor"]; 61 | [encoder encodeObject:_lightColor forKey:@"lightColor"]; 62 | [encoder encodeDouble:_materialSpecularity forKey:@"materialSpecularity"]; 63 | [encoder encodeDouble:_shininess forKey:@"shininess"]; 64 | } 65 | 66 | - (void)bindBuffers { 67 | SCNBufferBindingBlock lightBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 68 | { 69 | struct LightConstants { 70 | float position[3]; 71 | float diffuseIntensity[3]; 72 | float ambientIntensity[3]; 73 | } lights; 74 | 75 | lights.position[0] = self.lightPosition.x; 76 | lights.position[1] = self.lightPosition.y; 77 | lights.position[2] = self.lightPosition.z; 78 | 79 | if (self.lightColor) { 80 | lights.diffuseIntensity[0] = [self.lightColor redComponent]; 81 | lights.diffuseIntensity[1] = [self.lightColor greenComponent]; 82 | lights.diffuseIntensity[2] = [self.lightColor blueComponent]; 83 | } 84 | 85 | if (self.ambientColor) { 86 | lights.ambientIntensity[0] = [self.ambientColor redComponent]; 87 | lights.ambientIntensity[1] = [self.ambientColor greenComponent]; 88 | lights.ambientIntensity[2] = [self.ambientColor blueComponent]; 89 | } 90 | 91 | [buffer writeBytes:&lights length:sizeof(lights)]; 92 | }; 93 | 94 | SCNBufferBindingBlock materialBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 95 | { 96 | struct MaterialConstants { 97 | float specularColor[3]; 98 | float shininess; 99 | } material; 100 | 101 | material.specularColor[0] = self.materialSpecularity; 102 | material.specularColor[1] = self.materialSpecularity; 103 | material.specularColor[2] = self.materialSpecularity; 104 | material.shininess = self.shininess; 105 | 106 | [buffer writeBytes:&material length:sizeof(material)]; 107 | }; 108 | 109 | [self handleBindingOfBufferNamed:@"vertexLight" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 110 | [self handleBindingOfBufferNamed:@"fragmentLight" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 111 | [self handleBindingOfBufferNamed:@"material" frequency:SCNBufferFrequencyPerShadable usingBlock:materialBlock]; 112 | } 113 | 114 | #pragma mark - SCNProgramDelegate Protocol Methods 115 | 116 | - (void)program:(SCNProgram*)program handleError:(NSError*)error { 117 | // Log the shader compilation error 118 | NSLog(@"SceneKit compilation error: %@", error); 119 | } 120 | 121 | 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLambSkinProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHLambSkinProgram.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/31/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHLambSkinProgram.h" 10 | 11 | @implementation CWHLambSkinProgram 12 | 13 | +(BOOL) supportsSecureCoding { 14 | return YES; 15 | } 16 | 17 | -(instancetype)init 18 | { 19 | id device = MTLCreateSystemDefaultDevice(); 20 | id library = [device newDefaultLibrary]; 21 | 22 | self = [super initWithLibrary:library vertexFunctionName:@"LambSkinVertex" fragmentFunctionName:@"LambSkinFragment"]; 23 | 24 | if (self != nil) 25 | { 26 | self.delegate = self; 27 | 28 | [self bindBuffers]; 29 | 30 | NSColor *diffuseColor = [NSColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:1.0]; 31 | self.diffuseColor = diffuseColor; 32 | NSColor *ambientColor = [NSColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0]; 33 | self.ambientColor = ambientColor; 34 | NSColor *subColor = [NSColor colorWithRed:1. green:0.0 blue:0.0 alpha:1.0]; 35 | self.subColor = subColor; 36 | self.rolloff = 0.575; 37 | } 38 | 39 | return self; 40 | } 41 | 42 | - (id)initWithCoder:(NSCoder *)decoder { 43 | id device = MTLCreateSystemDefaultDevice(); 44 | id library = [device newDefaultLibrary]; 45 | 46 | self = [super initWithLibrary:library vertexFunctionName:@"LambSkinVertex" fragmentFunctionName:@"LambSkinFragment"]; 47 | 48 | if (self != nil) 49 | { 50 | self.delegate = self; 51 | 52 | [self bindBuffers]; 53 | 54 | self.diffuseColor =[decoder decodeObjectOfClass:[NSColor class] forKey:@"diffuseColor"]; 55 | self.ambientColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"ambientColor"]; 56 | self.subColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"subColor"]; 57 | self.rolloff = [decoder decodeDoubleForKey:@"rolloff"]; 58 | 59 | } 60 | return self; 61 | } 62 | 63 | - (void)encodeWithCoder:(NSCoder *)encoder { 64 | [encoder encodeObject:_diffuseColor forKey:@"diffuseColor"]; 65 | [encoder encodeObject:_ambientColor forKey:@"ambientColor"]; 66 | [encoder encodeObject:_subColor forKey:@"subColor"]; 67 | [encoder encodeDouble:_rolloff forKey:@"rolloff"]; 68 | } 69 | 70 | - (void)bindBuffers { 71 | SCNBufferBindingBlock lightBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 72 | { 73 | struct LightConstants { 74 | float position[3]; 75 | } lights; 76 | 77 | lights.position[0] = self.lightPosition.x; 78 | lights.position[1] = self.lightPosition.y; 79 | lights.position[2] = self.lightPosition.z; 80 | 81 | [buffer writeBytes:&lights length:sizeof(lights)]; 82 | }; 83 | 84 | SCNBufferBindingBlock materialBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 85 | { 86 | struct MaterialConstants { 87 | float ambientColor[3]; 88 | float diffuseColor[3]; 89 | float subColor[3]; 90 | float rolloff; 91 | } material; 92 | 93 | if (self.ambientColor) { 94 | material.ambientColor[0] = self.ambientColor.redComponent; 95 | material.ambientColor[1] = self.ambientColor.greenComponent; 96 | material.ambientColor[2] = self.ambientColor.blueComponent; 97 | } 98 | 99 | if (self.diffuseColor) { 100 | material.diffuseColor[0] = self.diffuseColor.redComponent; 101 | material.diffuseColor[1] = self.diffuseColor.greenComponent; 102 | material.diffuseColor[2] = self.diffuseColor.blueComponent; 103 | } 104 | 105 | if (self.subColor) { 106 | material.subColor[0] = self.subColor.redComponent; 107 | material.subColor[1] = self.subColor.greenComponent; 108 | material.subColor[2] = self.subColor.blueComponent; 109 | } 110 | 111 | material.rolloff = self.rolloff; 112 | 113 | [buffer writeBytes:&material length:sizeof(material)]; 114 | }; 115 | 116 | [self handleBindingOfBufferNamed:@"light" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 117 | [self handleBindingOfBufferNamed:@"material" frequency:SCNBufferFrequencyPerFrame usingBlock:materialBlock]; 118 | } 119 | 120 | #pragma mark - SCNProgramDelegate Protocol Methods 121 | 122 | - (void)program:(SCNProgram*)program handleError:(NSError*)error { 123 | // Log the shader compilation error 124 | NSLog(@"SceneKit compilation error: %@", error); 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHVelvetProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHVelvetProgram.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/30/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHVelvetProgram.h" 10 | 11 | @implementation CWHVelvetProgram 12 | 13 | +(BOOL) supportsSecureCoding { 14 | return YES; 15 | } 16 | 17 | -(instancetype)init 18 | { 19 | id device = MTLCreateSystemDefaultDevice(); 20 | id library = [device newDefaultLibrary]; 21 | 22 | self = [super initWithLibrary:library vertexFunctionName:@"VelvetVertex" fragmentFunctionName:@"VelvetFragment"]; 23 | 24 | if (self != nil) 25 | { 26 | self.delegate = self; 27 | 28 | [self bindBuffers]; 29 | 30 | NSColor *underColor = [NSColor colorWithRed:0.7 green:0.7 blue:0 alpha:1.0]; 31 | self.underColor = underColor; 32 | NSColor *fuzzColor = [NSColor colorWithRed:0.9 green:0.7 blue:0.5 alpha:1.0]; 33 | self.fuzzColor = fuzzColor; 34 | self.rolloff = 0.528; 35 | } 36 | 37 | return self; 38 | } 39 | 40 | - (id)initWithCoder:(NSCoder *)decoder { 41 | id device = MTLCreateSystemDefaultDevice(); 42 | id library = [device newDefaultLibrary]; 43 | 44 | self = [super initWithLibrary:library vertexFunctionName:@"VelvetVertex" fragmentFunctionName:@"VelvetFragment"]; 45 | 46 | if (self != nil) 47 | { 48 | self.delegate = self; 49 | 50 | [self bindBuffers]; 51 | 52 | self.underColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"underColor"]; 53 | self.fuzzColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"fuzzColor"]; 54 | self.primaryColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"primaryColor"]; 55 | self.rolloff = [decoder decodeDoubleForKey:@"rolloff"]; 56 | } 57 | return self; 58 | } 59 | 60 | - (void)encodeWithCoder:(NSCoder *)encoder { 61 | [encoder encodeObject:_underColor forKey:@"underColor"]; 62 | [encoder encodeObject:_fuzzColor forKey:@"fuzzColor"]; 63 | [encoder encodeObject:_primaryColor forKey:@"primaryColor"]; 64 | [encoder encodeDouble:_rolloff forKey:@"rolloff"]; 65 | } 66 | 67 | - (void)bindBuffers { 68 | SCNBufferBindingBlock lightBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 69 | { 70 | struct LightConstants { 71 | float position[3]; 72 | } lights; 73 | 74 | lights.position[0] = self.lightPosition.x; 75 | lights.position[1] = self.lightPosition.y; 76 | lights.position[2] = self.lightPosition.z; 77 | 78 | [buffer writeBytes:&lights length:sizeof(lights)]; 79 | }; 80 | 81 | SCNBufferBindingBlock materialBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 82 | { 83 | struct MaterialConstants { 84 | float primaryColor[4]; 85 | float fuzzColor[4]; 86 | float underColor[4]; 87 | float rolloff; 88 | } material; 89 | 90 | if (self.primaryColor) { 91 | material.primaryColor[0] = self.primaryColor.redComponent; 92 | material.primaryColor[1] = self.primaryColor.greenComponent; 93 | material.primaryColor[2] = self.primaryColor.blueComponent; 94 | material.primaryColor[3] = self.primaryColor.alphaComponent; 95 | } 96 | 97 | if (self.fuzzColor) { 98 | material.fuzzColor[0] = self.fuzzColor.redComponent; 99 | material.fuzzColor[1] = self.fuzzColor.greenComponent; 100 | material.fuzzColor[2] = self.fuzzColor.blueComponent; 101 | material.fuzzColor[3] = self.fuzzColor.alphaComponent; 102 | } 103 | 104 | if (self.underColor) { 105 | material.underColor[0] = self.underColor.redComponent; 106 | material.underColor[1] = self.underColor.greenComponent; 107 | material.underColor[2] = self.underColor.blueComponent; 108 | material.underColor[3] = self.underColor.alphaComponent; 109 | } 110 | 111 | material.rolloff = self.rolloff; 112 | 113 | [buffer writeBytes:&material length:sizeof(material)]; 114 | }; 115 | 116 | [self handleBindingOfBufferNamed:@"light" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 117 | [self handleBindingOfBufferNamed:@"material" frequency:SCNBufferFrequencyPerFrame usingBlock:materialBlock]; 118 | } 119 | 120 | #pragma mark - SCNProgramDelegate Protocol Methods 121 | 122 | - (void)program:(SCNProgram*)program handleError:(NSError*)error { 123 | // Log the shader compilation error 124 | NSLog(@"SceneKit compilation error: %@", error); 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLUTSkinProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHLUTSkinProgram.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/31/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHLUTSkinProgram.h" 10 | 11 | @implementation CWHLUTSkinProgram 12 | 13 | +(BOOL) supportsSecureCoding { 14 | return YES; 15 | } 16 | 17 | -(instancetype)init 18 | { 19 | id device = MTLCreateSystemDefaultDevice(); 20 | id library = [device newDefaultLibrary]; 21 | 22 | self = [super initWithLibrary:library vertexFunctionName:@"LUTSkinVertex" fragmentFunctionName:@"LUTSkinFragment"]; 23 | 24 | if (self != nil) 25 | { 26 | self.delegate = self; 27 | 28 | [self bindBuffers]; 29 | 30 | self.diffuseColor = [NSColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0];; 31 | self.specularColor = [NSColor whiteColor]; 32 | self.scatterColor = [NSColor redColor]; 33 | self.wrap = 0.58; 34 | self.scatterWidth = 0.10; 35 | self.shininess = 0.35; 36 | } 37 | 38 | return self; 39 | } 40 | 41 | - (id)initWithCoder:(NSCoder *)decoder { 42 | id device = MTLCreateSystemDefaultDevice(); 43 | id library = [device newDefaultLibrary]; 44 | 45 | self = [super initWithLibrary:library vertexFunctionName:@"LUTSkinVertex" fragmentFunctionName:@"LUTSkinFragment"]; 46 | 47 | if (self != nil) 48 | { 49 | self.delegate = self; 50 | 51 | [self bindBuffers]; 52 | 53 | self.diffuseColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"diffuseColor"]; 54 | self.specularColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"specularColor"]; 55 | self.scatterColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"scatterColor"]; 56 | self.wrap = [decoder decodeDoubleForKey:@"wrap"]; 57 | self.scatterWidth = [decoder decodeDoubleForKey:@"scatterWidth"]; 58 | self.shininess = [decoder decodeDoubleForKey:@"shininess"]; 59 | } 60 | return self; 61 | } 62 | 63 | - (void)encodeWithCoder:(NSCoder *)encoder { 64 | [encoder encodeObject:_diffuseColor forKey:@"diffuseColor"]; 65 | [encoder encodeObject:_specularColor forKey:@"specularColor"]; 66 | [encoder encodeObject:_scatterColor forKey:@"scatterColor"]; 67 | [encoder encodeDouble:_wrap forKey:@"wrap"]; 68 | [encoder encodeDouble:_scatterWidth forKey:@"scatterWidth"]; 69 | [encoder encodeDouble:_shininess forKey:@"shininess"]; 70 | } 71 | 72 | - (void)bindBuffers { 73 | SCNBufferBindingBlock lightBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 74 | { 75 | struct LightConstants { 76 | float position[3]; 77 | } lights; 78 | 79 | lights.position[0] = self.lightPosition.x; 80 | lights.position[1] = self.lightPosition.y; 81 | lights.position[2] = self.lightPosition.z; 82 | 83 | [buffer writeBytes:&lights length:sizeof(lights)]; 84 | }; 85 | 86 | SCNBufferBindingBlock materialBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 87 | { 88 | struct MaterialConstants { 89 | float diffuseColor[4]; 90 | float specularColor[4]; 91 | } material; 92 | 93 | if (self.diffuseColor) { 94 | material.diffuseColor[0] = self.diffuseColor.redComponent; 95 | material.diffuseColor[1] = self.diffuseColor.greenComponent; 96 | material.diffuseColor[2] = self.diffuseColor.blueComponent; 97 | material.diffuseColor[3] = self.diffuseColor.alphaComponent; 98 | } 99 | 100 | if (self.specularColor) { 101 | material.specularColor[0] = self.specularColor.redComponent; 102 | material.specularColor[1] = self.specularColor.greenComponent; 103 | material.specularColor[2] = self.specularColor.blueComponent; 104 | material.specularColor[3] = self.specularColor.alphaComponent; 105 | } 106 | 107 | [buffer writeBytes:&material length:sizeof(material)]; 108 | }; 109 | 110 | [self handleBindingOfBufferNamed:@"light" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 111 | [self handleBindingOfBufferNamed:@"material" frequency:SCNBufferFrequencyPerShadable usingBlock:materialBlock]; 112 | } 113 | 114 | - (NSDictionary *)shadableProperties { 115 | NSDictionary *properties = @{ 116 | @"skinLUT" : [SCNMaterialProperty materialPropertyWithContents:@""] 117 | }; 118 | return properties; 119 | } 120 | 121 | #pragma mark - SCNProgramDelegate Protocol Methods 122 | 123 | - (void)program:(SCNProgram*)program handleError:(NSError*)error { 124 | // Log the shader compilation error 125 | NSLog(@"SceneKit compilation error: %@", error); 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHGoochProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHBlinnProgram.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/29/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHGoochProgram.h" 10 | 11 | @implementation CWHGoochProgram 12 | 13 | +(BOOL) supportsSecureCoding { 14 | return YES; 15 | } 16 | 17 | -(instancetype)init 18 | { 19 | id device = MTLCreateSystemDefaultDevice(); 20 | id library = [device newDefaultLibrary]; 21 | 22 | self = [super initWithLibrary:library vertexFunctionName:@"GoochVertex" fragmentFunctionName:@"GoochFragment"]; 23 | 24 | if ( self != nil ) 25 | { 26 | self.delegate = self; 27 | 28 | [self bindBuffers]; 29 | 30 | NSColor *surfaceColor = [NSColor redColor]; 31 | self.surfaceColor = surfaceColor; 32 | 33 | NSColor *coolColor = [NSColor colorWithRed:0.2 green:1.0 blue:0.2 alpha:1.0]; 34 | self.coolColor = coolColor; 35 | 36 | NSColor *warmColor = [NSColor purpleColor]; 37 | self.warmColor = warmColor; 38 | 39 | self.diffuseCool = 0.0; 40 | self.diffuseWarm = 1.0; 41 | } 42 | 43 | return self; 44 | } 45 | 46 | - (id)initWithCoder:(NSCoder *)decoder { 47 | id device = MTLCreateSystemDefaultDevice(); 48 | id library = [device newDefaultLibrary]; 49 | 50 | self = [super initWithLibrary:library vertexFunctionName:@"GoochVertex" fragmentFunctionName:@"GoochFragment"]; 51 | 52 | if ( self != nil ) 53 | { 54 | self.delegate = self; 55 | 56 | [self bindBuffers]; 57 | 58 | self.coolColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"coolColor"]; 59 | self.warmColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"warmColor"]; 60 | self.surfaceColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"surfaceColor"]; 61 | self.diffuseCool = [decoder decodeDoubleForKey:@"diffuseCool"]; 62 | self.diffuseWarm = [decoder decodeDoubleForKey:@"diffuseWarm"]; 63 | } 64 | return self; 65 | } 66 | 67 | - (void)encodeWithCoder:(NSCoder *)encoder { 68 | [encoder encodeObject:_coolColor forKey:@"coolColor"]; 69 | [encoder encodeObject:_warmColor forKey:@"warmColor"]; 70 | [encoder encodeObject:_surfaceColor forKey:@"surfaceColor"]; 71 | [encoder encodeDouble:_diffuseCool forKey:@"diffuseCool"]; 72 | [encoder encodeDouble:_diffuseWarm forKey:@"diffuseWarm"]; 73 | } 74 | 75 | - (void)bindBuffers { 76 | SCNBufferBindingBlock lightBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 77 | { 78 | struct LightConstants { 79 | float position[3]; 80 | } lights; 81 | 82 | lights.position[0] = self.lightPosition.x; 83 | lights.position[1] = self.lightPosition.y; 84 | lights.position[2] = self.lightPosition.z; 85 | 86 | [buffer writeBytes:&lights length:sizeof(lights)]; 87 | }; 88 | 89 | SCNBufferBindingBlock materialBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 90 | { 91 | struct MaterialConstants { 92 | float surfaceColor[4]; 93 | float warmColor[4]; 94 | float coolColor[4]; 95 | float diffuseWarm; 96 | float diffuseCool; 97 | } material; 98 | 99 | if (self.surfaceColor) { 100 | material.surfaceColor[0] = self.surfaceColor.redComponent; 101 | material.surfaceColor[1] = self.surfaceColor.greenComponent; 102 | material.surfaceColor[2] = self.surfaceColor.blueComponent; 103 | material.surfaceColor[3] = self.surfaceColor.alphaComponent; 104 | } 105 | 106 | if (self.warmColor) { 107 | material.warmColor[0] = self.warmColor.redComponent; 108 | material.warmColor[1] = self.warmColor.greenComponent; 109 | material.warmColor[2] = self.warmColor.blueComponent; 110 | material.warmColor[3] = self.warmColor.alphaComponent; 111 | } 112 | 113 | if (self.coolColor) { 114 | material.coolColor[0] = self.coolColor.redComponent; 115 | material.coolColor[1] = self.coolColor.greenComponent; 116 | material.coolColor[2] = self.coolColor.blueComponent; 117 | material.coolColor[3] = self.coolColor.alphaComponent; 118 | } 119 | 120 | material.diffuseWarm = self.diffuseWarm; 121 | material.diffuseCool = self.diffuseCool; 122 | 123 | [buffer writeBytes:&material length:sizeof(material)]; 124 | }; 125 | 126 | [self handleBindingOfBufferNamed:@"light" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 127 | [self handleBindingOfBufferNamed:@"material" frequency:SCNBufferFrequencyPerFrame usingBlock:materialBlock]; 128 | } 129 | 130 | #pragma mark - SCNProgramDelegate Protocol Methods 131 | 132 | - (void)program:(SCNProgram*)program handleError:(NSError*)error { 133 | // Log the shader compilation error 134 | NSLog(@"SceneKit compilation error: %@", error); 135 | } 136 | 137 | @end 138 | -------------------------------------------------------------------------------- /ScenekitStarter/ThinFilmParameterView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHGlossyWetHighlightParameterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHGlossyWetHighlightParameterViewController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 9/12/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHGlossyWetHighlightParameterViewController.h" 10 | 11 | @interface CWHGlossyWetHighlightParameterViewController () 12 | @end 13 | 14 | @implementation CWHGlossyWetHighlightParameterViewController 15 | 16 | - (void)viewDidLoad { 17 | [super viewDidLoad]; 18 | 19 | NSColor *ambientColor = [self.program valueForKey:@"ambientColor"]; 20 | 21 | if (ambientColor) { 22 | [self.ambientColorWell setColor:ambientColor]; 23 | } 24 | 25 | NSColor *diffuseColor = [self.program valueForKey:@"diffuseColor"]; 26 | 27 | if (diffuseColor) { 28 | [self.diffuseColorWell setColor:diffuseColor]; 29 | } 30 | 31 | NSColor *specularColor = [self.program valueForKey:@"specularColor"]; 32 | 33 | if (specularColor) { 34 | [self.specularColorWell setColor:specularColor]; 35 | } 36 | 37 | double glossMin = [[self.program valueForKey:@"glossMin"] doubleValue]; 38 | if (glossMin >= 0) { 39 | [self.glossMinSlider setDoubleValue:glossMin]; 40 | [self.glossMinTextField setDoubleValue:glossMin]; 41 | 42 | } 43 | 44 | double glossMax = [[self.program valueForKey:@"glossMax"] doubleValue]; 45 | if (glossMax >= 0) { 46 | [self.glossMaxSlider setDoubleValue:glossMax]; 47 | [self.glossMaxTextField setDoubleValue:glossMax]; 48 | } 49 | 50 | double glossDrop = [[self.program valueForKey:@"glossDrop"] doubleValue]; 51 | if (glossDrop >= 0) { 52 | [self.glossDropSlider setDoubleValue:glossDrop]; 53 | [self.glossDropTextField setDoubleValue:glossDrop]; 54 | } 55 | 56 | double specularity = [[self.program valueForKey:@"specularity"] doubleValue]; 57 | if (specularity >= 0) { 58 | [self.specularitySlider setDoubleValue:specularity]; 59 | [self.specularityTextField setDoubleValue:specularity]; 60 | } 61 | 62 | double specularExponent = [[self.program valueForKey:@"specularExponent"] doubleValue]; 63 | if (specularExponent >= 0) { 64 | [self.specularExponentSlider setDoubleValue:specularExponent]; 65 | [self.specularExponentTextField setDoubleValue:specularExponent]; 66 | } 67 | } 68 | 69 | - (IBAction)updateGlossMin:(id)sender { 70 | if ([sender isKindOfClass:[NSSlider class]]) { 71 | [self.glossMinTextField setDoubleValue:[sender doubleValue]]; 72 | }else{ 73 | [self.glossMinSlider setDoubleValue:[sender doubleValue]]; 74 | } 75 | 76 | [self updateShaderValues]; 77 | } 78 | 79 | - (IBAction)updateGlossMax:(id)sender { 80 | if ([sender isKindOfClass:[NSSlider class]]) { 81 | [self.glossMaxTextField setDoubleValue:[sender doubleValue]]; 82 | }else{ 83 | [self.glossMaxSlider setDoubleValue:[sender doubleValue]]; 84 | } 85 | 86 | [self updateShaderValues]; 87 | } 88 | 89 | - (IBAction)updateGlossDrop:(id)sender { 90 | if ([sender isKindOfClass:[NSSlider class]]) { 91 | [self.glossDropTextField setDoubleValue:[sender doubleValue]]; 92 | }else{ 93 | [self.glossDropSlider setDoubleValue:[sender doubleValue]]; 94 | } 95 | 96 | [self updateShaderValues]; 97 | 98 | } 99 | 100 | - (IBAction)updateSpecularExponent:(id)sender { 101 | 102 | if ([sender isKindOfClass:[NSSlider class]]) { 103 | [self.specularExponentTextField setDoubleValue:[sender doubleValue]]; 104 | }else{ 105 | [self.specularExponentSlider setDoubleValue:[sender doubleValue]]; 106 | } 107 | 108 | [self updateShaderValues]; 109 | } 110 | 111 | - (IBAction)updateSpecularity:(id)sender { 112 | 113 | if ([sender isKindOfClass:[NSSlider class]]) { 114 | [self.specularityTextField setDoubleValue:[sender doubleValue]]; 115 | }else{ 116 | [self.specularitySlider setDoubleValue:[sender doubleValue]]; 117 | } 118 | 119 | [self updateShaderValues]; 120 | } 121 | 122 | - (IBAction)updateDiffuseColor:(id)sender { 123 | [self updateShaderValues]; 124 | } 125 | 126 | - (IBAction)updateAmbientColor:(id)sender { 127 | [self updateShaderValues]; 128 | } 129 | 130 | - (IBAction)updateSpecularColor:(id)sender { 131 | [self updateShaderValues]; 132 | } 133 | 134 | -(void)updateShaderValues 135 | { 136 | CWHGlossyWetHighlightProgram *program = (CWHGlossyWetHighlightProgram *)self.program; 137 | 138 | program.glossMin = [self.glossMinSlider doubleValue]; 139 | program.glossMax = [self.glossMaxSlider doubleValue]; 140 | program.glossDrop = [self.glossDropSlider doubleValue]; 141 | program.specularExponent = [self.specularExponentSlider doubleValue]; 142 | program.specularity = [self.specularitySlider doubleValue]; 143 | program.specularColor = [self.specularColorWell color]; 144 | program.ambientColor = [self.ambientColorWell color]; 145 | program.diffuseColor = [self.diffuseColorWell color]; 146 | 147 | [self.delegate updateProgram:program shadableProperties:nil]; 148 | } 149 | 150 | @end 151 | -------------------------------------------------------------------------------- /ScenekitStarter/GlossyWetHighlight.metal: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace metal; 3 | 4 | #include 5 | 6 | struct VertexIn { 7 | float4 position [[attribute(SCNVertexSemanticPosition)]]; 8 | float3 normal [[attribute(SCNVertexSemanticNormal)]]; 9 | float2 texCoords [[attribute(SCNVertexSemanticTexcoord0)]]; 10 | }; 11 | 12 | struct NodeConstants { 13 | float4x4 modelViewTransform; 14 | float4x4 modelViewProjectionTransform; 15 | float4x4 normalTransform; 16 | float4x4 inverseProjectionTransform; 17 | }; 18 | 19 | struct LightConstants { 20 | packed_float3 position; 21 | packed_float3 ambientIntensity; 22 | packed_float3 diffuseIntensity; 23 | packed_float3 specularIntensity; 24 | }; 25 | 26 | struct MaterialConstants { 27 | float specularExponent; 28 | float specularity; 29 | float glossMin; 30 | float glossMax; 31 | float glossDrop; 32 | }; 33 | 34 | struct VertexOut { 35 | float4 position [[position]]; 36 | //float4 color; 37 | float2 texCoords; 38 | float3 lightVec; 39 | float3 eyeView; 40 | float3 eyeNormal; 41 | }; 42 | 43 | /* 44 | Adapted from: 45 | 'glossyWetHilight.fx' from NVIDIA shader library 46 | http://developer.download.nvidia.com/shaderlibrary/HLSL/glossyWetHilight.fx 47 | NDVIDIA Corporation 2007 48 | 49 | HLSL > GLSL conversion and Quartz Composer setup 50 | toneburst 2008 51 | http://machinesdontcare.wordpress.com 52 | */ 53 | 54 | // Main Glossy Wet Hilight Vertex Shader function 55 | void glossyWetVS(VertexIn in, thread VertexOut &out, constant NodeConstants &scn_node, constant LightConstants &light) 56 | { 57 | out.lightVec = light.position.xyz - in.position.xyz; 58 | out.eyeView = normalize(scn_node.inverseProjectionTransform[3].xyz - in.position.xyz); 59 | float4 n = scn_node.normalTransform * float4(in.normal, 0.0f); 60 | out.eyeNormal = normalize(n.xyz); 61 | } 62 | 63 | vertex VertexOut GlossyWetHighlightVertex(VertexIn in [[stage_in]], 64 | constant SCNSceneBuffer &scn_frame [[buffer(0)]], 65 | constant NodeConstants &scn_node [[buffer(1)]], 66 | constant LightConstants &vertexLights [[buffer(2)]]) 67 | { 68 | VertexOut out; 69 | glossyWetVS(in, out, scn_node, vertexLights); 70 | 71 | out.position = scn_node.modelViewProjectionTransform * in.position; 72 | //out.color = in.color; 73 | out.texCoords = /*gl_TextureMatrix[0] **/ in.texCoords; 74 | 75 | return out; 76 | } 77 | 78 | /* 79 | Adapted from: 80 | 'glossyWetHilight.fx' from NVIDIA shader library 81 | http://developer.download.nvidia.com/shaderlibrary/HLSL/glossyWetHilight.fx 82 | NDVIDIA Corporation 2007 83 | 84 | HLSL > GLSL conversion and Quartz Composer setup 85 | toneburst 2008 86 | http://machinesdontcare.wordpress.com 87 | */ 88 | 89 | static float3 lit (float NdotL, float NdotH, float m) 90 | { 91 | float ambient = 1.0; 92 | float diffuse = max(NdotL, 0.0); 93 | float specular = step(0.0, NdotL) * max(NdotH * m, 1.0); 94 | return float3(ambient, diffuse, specular); 95 | } 96 | 97 | // Calculates specular dropoff 98 | float glossy_drop(float v, float gMax, float gMin, float gDrop) 99 | { 100 | return (gDrop + smoothstep(gMin, gMax, v) * (1.0f - gDrop)); 101 | } 102 | 103 | // Main Glossy Wet Hilight Fragment Shader function 104 | float4 glossyWetFS(thread VertexOut &in, float4 baseColor, constant LightConstants &light, constant MaterialConstants &material) 105 | { 106 | float3 Ln = normalize(in.lightVec); 107 | float3 Nn = normalize(in.eyeNormal); 108 | float3 Vn = normalize(in.eyeView); 109 | float3 Hn = normalize(Vn + Ln); 110 | // Specular component 111 | float4 litV = float4(lit(dot(Ln, Nn), dot(Hn, Nn), material.specularExponent), 1.0); 112 | float spec = powr(litV.y, litV.z); 113 | spec *= (material.specularity * glossy_drop(spec, material.glossMax, material.glossMin, material.glossDrop)); 114 | float3 specularContrib = spec * light.specularIntensity.xyz; 115 | // Diffuse component 116 | float3 diffuseContrib = litV.y * light.diffuseIntensity.xyz + light.ambientIntensity.xyz; 117 | // Combine lighting components and output result 118 | return float4(specularContrib + (baseColor.rgb * diffuseContrib), baseColor.a); 119 | } 120 | 121 | fragment float4 GlossyWetHighlightFragment(VertexOut in [[stage_in]], 122 | /*texture2d tex2d [[texture(0)]],*/ 123 | constant LightConstants &fragmentLights [[buffer(0)]], 124 | constant MaterialConstants &material [[buffer(1)]]) 125 | { 126 | /* 127 | constexpr sampler bilinearClampedSampler(coord::normalized, 128 | min_filter::linear, 129 | mag_filter::linear, 130 | mip_filter::none, 131 | address::clamp_to_edge); 132 | 133 | float4 baseColor = tex2d.sample(bilinearClampedSampler, in.texCoords); 134 | */ 135 | float4 baseColor(1.0f, 1.0f, 1.0f, 1.0f); 136 | return glossyWetFS(in, baseColor, fragmentLights, material); 137 | } 138 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHLightingModelWindowController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHLightingModelWindowController.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 8/1/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHLightingModelWindowController.h" 10 | #import "CWHLightingViewController.h" 11 | #import "CWHParameterViewController.h" 12 | 13 | @interface CWHLightingModelWindowController () 14 | -(void)saveShaderValues; 15 | @end 16 | 17 | @implementation CWHLightingModelWindowController 18 | 19 | - (void)awakeFromNib 20 | { 21 | self.lightingParameterState = FALSE; 22 | [self updateLightingModel:self.lightingModelPopupButton]; 23 | } 24 | 25 | -(void)parameterViewWillClose { 26 | self.lightingParameterState = FALSE; 27 | [self saveShaderValues]; 28 | } 29 | 30 | -(void)updateProgram:(SCNProgram *)program shadableProperties:(NSDictionary *)properties; 31 | { 32 | self.currentProgram = program; 33 | 34 | SCNNode *shadedNode = self.lightingViewController.geometryNode; 35 | 36 | SCNMaterial *programMaterial = [SCNMaterial material]; 37 | programMaterial.program = program; 38 | for (NSString *key in properties) { 39 | [programMaterial setValue:properties[key] forKey:key]; 40 | } 41 | shadedNode.geometry.materials = @[programMaterial]; 42 | } 43 | 44 | -(CWHParameterViewController *)parameterViewControllerForCurrentProgram 45 | { 46 | NSString *strippedString = [self.currentLightingModel stringByReplacingOccurrencesOfString:@" " withString:@""]; 47 | NSString *programString = [NSString stringWithFormat:@"CWH%@ParameterViewController", strippedString]; 48 | NSString *nibString = [NSString stringWithFormat:@"%@ParameterView", strippedString]; 49 | 50 | Class parameterViewControllerClass = NSClassFromString(programString); 51 | CWHParameterViewController *parameterViewController = nil; 52 | if (parameterViewControllerClass) { 53 | parameterViewController = [[parameterViewControllerClass alloc] 54 | initWithNibName:nibString bundle:nil]; 55 | } 56 | 57 | parameterViewController.program = self.currentProgram; 58 | 59 | return parameterViewController; 60 | } 61 | 62 | -(IBAction)showInputParameters:(id)sender 63 | { 64 | if(self.lightingParameterState == FALSE){ 65 | CWHParameterViewController *parameterViewController = [self parameterViewControllerForCurrentProgram]; 66 | 67 | if (parameterViewController) { 68 | [self.lightingViewController presentViewController:parameterViewController 69 | asPopoverRelativeToRect:self.parameterToolbarItem.view.bounds 70 | ofView:self.parameterToolbarItem.view 71 | preferredEdge:NSMaxYEdge 72 | behavior:NSPopoverBehaviorTransient]; 73 | 74 | parameterViewController.delegate = self; 75 | self.lightingParameterState = TRUE; 76 | } 77 | 78 | }else{ 79 | self.lightingParameterState = FALSE; 80 | } 81 | 82 | } 83 | 84 | -(void)saveShaderValues 85 | { 86 | NSError *error = nil; 87 | if(self.currentProgram) { 88 | NSString *className = NSStringFromClass([self.currentProgram class]); 89 | NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.currentProgram requiringSecureCoding:YES error:&error]; 90 | if (data) { 91 | [[NSUserDefaults standardUserDefaults] setObject:data forKey:className]; 92 | } else { 93 | NSLog(@"Encountered error when serializing shader program: %@", error.localizedDescription); 94 | } 95 | } 96 | } 97 | 98 | -(SCNProgram *)programForLightingModel:(NSString *)lightingModel 99 | { 100 | NSString *strippedString = [lightingModel stringByReplacingOccurrencesOfString:@" " withString:@""]; 101 | NSString *programString = [NSString stringWithFormat:@"CWH%@Program", strippedString]; 102 | Class programClass = NSClassFromString(programString); 103 | 104 | SCNProgram *program = nil; 105 | //unarchive here if we've changed some parameters 106 | NSData *programData = [[NSUserDefaults standardUserDefaults] objectForKey:programString]; 107 | if(programData){ 108 | NSError *error = nil; 109 | program = [NSKeyedUnarchiver unarchivedObjectOfClass:programClass fromData:programData error:&error]; 110 | if (program == nil) { 111 | NSLog(@"Encountered error when deserializing shader program: %@", error.localizedDescription); 112 | } 113 | } else if (programClass) { 114 | program = (SCNProgram *)[programClass program]; 115 | } 116 | 117 | return program; 118 | } 119 | 120 | - (IBAction)updateLightingModel:(id)sender { 121 | NSString *updatedModel = [sender titleOfSelectedItem]; 122 | 123 | if(![self.currentLightingModel isEqualToString:updatedModel]){ 124 | CWHLightingProgram *program = (CWHLightingProgram *)[self programForLightingModel:updatedModel]; 125 | NSAssert([program isKindOfClass:[CWHLightingProgram class]], 126 | @"Program for lighting model is expected to be an instance of a subclass of CWHLightingProgram"); 127 | NSDictionary *properties = program.shadableProperties; 128 | [self updateProgram:program shadableProperties:properties]; 129 | self.currentLightingModel = updatedModel; 130 | } 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHGlossyWetHighlightProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHGlossyWetHighlightProgram.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/31/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHGlossyWetHighlightProgram.h" 10 | 11 | @implementation CWHGlossyWetHighlightProgram 12 | 13 | +(BOOL) supportsSecureCoding { 14 | return YES; 15 | } 16 | 17 | -(instancetype)init 18 | { 19 | id device = MTLCreateSystemDefaultDevice(); 20 | id library = [device newDefaultLibrary]; 21 | 22 | self = [super initWithLibrary:library vertexFunctionName:@"GlossyWetHighlightVertex" fragmentFunctionName:@"GlossyWetHighlightFragment"]; 23 | 24 | if (self != nil) 25 | { 26 | self.delegate = self; 27 | 28 | [self bindBuffers]; 29 | 30 | self.ambientColor = [NSColor colorWithRed:0. green:0. blue:0. alpha:1.]; 31 | self.diffuseColor = [NSColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.]; 32 | self.specularColor = [NSColor colorWithRed:1. green:0. blue:0. alpha:1.]; 33 | self.specularity = 0.3; 34 | self.specularExponent = 3.0; 35 | self.glossMax = 1.349; 36 | self.glossMin = 1.199; 37 | self.glossDrop = 2.661; 38 | } 39 | 40 | return self; 41 | } 42 | 43 | - (id)initWithCoder:(NSCoder *)decoder { 44 | id device = MTLCreateSystemDefaultDevice(); 45 | id library = [device newDefaultLibrary]; 46 | 47 | self = [super initWithLibrary:library vertexFunctionName:@"GlossyWetHighlightVertex" fragmentFunctionName:@"GlossyWetHighlightFragment"]; 48 | 49 | if (self != nil) 50 | { 51 | self.delegate = self; 52 | 53 | [self bindBuffers]; 54 | 55 | self.ambientColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"ambientColor"]; 56 | self.diffuseColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"diffuseColor"]; 57 | self.specularColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"specularColor"]; 58 | self.specularity = [decoder decodeDoubleForKey:@"specularity"]; 59 | self.specularExponent= [decoder decodeDoubleForKey:@"specularExponent"]; 60 | self.glossMax= [decoder decodeDoubleForKey:@"glossMax"]; 61 | self.glossMin= [decoder decodeDoubleForKey:@"glossMin"]; 62 | self.glossDrop = [decoder decodeDoubleForKey:@"glossDrop"]; 63 | 64 | } 65 | return self; 66 | } 67 | 68 | - (void)encodeWithCoder:(NSCoder *)encoder { 69 | [encoder encodeObject:_ambientColor forKey:@"ambientColor"]; 70 | [encoder encodeObject:_diffuseColor forKey:@"diffuseColor"]; 71 | [encoder encodeObject:_specularColor forKey:@"specularColor"]; 72 | [encoder encodeDouble:_specularity forKey:@"specularity"]; 73 | [encoder encodeDouble:_specularExponent forKey:@"specularExponent"]; 74 | [encoder encodeDouble:_glossMax forKey:@"glossMax"]; 75 | [encoder encodeDouble:_glossMin forKey:@"glossMin"]; 76 | [encoder encodeDouble:_glossDrop forKey:@"glossDrop"]; 77 | } 78 | 79 | - (void)bindBuffers { 80 | SCNBufferBindingBlock lightBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 81 | { 82 | struct LightConstants { 83 | float position[3]; 84 | float ambientIntensity[3]; 85 | float diffuseIntensity[3]; 86 | float specularIntensity[3]; 87 | } lights; 88 | 89 | lights.position[0] = self.lightPosition.x; 90 | lights.position[1] = self.lightPosition.y; 91 | lights.position[2] = self.lightPosition.z; 92 | 93 | if (self.ambientColor) { 94 | lights.ambientIntensity[0] = [self.ambientColor redComponent]; 95 | lights.ambientIntensity[1] = [self.ambientColor greenComponent]; 96 | lights.ambientIntensity[2] = [self.ambientColor blueComponent]; 97 | } 98 | 99 | if (self.diffuseColor) { 100 | lights.diffuseIntensity[0] = [self.diffuseColor redComponent]; 101 | lights.diffuseIntensity[1] = [self.diffuseColor greenComponent]; 102 | lights.diffuseIntensity[2] = [self.diffuseColor blueComponent]; 103 | } 104 | 105 | if (self.specularColor) { 106 | lights.specularIntensity[0] = [self.specularColor redComponent]; 107 | lights.specularIntensity[1] = [self.specularColor greenComponent]; 108 | lights.specularIntensity[2] = [self.specularColor blueComponent]; 109 | } 110 | 111 | [buffer writeBytes:&lights length:sizeof(lights)]; 112 | }; 113 | 114 | SCNBufferBindingBlock materialBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 115 | { 116 | struct MaterialConstants { 117 | float specularExponent; 118 | float specularity; 119 | float glossMin; 120 | float glossMax; 121 | float glossDrop; 122 | } material; 123 | 124 | material.specularExponent = self.specularExponent; 125 | material.specularity = self.specularity; 126 | material.glossMin = self.glossMin; 127 | material.glossMax = self.glossMax; 128 | material.glossDrop = self.glossDrop; 129 | 130 | [buffer writeBytes:&material length:sizeof(material)]; 131 | }; 132 | 133 | [self handleBindingOfBufferNamed:@"vertexLights" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 134 | [self handleBindingOfBufferNamed:@"fragmentLights" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 135 | [self handleBindingOfBufferNamed:@"material" frequency:SCNBufferFrequencyPerFrame usingBlock:materialBlock]; 136 | } 137 | 138 | #pragma mark - SCNProgramDelegate Protocol Methods 139 | 140 | - (void)program:(SCNProgram*)program handleError:(NSError*)error { 141 | // Log the shader compilation error 142 | NSLog(@"SceneKit compilation error: %@", error); 143 | } 144 | 145 | @end 146 | -------------------------------------------------------------------------------- /ScenekitStarter/CWHEdgeFuzzProgram.m: -------------------------------------------------------------------------------- 1 | // 2 | // CWHEdgeFuzzProgram.m 3 | // ScenekitStarter 4 | // 5 | // Created by Dale Bradshaw on 7/31/14. 6 | // Copyright (c) 2014 Creative Workflow Hacks. All rights reserved. 7 | // 8 | 9 | #import "CWHEdgeFuzzProgram.h" 10 | 11 | @implementation CWHEdgeFuzzProgram 12 | 13 | +(BOOL) supportsSecureCoding { 14 | return YES; 15 | } 16 | 17 | -(instancetype)init 18 | { 19 | id device = MTLCreateSystemDefaultDevice(); 20 | id library = [device newDefaultLibrary]; 21 | 22 | self = [super initWithLibrary:library vertexFunctionName:@"EdgeFuzzVertex" fragmentFunctionName:@"EdgeFuzzFragment"]; 23 | 24 | if ( self != nil ) 25 | { 26 | self.delegate = self; 27 | 28 | [self bindBuffers]; 29 | 30 | NSColor *surfaceColor = [NSColor colorWithRed:0.8 green:0.4 blue:0.2 alpha:1.]; 31 | self.surfaceColor = surfaceColor; 32 | NSColor *edgeColor = [NSColor colorWithRed:0.4 green:0.8 blue:1. alpha:1.]; 33 | self.edgeColor = edgeColor; 34 | NSColor *lightColor = [NSColor colorWithRed:1. green:1. blue:1. alpha:1.]; 35 | self.lightColor = lightColor; 36 | NSColor *ambientColor = [NSColor colorWithRed:0. green:0. blue:0. alpha:1.]; 37 | self.ambientColor = ambientColor; 38 | 39 | self.fuzziness = 0.166; 40 | self.edgeFade = 3.868; 41 | self.specularity = 0.1488; 42 | } 43 | 44 | return self; 45 | } 46 | 47 | - (id)initWithCoder:(NSCoder *)decoder { 48 | 49 | id device = MTLCreateSystemDefaultDevice(); 50 | id library = [device newDefaultLibrary]; 51 | 52 | self = [super initWithLibrary:library vertexFunctionName:@"EdgeFuzzVertex" fragmentFunctionName:@"EdgeFuzzFragment"]; 53 | 54 | if (self) { 55 | self.surfaceColor =[decoder decodeObjectOfClass:[NSColor class] forKey:@"surfaceColor"]; 56 | self.edgeColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"edgeColor"]; 57 | self.lightColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"lightColor"]; 58 | self.ambientColor = [decoder decodeObjectOfClass:[NSColor class] forKey:@"ambientColor"]; 59 | self.fuzziness = [decoder decodeDoubleForKey:@"fuzziness"]; 60 | self.edgeFade = [decoder decodeDoubleForKey:@"edgeFade"]; 61 | self.specularity = [decoder decodeDoubleForKey:@"specularity"]; 62 | 63 | self.delegate = self; 64 | 65 | [self bindBuffers]; 66 | } 67 | 68 | return self; 69 | } 70 | 71 | - (void)encodeWithCoder:(NSCoder *)encoder { 72 | [encoder encodeObject:_surfaceColor forKey:@"surfaceColor"]; 73 | [encoder encodeObject:_edgeColor forKey:@"edgeColor"]; 74 | [encoder encodeObject:_lightColor forKey:@"lightColor"]; 75 | [encoder encodeObject:_ambientColor forKey:@"ambientColor"]; 76 | [encoder encodeDouble:_fuzziness forKey:@"fuzziness"]; 77 | [encoder encodeDouble:_edgeFade forKey:@"edgeFade"]; 78 | [encoder encodeDouble:_specularity forKey:@"specularity"]; 79 | } 80 | 81 | - (void)bindBuffers { 82 | SCNBufferBindingBlock lightBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 83 | { 84 | struct LightConstants { 85 | float position[3]; 86 | float ambientIntensity[3]; 87 | float diffuseIntensity[3]; 88 | } lights; 89 | 90 | lights.position[0] = self.lightPosition.x; 91 | lights.position[1] = self.lightPosition.y; 92 | lights.position[2] = self.lightPosition.z; 93 | 94 | if (self.lightColor) { 95 | lights.diffuseIntensity[0] = [self.lightColor redComponent]; 96 | lights.diffuseIntensity[1] = [self.lightColor greenComponent]; 97 | lights.diffuseIntensity[2] = [self.lightColor blueComponent]; 98 | } 99 | 100 | if (self.ambientColor) { 101 | lights.ambientIntensity[0] = [self.ambientColor redComponent]; 102 | lights.ambientIntensity[1] = [self.ambientColor greenComponent]; 103 | lights.ambientIntensity[2] = [self.ambientColor blueComponent]; 104 | } 105 | 106 | [buffer writeBytes:&lights length:sizeof(lights)]; 107 | }; 108 | 109 | SCNBufferBindingBlock materialBlock = ^(id buffer, SCNNode *node, id shadable, SCNRenderer *renderer) 110 | { 111 | struct MaterialConstants { 112 | float edgeColor[4]; 113 | float surfaceColor[4]; 114 | float specularity; 115 | float fuzziness; 116 | float edgeFade; 117 | } material; 118 | 119 | if (self.edgeColor) { 120 | material.edgeColor[0] = [self.edgeColor redComponent]; 121 | material.edgeColor[1] = [self.edgeColor greenComponent]; 122 | material.edgeColor[2] = [self.edgeColor blueComponent]; 123 | material.edgeColor[3] = [self.edgeColor alphaComponent]; 124 | } 125 | 126 | if (self.surfaceColor) { 127 | material.surfaceColor[0] = [self.surfaceColor redComponent]; 128 | material.surfaceColor[1] = [self.surfaceColor greenComponent]; 129 | material.surfaceColor[2] = [self.surfaceColor blueComponent]; 130 | material.surfaceColor[3] = [self.surfaceColor alphaComponent]; 131 | } 132 | 133 | material.specularity = self.specularity; 134 | material.fuzziness = self.fuzziness; 135 | material.edgeFade = self.edgeFade; 136 | 137 | [buffer writeBytes:&material length:sizeof(material)]; 138 | }; 139 | 140 | [self handleBindingOfBufferNamed:@"vertexLights" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 141 | [self handleBindingOfBufferNamed:@"fragmentLights" frequency:SCNBufferFrequencyPerFrame usingBlock:lightBlock]; 142 | [self handleBindingOfBufferNamed:@"material" frequency:SCNBufferFrequencyPerShadable usingBlock:materialBlock]; 143 | } 144 | 145 | #pragma mark - SCNProgramDelegate Protocol Methods 146 | 147 | - (void)program:(SCNProgram*)program handleError:(NSError*)error { 148 | // Log the shader compilation error 149 | NSLog(@"SceneKit compilation error: %@", error); 150 | } 151 | 152 | @end 153 | -------------------------------------------------------------------------------- /ScenekitStarter/LambSkinParameterView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /ScenekitStarter/LightingModelWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /ScenekitStarter/VelvetParameterView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | --------------------------------------------------------------------------------