├── .DS_Store ├── Iridescent Tiles Shader.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── adamfuhrer.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── adamfuhrer.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── Iridescent Tiles Shader ├── Iridescent_Tiles_ShaderView.h └── Iridescent_Tiles_ShaderView.m ├── README.md ├── screensaver.mov └── screensaver.swift /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamfuhrer/shader-screensaver/ee6523d2171080c18fc02b81d766ad15d0ad107d/.DS_Store -------------------------------------------------------------------------------- /Iridescent Tiles Shader.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 71D097EF2BF96EE300AB8E6A /* screensaver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D097EE2BF96EE300AB8E6A /* screensaver.swift */; }; 11 | 71D097F12BF96F0E00AB8E6A /* screensaver.mov in Resources */ = {isa = PBXBuildFile; fileRef = 71D097F02BF96F0E00AB8E6A /* screensaver.mov */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXFileReference section */ 15 | 71D097E22BF96ED000AB8E6A /* Iridescent Tiles Shader.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Iridescent Tiles Shader.saver"; sourceTree = BUILT_PRODUCTS_DIR; }; 16 | 71D097EE2BF96EE300AB8E6A /* screensaver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = screensaver.swift; sourceTree = ""; }; 17 | 71D097F02BF96F0E00AB8E6A /* screensaver.mov */ = {isa = PBXFileReference; lastKnownFileType = video.quicktime; path = screensaver.mov; sourceTree = ""; }; 18 | /* End PBXFileReference section */ 19 | 20 | /* Begin PBXFrameworksBuildPhase section */ 21 | 71D097DF2BF96ED000AB8E6A /* Frameworks */ = { 22 | isa = PBXFrameworksBuildPhase; 23 | buildActionMask = 2147483647; 24 | files = ( 25 | ); 26 | runOnlyForDeploymentPostprocessing = 0; 27 | }; 28 | /* End PBXFrameworksBuildPhase section */ 29 | 30 | /* Begin PBXGroup section */ 31 | 71D097D82BF96ED000AB8E6A = { 32 | isa = PBXGroup; 33 | children = ( 34 | 71D097F02BF96F0E00AB8E6A /* screensaver.mov */, 35 | 71D097EE2BF96EE300AB8E6A /* screensaver.swift */, 36 | 71D097E32BF96ED000AB8E6A /* Products */, 37 | ); 38 | sourceTree = ""; 39 | }; 40 | 71D097E32BF96ED000AB8E6A /* Products */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | 71D097E22BF96ED000AB8E6A /* Iridescent Tiles Shader.saver */, 44 | ); 45 | name = Products; 46 | sourceTree = ""; 47 | }; 48 | /* End PBXGroup section */ 49 | 50 | /* Begin PBXHeadersBuildPhase section */ 51 | 71D097DD2BF96ED000AB8E6A /* Headers */ = { 52 | isa = PBXHeadersBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXHeadersBuildPhase section */ 59 | 60 | /* Begin PBXNativeTarget section */ 61 | 71D097E12BF96ED000AB8E6A /* Iridescent Tiles Shader */ = { 62 | isa = PBXNativeTarget; 63 | buildConfigurationList = 71D097EB2BF96ED000AB8E6A /* Build configuration list for PBXNativeTarget "Iridescent Tiles Shader" */; 64 | buildPhases = ( 65 | 71D097DD2BF96ED000AB8E6A /* Headers */, 66 | 71D097DE2BF96ED000AB8E6A /* Sources */, 67 | 71D097DF2BF96ED000AB8E6A /* Frameworks */, 68 | 71D097E02BF96ED000AB8E6A /* Resources */, 69 | ); 70 | buildRules = ( 71 | ); 72 | dependencies = ( 73 | ); 74 | name = "Iridescent Tiles Shader"; 75 | productName = "Iridescent Tiles Shader"; 76 | productReference = 71D097E22BF96ED000AB8E6A /* Iridescent Tiles Shader.saver */; 77 | productType = "com.apple.product-type.bundle"; 78 | }; 79 | /* End PBXNativeTarget section */ 80 | 81 | /* Begin PBXProject section */ 82 | 71D097D92BF96ED000AB8E6A /* Project object */ = { 83 | isa = PBXProject; 84 | attributes = { 85 | BuildIndependentTargetsInParallel = 1; 86 | LastUpgradeCheck = 1540; 87 | TargetAttributes = { 88 | 71D097E12BF96ED000AB8E6A = { 89 | CreatedOnToolsVersion = 15.4; 90 | LastSwiftMigration = 1540; 91 | }; 92 | }; 93 | }; 94 | buildConfigurationList = 71D097DC2BF96ED000AB8E6A /* Build configuration list for PBXProject "Iridescent Tiles Shader" */; 95 | compatibilityVersion = "Xcode 14.0"; 96 | developmentRegion = en; 97 | hasScannedForEncodings = 0; 98 | knownRegions = ( 99 | en, 100 | Base, 101 | ); 102 | mainGroup = 71D097D82BF96ED000AB8E6A; 103 | productRefGroup = 71D097E32BF96ED000AB8E6A /* Products */; 104 | projectDirPath = ""; 105 | projectRoot = ""; 106 | targets = ( 107 | 71D097E12BF96ED000AB8E6A /* Iridescent Tiles Shader */, 108 | ); 109 | }; 110 | /* End PBXProject section */ 111 | 112 | /* Begin PBXResourcesBuildPhase section */ 113 | 71D097E02BF96ED000AB8E6A /* Resources */ = { 114 | isa = PBXResourcesBuildPhase; 115 | buildActionMask = 2147483647; 116 | files = ( 117 | 71D097F12BF96F0E00AB8E6A /* screensaver.mov in Resources */, 118 | ); 119 | runOnlyForDeploymentPostprocessing = 0; 120 | }; 121 | /* End PBXResourcesBuildPhase section */ 122 | 123 | /* Begin PBXSourcesBuildPhase section */ 124 | 71D097DE2BF96ED000AB8E6A /* Sources */ = { 125 | isa = PBXSourcesBuildPhase; 126 | buildActionMask = 2147483647; 127 | files = ( 128 | 71D097EF2BF96EE300AB8E6A /* screensaver.swift in Sources */, 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | /* End PBXSourcesBuildPhase section */ 133 | 134 | /* Begin XCBuildConfiguration section */ 135 | 71D097E92BF96ED000AB8E6A /* Debug */ = { 136 | isa = XCBuildConfiguration; 137 | buildSettings = { 138 | ALWAYS_SEARCH_USER_PATHS = NO; 139 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 140 | CLANG_ANALYZER_NONNULL = YES; 141 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 142 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 143 | CLANG_ENABLE_MODULES = YES; 144 | CLANG_ENABLE_OBJC_ARC = YES; 145 | CLANG_ENABLE_OBJC_WEAK = YES; 146 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 147 | CLANG_WARN_BOOL_CONVERSION = YES; 148 | CLANG_WARN_COMMA = YES; 149 | CLANG_WARN_CONSTANT_CONVERSION = YES; 150 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 151 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 152 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 153 | CLANG_WARN_EMPTY_BODY = YES; 154 | CLANG_WARN_ENUM_CONVERSION = YES; 155 | CLANG_WARN_INFINITE_RECURSION = YES; 156 | CLANG_WARN_INT_CONVERSION = YES; 157 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 158 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 159 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 160 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 161 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 162 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 163 | CLANG_WARN_STRICT_PROTOTYPES = YES; 164 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 165 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 166 | CLANG_WARN_UNREACHABLE_CODE = YES; 167 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 168 | COPY_PHASE_STRIP = NO; 169 | DEBUG_INFORMATION_FORMAT = dwarf; 170 | ENABLE_STRICT_OBJC_MSGSEND = YES; 171 | ENABLE_TESTABILITY = YES; 172 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 173 | GCC_C_LANGUAGE_STANDARD = gnu17; 174 | GCC_DYNAMIC_NO_PIC = NO; 175 | GCC_NO_COMMON_BLOCKS = YES; 176 | GCC_OPTIMIZATION_LEVEL = 0; 177 | GCC_PREPROCESSOR_DEFINITIONS = ( 178 | "DEBUG=1", 179 | "$(inherited)", 180 | ); 181 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 182 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 183 | GCC_WARN_UNDECLARED_SELECTOR = YES; 184 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 185 | GCC_WARN_UNUSED_FUNCTION = YES; 186 | GCC_WARN_UNUSED_VARIABLE = YES; 187 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 188 | MACOSX_DEPLOYMENT_TARGET = 14.4; 189 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 190 | MTL_FAST_MATH = YES; 191 | ONLY_ACTIVE_ARCH = YES; 192 | SDKROOT = macosx; 193 | }; 194 | name = Debug; 195 | }; 196 | 71D097EA2BF96ED000AB8E6A /* Release */ = { 197 | isa = XCBuildConfiguration; 198 | buildSettings = { 199 | ALWAYS_SEARCH_USER_PATHS = NO; 200 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 201 | CLANG_ANALYZER_NONNULL = YES; 202 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 203 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 204 | CLANG_ENABLE_MODULES = YES; 205 | CLANG_ENABLE_OBJC_ARC = YES; 206 | CLANG_ENABLE_OBJC_WEAK = YES; 207 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 208 | CLANG_WARN_BOOL_CONVERSION = YES; 209 | CLANG_WARN_COMMA = YES; 210 | CLANG_WARN_CONSTANT_CONVERSION = YES; 211 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 212 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 213 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 214 | CLANG_WARN_EMPTY_BODY = YES; 215 | CLANG_WARN_ENUM_CONVERSION = YES; 216 | CLANG_WARN_INFINITE_RECURSION = YES; 217 | CLANG_WARN_INT_CONVERSION = YES; 218 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 219 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 220 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 221 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 222 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 223 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 224 | CLANG_WARN_STRICT_PROTOTYPES = YES; 225 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 226 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 227 | CLANG_WARN_UNREACHABLE_CODE = YES; 228 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 229 | COPY_PHASE_STRIP = NO; 230 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 231 | ENABLE_NS_ASSERTIONS = NO; 232 | ENABLE_STRICT_OBJC_MSGSEND = YES; 233 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 234 | GCC_C_LANGUAGE_STANDARD = gnu17; 235 | GCC_NO_COMMON_BLOCKS = YES; 236 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 237 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 238 | GCC_WARN_UNDECLARED_SELECTOR = YES; 239 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 240 | GCC_WARN_UNUSED_FUNCTION = YES; 241 | GCC_WARN_UNUSED_VARIABLE = YES; 242 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 243 | MACOSX_DEPLOYMENT_TARGET = 14.4; 244 | MTL_ENABLE_DEBUG_INFO = NO; 245 | MTL_FAST_MATH = YES; 246 | SDKROOT = macosx; 247 | }; 248 | name = Release; 249 | }; 250 | 71D097EC2BF96ED000AB8E6A /* Debug */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | CLANG_ENABLE_MODULES = YES; 254 | CODE_SIGN_STYLE = Automatic; 255 | COMBINE_HIDPI_IMAGES = YES; 256 | CURRENT_PROJECT_VERSION = 1; 257 | GENERATE_INFOPLIST_FILE = YES; 258 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 259 | INFOPLIST_KEY_NSPrincipalClass = Iridescent_Tiles_ShaderView; 260 | INSTALL_PATH = "$(HOME)/Library/Screen Savers"; 261 | MARKETING_VERSION = 1.0; 262 | PRODUCT_BUNDLE_IDENTIFIER = "adamfuhrer.Iridescent-Tiles-Shader"; 263 | PRODUCT_NAME = "$(TARGET_NAME)"; 264 | SWIFT_EMIT_LOC_STRINGS = YES; 265 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 266 | SWIFT_VERSION = 5.0; 267 | WRAPPER_EXTENSION = saver; 268 | }; 269 | name = Debug; 270 | }; 271 | 71D097ED2BF96ED000AB8E6A /* Release */ = { 272 | isa = XCBuildConfiguration; 273 | buildSettings = { 274 | CLANG_ENABLE_MODULES = YES; 275 | CODE_SIGN_STYLE = Automatic; 276 | COMBINE_HIDPI_IMAGES = YES; 277 | CURRENT_PROJECT_VERSION = 1; 278 | GENERATE_INFOPLIST_FILE = YES; 279 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 280 | INFOPLIST_KEY_NSPrincipalClass = Iridescent_Tiles_ShaderView; 281 | INSTALL_PATH = "$(HOME)/Library/Screen Savers"; 282 | MARKETING_VERSION = 1.0; 283 | PRODUCT_BUNDLE_IDENTIFIER = "adamfuhrer.Iridescent-Tiles-Shader"; 284 | PRODUCT_NAME = "$(TARGET_NAME)"; 285 | SWIFT_EMIT_LOC_STRINGS = YES; 286 | SWIFT_VERSION = 5.0; 287 | WRAPPER_EXTENSION = saver; 288 | }; 289 | name = Release; 290 | }; 291 | /* End XCBuildConfiguration section */ 292 | 293 | /* Begin XCConfigurationList section */ 294 | 71D097DC2BF96ED000AB8E6A /* Build configuration list for PBXProject "Iridescent Tiles Shader" */ = { 295 | isa = XCConfigurationList; 296 | buildConfigurations = ( 297 | 71D097E92BF96ED000AB8E6A /* Debug */, 298 | 71D097EA2BF96ED000AB8E6A /* Release */, 299 | ); 300 | defaultConfigurationIsVisible = 0; 301 | defaultConfigurationName = Release; 302 | }; 303 | 71D097EB2BF96ED000AB8E6A /* Build configuration list for PBXNativeTarget "Iridescent Tiles Shader" */ = { 304 | isa = XCConfigurationList; 305 | buildConfigurations = ( 306 | 71D097EC2BF96ED000AB8E6A /* Debug */, 307 | 71D097ED2BF96ED000AB8E6A /* Release */, 308 | ); 309 | defaultConfigurationIsVisible = 0; 310 | defaultConfigurationName = Release; 311 | }; 312 | /* End XCConfigurationList section */ 313 | }; 314 | rootObject = 71D097D92BF96ED000AB8E6A /* Project object */; 315 | } 316 | -------------------------------------------------------------------------------- /Iridescent Tiles Shader.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Iridescent Tiles Shader.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Iridescent Tiles Shader.xcodeproj/project.xcworkspace/xcuserdata/adamfuhrer.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamfuhrer/shader-screensaver/ee6523d2171080c18fc02b81d766ad15d0ad107d/Iridescent Tiles Shader.xcodeproj/project.xcworkspace/xcuserdata/adamfuhrer.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Iridescent Tiles Shader.xcodeproj/xcuserdata/adamfuhrer.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Iridescent Tiles Shader.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Iridescent Tiles Shader/Iridescent_Tiles_ShaderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // Iridescent_Tiles_ShaderView.h 3 | // Iridescent Tiles Shader 4 | // 5 | // Created by Adam Fuhrer on 2024-05-18. 6 | // 7 | 8 | #import 9 | 10 | @interface Iridescent_Tiles_ShaderView : ScreenSaverView 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Iridescent Tiles Shader/Iridescent_Tiles_ShaderView.m: -------------------------------------------------------------------------------- 1 | // 2 | // Iridescent_Tiles_ShaderView.m 3 | // Iridescent Tiles Shader 4 | // 5 | // Created by Adam Fuhrer on 2024-05-18. 6 | // 7 | 8 | #import "Iridescent_Tiles_ShaderView.h" 9 | 10 | @implementation Iridescent_Tiles_ShaderView 11 | 12 | - (instancetype)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview 13 | { 14 | self = [super initWithFrame:frame isPreview:isPreview]; 15 | if (self) { 16 | [self setAnimationTimeInterval:1/30.0]; 17 | } 18 | return self; 19 | } 20 | 21 | - (void)startAnimation 22 | { 23 | [super startAnimation]; 24 | } 25 | 26 | - (void)stopAnimation 27 | { 28 | [super stopAnimation]; 29 | } 30 | 31 | - (void)drawRect:(NSRect)rect 32 | { 33 | [super drawRect:rect]; 34 | } 35 | 36 | - (void)animateOneFrame 37 | { 38 | return; 39 | } 40 | 41 | - (BOOL)hasConfigureSheet 42 | { 43 | return NO; 44 | } 45 | 46 | - (NSWindow*)configureSheet 47 | { 48 | return nil; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | https://github.com/adamfuhrer/shader-screensaver/assets/10779827/0a51d2be-7b9d-4ca8-93e7-a7a74d0eb9e6 2 | 3 | 4 | GLSL Shader: https://shaders-adamfuhrer.vercel.app/iridescent-windows 5 | 6 | Screensaver: https://adamfuhrer.com/Iridescent-Tiles-Shader.zip 7 | 8 | ___ 9 | 10 | Website: https://adamfuhrer.com/ 11 | 12 | Twitter: https://x.com/adamfuhrer 13 | -------------------------------------------------------------------------------- /screensaver.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamfuhrer/shader-screensaver/ee6523d2171080c18fc02b81d766ad15d0ad107d/screensaver.mov -------------------------------------------------------------------------------- /screensaver.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import ScreenSaver 3 | import AVKit 4 | 5 | class GLSLView: ScreenSaverView { 6 | private var player: AVPlayer! 7 | private var playerLayer: AVPlayerLayer! 8 | 9 | override init?(frame: NSRect, isPreview: Bool) { 10 | super.init(frame: frame, isPreview: isPreview) 11 | animationTimeInterval = 1.0/30.0 12 | wantsLayer = true 13 | player = createAVPlayer() 14 | playerLayer = createAVPlayerLayer(player: player) 15 | self.layer = playerLayer 16 | } 17 | 18 | required init?(coder: NSCoder) { 19 | fatalError("init(coder:) has not been implemented") 20 | } 21 | 22 | override func startAnimation() { 23 | super.startAnimation() 24 | player.play() 25 | } 26 | 27 | override func stopAnimation() { 28 | super.stopAnimation() 29 | player.pause() 30 | } 31 | 32 | func createAVPlayer() -> AVPlayer { 33 | let glslBundle: Bundle = Bundle(for: GLSLView.self) 34 | guard let url = glslBundle.url(forResource: "screensaver", withExtension: "mov") else { 35 | fatalError("moon.mov not found in \(glslBundle.bundlePath)") 36 | } 37 | let avPlayer = AVPlayer(url: url) 38 | NotificationCenter.default.addObserver(self, 39 | selector: #selector(playerItemDidReachEnd), 40 | name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, 41 | object: nil) 42 | return avPlayer 43 | } 44 | 45 | func createAVPlayerLayer(player: AVPlayer) -> AVPlayerLayer { 46 | let avPlayerLayer: AVPlayerLayer = AVPlayerLayer(player: player) 47 | avPlayerLayer.frame = bounds 48 | avPlayerLayer.autoresizingMask = [.layerWidthSizable, .layerHeightSizable] 49 | avPlayerLayer.needsDisplayOnBoundsChange = true 50 | avPlayerLayer.contentsGravity = .resizeAspect 51 | avPlayerLayer.videoGravity = .resizeAspectFill 52 | avPlayerLayer.backgroundColor = CGColor(red: 0.00, green: 0.01, blue: 0.00, alpha:1.0) 53 | return avPlayerLayer 54 | } 55 | 56 | // Notification Handling 57 | @objc func playerItemDidReachEnd(notification: NSNotification) { 58 | player.seek(to: CMTime.zero) 59 | player.play() 60 | } 61 | 62 | // Remove Observer 63 | deinit { 64 | NotificationCenter.default.removeObserver(self) 65 | } 66 | } 67 | --------------------------------------------------------------------------------