├── English.lproj ├── InfoPlist.strings ├── MainMenu.nib │ ├── classes.nib │ ├── info.nib │ └── keyedobjects.nib └── ScreenSaver.nib │ ├── classes.nib │ ├── info.nib │ └── keyedobjects.nib ├── GPULife saver-Info.plist ├── GPULife.xcodeproj └── project.pbxproj ├── GPULifeSaverView.h ├── GPULifeSaverView.m ├── GPULifeView.h ├── GPULifeView.m ├── GPULife_Prefix.pch ├── Info.plist ├── LICENSE ├── LifeShader ├── main.m └── website ├── index.html ├── life.png └── settings.png /English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeash/GPULife/6c1c3908bc9ffba4131ec42622918dae86be8c93/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /English.lproj/MainMenu.nib/classes.nib: -------------------------------------------------------------------------------- 1 | { 2 | IBClasses = ( 3 | {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 4 | {CLASS = GPULifeView; LANGUAGE = ObjC; SUPERCLASS = NSOpenGLView; } 5 | ); 6 | IBVersion = 1; 7 | } -------------------------------------------------------------------------------- /English.lproj/MainMenu.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBDocumentLocation 6 | 94 80 356 240 0 0 1280 832 7 | IBEditorPositions 8 | 9 | 29 10 | 93 282 338 44 0 0 1280 832 11 | 12 | IBFramework Version 13 | 437.0 14 | IBOpenObjects 15 | 16 | 21 17 | 29 18 | 19 | IBSystem Version 20 | 8A428 21 | 22 | 23 | -------------------------------------------------------------------------------- /English.lproj/MainMenu.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeash/GPULife/6c1c3908bc9ffba4131ec42622918dae86be8c93/English.lproj/MainMenu.nib/keyedobjects.nib -------------------------------------------------------------------------------- /English.lproj/ScreenSaver.nib/classes.nib: -------------------------------------------------------------------------------- 1 | { 2 | IBClasses = ( 3 | {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 4 | { 5 | ACTIONS = { 6 | cancel = id; 7 | limitFPSChecked = id; 8 | limitFPSField = id; 9 | limitFPSSlider = id; 10 | ok = id; 11 | }; 12 | CLASS = GPULifeSaverView; 13 | LANGUAGE = ObjC; 14 | OUTLETS = { 15 | colorWellBox = NSBox; 16 | configureSheet = NSWindow; 17 | displayFPSCheckbox = NSButton; 18 | fpsField = NSTextField; 19 | fpsSlider = NSSlider; 20 | generationField = NSTextField; 21 | initialFillSlider = NSSlider; 22 | limitFPSCheckbox = NSButton; 23 | zoomField = NSTextField; 24 | zoomSlider = NSSlider; 25 | }; 26 | SUPERCLASS = ScreenSaverView; 27 | }, 28 | {CLASS = ScreenSaverView; LANGUAGE = ObjC; SUPERCLASS = NSView; } 29 | ); 30 | IBVersion = 1; 31 | } -------------------------------------------------------------------------------- /English.lproj/ScreenSaver.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBDocumentLocation 6 | 69 53 356 240 0 0 1280 832 7 | IBFramework Version 8 | 437.0 9 | IBGroupedObjects 10 | 11 | 0 12 | 13 | 10 14 | 11 15 | 13 16 | 12 17 | 18 | 19 | IBLastGroupID 20 | 1 21 | IBOpenObjects 22 | 23 | 5 24 | 25 | IBSystem Version 26 | 8A428 27 | 28 | 29 | -------------------------------------------------------------------------------- /English.lproj/ScreenSaver.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeash/GPULife/6c1c3908bc9ffba4131ec42622918dae86be8c93/English.lproj/ScreenSaver.nib/keyedobjects.nib -------------------------------------------------------------------------------- /GPULife saver-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | GPULife 9 | CFBundleName 10 | GPULife 11 | CFBundleIdentifier 12 | com.mikeash.GPULife.saver 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0.1 21 | CSResourcesFileMapped 22 | yes 23 | NSPrincipalClass 24 | GPULifeSaverView 25 | 26 | 27 | -------------------------------------------------------------------------------- /GPULife.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; }; 11 | 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 12 | 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 13 | 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; 14 | C26797C60B0B938F00FD6A40 /* GPULife.saver in CopyFiles */ = {isa = PBXBuildFile; fileRef = C2CC7A7008350BBD00EB6054 /* GPULife.saver */; }; 15 | C2CC78710833A2A300EB6054 /* LifeShader in Resources */ = {isa = PBXBuildFile; fileRef = C2CC78700833A2A300EB6054 /* LifeShader */; }; 16 | C2CC78790833A2DC00EB6054 /* GPULifeView.m in Sources */ = {isa = PBXBuildFile; fileRef = C2CC78780833A2DC00EB6054 /* GPULifeView.m */; }; 17 | C2CC795C0833B01800EB6054 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2CC795B0833B01800EB6054 /* OpenGL.framework */; }; 18 | C2CC7A7908350BE700EB6054 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2CC7A7808350BE700EB6054 /* ScreenSaver.framework */; }; 19 | C2CC7A9808350C5A00EB6054 /* GPULifeSaverView.m in Sources */ = {isa = PBXBuildFile; fileRef = C2CC7A9708350C5A00EB6054 /* GPULifeSaverView.m */; }; 20 | C2CC7A9908350C6300EB6054 /* GPULifeView.m in Sources */ = {isa = PBXBuildFile; fileRef = C2CC78780833A2DC00EB6054 /* GPULifeView.m */; }; 21 | C2CC7ACE08350E2900EB6054 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2CC795B0833B01800EB6054 /* OpenGL.framework */; }; 22 | C2CC7ACF08350E2900EB6054 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; 23 | C2CC7ADD08350E6E00EB6054 /* LifeShader in Resources */ = {isa = PBXBuildFile; fileRef = C2CC78700833A2A300EB6054 /* LifeShader */; }; 24 | C2CC7B300835127B00EB6054 /* ScreenSaver.nib in Resources */ = {isa = PBXBuildFile; fileRef = C2CC7B2E0835127B00EB6054 /* ScreenSaver.nib */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXCopyFilesBuildPhase section */ 28 | C26797C20B0B937E00FD6A40 /* CopyFiles */ = { 29 | isa = PBXCopyFilesBuildPhase; 30 | buildActionMask = 2147483647; 31 | dstPath = "$(HOME)/Library/Screen Savers"; 32 | dstSubfolderSpec = 0; 33 | files = ( 34 | C26797C60B0B938F00FD6A40 /* GPULife.saver in CopyFiles */, 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXCopyFilesBuildPhase section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 42 | 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 43 | 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; }; 44 | 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 45 | 29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = ""; }; 46 | 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 47 | 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 48 | 32CA4F630368D1EE00C91783 /* GPULife_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPULife_Prefix.pch; sourceTree = ""; }; 49 | 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 50 | 8D1107320486CEB800E47090 /* GPULife.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GPULife.app; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | C2CC78700833A2A300EB6054 /* LifeShader */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LifeShader; sourceTree = ""; }; 52 | C2CC78770833A2DC00EB6054 /* GPULifeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPULifeView.h; sourceTree = ""; }; 53 | C2CC78780833A2DC00EB6054 /* GPULifeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPULifeView.m; sourceTree = ""; }; 54 | C2CC795B0833B01800EB6054 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = ""; }; 55 | C2CC7A7008350BBD00EB6054 /* GPULife.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GPULife.saver; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | C2CC7A7108350BBD00EB6054 /* GPULife saver-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GPULife saver-Info.plist"; sourceTree = ""; }; 57 | C2CC7A7808350BE700EB6054 /* ScreenSaver.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ScreenSaver.framework; path = /System/Library/Frameworks/ScreenSaver.framework; sourceTree = ""; }; 58 | C2CC7A9608350C5A00EB6054 /* GPULifeSaverView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPULifeSaverView.h; sourceTree = ""; }; 59 | C2CC7A9708350C5A00EB6054 /* GPULifeSaverView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPULifeSaverView.m; sourceTree = ""; }; 60 | C2CC7B2F0835127B00EB6054 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/ScreenSaver.nib; sourceTree = ""; }; 61 | /* End PBXFileReference section */ 62 | 63 | /* Begin PBXFrameworksBuildPhase section */ 64 | 8D11072E0486CEB800E47090 /* Frameworks */ = { 65 | isa = PBXFrameworksBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, 69 | C2CC795C0833B01800EB6054 /* OpenGL.framework in Frameworks */, 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | C2CC7A6E08350BBD00EB6054 /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | C2CC7ACE08350E2900EB6054 /* OpenGL.framework in Frameworks */, 78 | C2CC7ACF08350E2900EB6054 /* Cocoa.framework in Frameworks */, 79 | C2CC7A7908350BE700EB6054 /* ScreenSaver.framework in Frameworks */, 80 | ); 81 | runOnlyForDeploymentPostprocessing = 0; 82 | }; 83 | /* End PBXFrameworksBuildPhase section */ 84 | 85 | /* Begin PBXGroup section */ 86 | 080E96DDFE201D6D7F000001 /* Classes */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | ); 90 | name = Classes; 91 | sourceTree = ""; 92 | }; 93 | 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | C2CC7A7808350BE700EB6054 /* ScreenSaver.framework */, 97 | C2CC795B0833B01800EB6054 /* OpenGL.framework */, 98 | 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, 99 | ); 100 | name = "Linked Frameworks"; 101 | sourceTree = ""; 102 | }; 103 | 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 29B97324FDCFA39411CA2CEA /* AppKit.framework */, 107 | 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */, 108 | 29B97325FDCFA39411CA2CEA /* Foundation.framework */, 109 | ); 110 | name = "Other Frameworks"; 111 | sourceTree = ""; 112 | }; 113 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 8D1107320486CEB800E47090 /* GPULife.app */, 117 | C2CC7A7008350BBD00EB6054 /* GPULife.saver */, 118 | ); 119 | name = Products; 120 | sourceTree = ""; 121 | }; 122 | 29B97314FDCFA39411CA2CEA /* GPULife */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 080E96DDFE201D6D7F000001 /* Classes */, 126 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 127 | 29B97317FDCFA39411CA2CEA /* Resources */, 128 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 129 | 19C28FACFE9D520D11CA2CBB /* Products */, 130 | ); 131 | name = GPULife; 132 | sourceTree = ""; 133 | }; 134 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 32CA4F630368D1EE00C91783 /* GPULife_Prefix.pch */, 138 | 29B97316FDCFA39411CA2CEA /* main.m */, 139 | C2CC78770833A2DC00EB6054 /* GPULifeView.h */, 140 | C2CC78780833A2DC00EB6054 /* GPULifeView.m */, 141 | C2CC7A9608350C5A00EB6054 /* GPULifeSaverView.h */, 142 | C2CC7A9708350C5A00EB6054 /* GPULifeSaverView.m */, 143 | ); 144 | name = "Other Sources"; 145 | sourceTree = ""; 146 | }; 147 | 29B97317FDCFA39411CA2CEA /* Resources */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | C2CC7A7108350BBD00EB6054 /* GPULife saver-Info.plist */, 151 | 8D1107310486CEB800E47090 /* Info.plist */, 152 | 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, 153 | 29B97318FDCFA39411CA2CEA /* MainMenu.nib */, 154 | C2CC78700833A2A300EB6054 /* LifeShader */, 155 | C2CC7B2E0835127B00EB6054 /* ScreenSaver.nib */, 156 | ); 157 | name = Resources; 158 | sourceTree = ""; 159 | }; 160 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, 164 | 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, 165 | ); 166 | name = Frameworks; 167 | sourceTree = ""; 168 | }; 169 | /* End PBXGroup section */ 170 | 171 | /* Begin PBXNativeTarget section */ 172 | 8D1107260486CEB800E47090 /* GPULife */ = { 173 | isa = PBXNativeTarget; 174 | buildConfigurationList = C2D8204E0897ABEC008CB8EC /* Build configuration list for PBXNativeTarget "GPULife" */; 175 | buildPhases = ( 176 | 8D1107290486CEB800E47090 /* Resources */, 177 | 8D11072C0486CEB800E47090 /* Sources */, 178 | 8D11072E0486CEB800E47090 /* Frameworks */, 179 | ); 180 | buildRules = ( 181 | ); 182 | dependencies = ( 183 | ); 184 | name = GPULife; 185 | productInstallPath = "$(HOME)/Applications"; 186 | productName = GPULife; 187 | productReference = 8D1107320486CEB800E47090 /* GPULife.app */; 188 | productType = "com.apple.product-type.application"; 189 | }; 190 | C2CC7A6F08350BBD00EB6054 /* GPULife saver */ = { 191 | isa = PBXNativeTarget; 192 | buildConfigurationList = C2D820520897ABEC008CB8EC /* Build configuration list for PBXNativeTarget "GPULife saver" */; 193 | buildPhases = ( 194 | C2CC7A6C08350BBD00EB6054 /* Resources */, 195 | C2CC7A6D08350BBD00EB6054 /* Sources */, 196 | C2CC7A6E08350BBD00EB6054 /* Frameworks */, 197 | C26797C20B0B937E00FD6A40 /* CopyFiles */, 198 | ); 199 | buildRules = ( 200 | ); 201 | dependencies = ( 202 | ); 203 | name = "GPULife saver"; 204 | productName = "GPULife saver"; 205 | productReference = C2CC7A7008350BBD00EB6054 /* GPULife.saver */; 206 | productType = "com.apple.product-type.bundle"; 207 | }; 208 | /* End PBXNativeTarget section */ 209 | 210 | /* Begin PBXProject section */ 211 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 212 | isa = PBXProject; 213 | attributes = { 214 | LastUpgradeCheck = 0440; 215 | }; 216 | buildConfigurationList = C2D820560897ABEC008CB8EC /* Build configuration list for PBXProject "GPULife" */; 217 | compatibilityVersion = "Xcode 3.2"; 218 | developmentRegion = English; 219 | hasScannedForEncodings = 1; 220 | knownRegions = ( 221 | en, 222 | ); 223 | mainGroup = 29B97314FDCFA39411CA2CEA /* GPULife */; 224 | projectDirPath = ""; 225 | projectRoot = ""; 226 | targets = ( 227 | 8D1107260486CEB800E47090 /* GPULife */, 228 | C2CC7A6F08350BBD00EB6054 /* GPULife saver */, 229 | ); 230 | }; 231 | /* End PBXProject section */ 232 | 233 | /* Begin PBXResourcesBuildPhase section */ 234 | 8D1107290486CEB800E47090 /* Resources */ = { 235 | isa = PBXResourcesBuildPhase; 236 | buildActionMask = 2147483647; 237 | files = ( 238 | 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */, 239 | 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */, 240 | C2CC78710833A2A300EB6054 /* LifeShader in Resources */, 241 | ); 242 | runOnlyForDeploymentPostprocessing = 0; 243 | }; 244 | C2CC7A6C08350BBD00EB6054 /* Resources */ = { 245 | isa = PBXResourcesBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | C2CC7ADD08350E6E00EB6054 /* LifeShader in Resources */, 249 | C2CC7B300835127B00EB6054 /* ScreenSaver.nib in Resources */, 250 | ); 251 | runOnlyForDeploymentPostprocessing = 0; 252 | }; 253 | /* End PBXResourcesBuildPhase section */ 254 | 255 | /* Begin PBXSourcesBuildPhase section */ 256 | 8D11072C0486CEB800E47090 /* Sources */ = { 257 | isa = PBXSourcesBuildPhase; 258 | buildActionMask = 2147483647; 259 | files = ( 260 | 8D11072D0486CEB800E47090 /* main.m in Sources */, 261 | C2CC78790833A2DC00EB6054 /* GPULifeView.m in Sources */, 262 | ); 263 | runOnlyForDeploymentPostprocessing = 0; 264 | }; 265 | C2CC7A6D08350BBD00EB6054 /* Sources */ = { 266 | isa = PBXSourcesBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | C2CC7A9808350C5A00EB6054 /* GPULifeSaverView.m in Sources */, 270 | C2CC7A9908350C6300EB6054 /* GPULifeView.m in Sources */, 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | }; 274 | /* End PBXSourcesBuildPhase section */ 275 | 276 | /* Begin PBXVariantGroup section */ 277 | 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { 278 | isa = PBXVariantGroup; 279 | children = ( 280 | 089C165DFE840E0CC02AAC07 /* English */, 281 | ); 282 | name = InfoPlist.strings; 283 | sourceTree = ""; 284 | }; 285 | 29B97318FDCFA39411CA2CEA /* MainMenu.nib */ = { 286 | isa = PBXVariantGroup; 287 | children = ( 288 | 29B97319FDCFA39411CA2CEA /* English */, 289 | ); 290 | name = MainMenu.nib; 291 | sourceTree = ""; 292 | }; 293 | C2CC7B2E0835127B00EB6054 /* ScreenSaver.nib */ = { 294 | isa = PBXVariantGroup; 295 | children = ( 296 | C2CC7B2F0835127B00EB6054 /* English */, 297 | ); 298 | name = ScreenSaver.nib; 299 | sourceTree = ""; 300 | }; 301 | /* End PBXVariantGroup section */ 302 | 303 | /* Begin XCBuildConfiguration section */ 304 | C2D8204F0897ABEC008CB8EC /* Development */ = { 305 | isa = XCBuildConfiguration; 306 | buildSettings = { 307 | COMBINE_HIDPI_IMAGES = YES; 308 | COPY_PHASE_STRIP = NO; 309 | GCC_DYNAMIC_NO_PIC = NO; 310 | GCC_ENABLE_OBJC_GC = supported; 311 | GCC_GENERATE_DEBUGGING_SYMBOLS = YES; 312 | GCC_OPTIMIZATION_LEVEL = 0; 313 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 314 | GCC_PREFIX_HEADER = GPULife_Prefix.pch; 315 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 316 | GCC_WARN_UNUSED_VARIABLE = YES; 317 | INFOPLIST_FILE = Info.plist; 318 | INSTALL_PATH = "$(HOME)/Applications"; 319 | PRODUCT_NAME = GPULife; 320 | SDKROOT_x86_64 = ""; 321 | WARNING_CFLAGS = ( 322 | "-W", 323 | "-Wall", 324 | "-Wno-unused-parameter", 325 | ); 326 | WRAPPER_EXTENSION = app; 327 | ZERO_LINK = YES; 328 | }; 329 | name = Development; 330 | }; 331 | C2D820500897ABEC008CB8EC /* Deployment */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | COMBINE_HIDPI_IMAGES = YES; 335 | COPY_PHASE_STRIP = YES; 336 | GCC_GENERATE_DEBUGGING_SYMBOLS = NO; 337 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 338 | GCC_PREFIX_HEADER = GPULife_Prefix.pch; 339 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 340 | GCC_WARN_UNUSED_VARIABLE = YES; 341 | INFOPLIST_FILE = Info.plist; 342 | INSTALL_PATH = "$(HOME)/Applications"; 343 | PRODUCT_NAME = GPULife; 344 | WARNING_CFLAGS = ( 345 | "-W", 346 | "-Wall", 347 | "-Wno-unused-parameter", 348 | ); 349 | WRAPPER_EXTENSION = app; 350 | ZERO_LINK = NO; 351 | }; 352 | name = Deployment; 353 | }; 354 | C2D820510897ABEC008CB8EC /* Default */ = { 355 | isa = XCBuildConfiguration; 356 | buildSettings = { 357 | COMBINE_HIDPI_IMAGES = YES; 358 | GCC_GENERATE_DEBUGGING_SYMBOLS = NO; 359 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 360 | GCC_PREFIX_HEADER = GPULife_Prefix.pch; 361 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 362 | GCC_WARN_UNUSED_VARIABLE = YES; 363 | INFOPLIST_FILE = Info.plist; 364 | INSTALL_PATH = "$(HOME)/Applications"; 365 | PRODUCT_NAME = GPULife; 366 | WARNING_CFLAGS = ( 367 | "-W", 368 | "-Wall", 369 | "-Wno-unused-parameter", 370 | ); 371 | WRAPPER_EXTENSION = app; 372 | }; 373 | name = Default; 374 | }; 375 | C2D820530897ABEC008CB8EC /* Development */ = { 376 | isa = XCBuildConfiguration; 377 | buildSettings = { 378 | COMBINE_HIDPI_IMAGES = YES; 379 | COPY_PHASE_STRIP = NO; 380 | GCC_DYNAMIC_NO_PIC = NO; 381 | GCC_ENABLE_OBJC_GC = supported; 382 | GCC_GENERATE_DEBUGGING_SYMBOLS = YES; 383 | GCC_MODEL_TUNING = G4; 384 | GCC_OPTIMIZATION_LEVEL = 0; 385 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 386 | GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Cocoa.framework/Headers/Cocoa.h"; 387 | INFOPLIST_FILE = "GPULife saver-Info.plist"; 388 | INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; 389 | LIBRARY_STYLE = BUNDLE; 390 | OTHER_CFLAGS = ""; 391 | OTHER_LDFLAGS = ""; 392 | OTHER_REZFLAGS = ""; 393 | PRODUCT_NAME = GPULife; 394 | SDKROOT_x86_64 = ""; 395 | SECTORDER_FLAGS = ""; 396 | WARNING_CFLAGS = ( 397 | "-W", 398 | "-Wall", 399 | "-Wno-unused-parameter", 400 | ); 401 | WRAPPER_EXTENSION = saver; 402 | ZERO_LINK = YES; 403 | }; 404 | name = Development; 405 | }; 406 | C2D820540897ABEC008CB8EC /* Deployment */ = { 407 | isa = XCBuildConfiguration; 408 | buildSettings = { 409 | COMBINE_HIDPI_IMAGES = YES; 410 | COPY_PHASE_STRIP = YES; 411 | GCC_ENABLE_OBJC_GC = supported; 412 | GCC_GENERATE_DEBUGGING_SYMBOLS = NO; 413 | GCC_MODEL_TUNING = G4; 414 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 415 | GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Cocoa.framework/Headers/Cocoa.h"; 416 | INFOPLIST_FILE = "GPULife saver-Info.plist"; 417 | INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; 418 | LIBRARY_STYLE = BUNDLE; 419 | OTHER_CFLAGS = ""; 420 | OTHER_LDFLAGS = ""; 421 | OTHER_REZFLAGS = ""; 422 | PRODUCT_NAME = GPULife; 423 | SDKROOT_x86_64 = ""; 424 | SECTORDER_FLAGS = ""; 425 | WARNING_CFLAGS = ( 426 | "-W", 427 | "-Wall", 428 | "-Wno-unused-parameter", 429 | ); 430 | WRAPPER_EXTENSION = saver; 431 | ZERO_LINK = NO; 432 | }; 433 | name = Deployment; 434 | }; 435 | C2D820550897ABEC008CB8EC /* Default */ = { 436 | isa = XCBuildConfiguration; 437 | buildSettings = { 438 | COMBINE_HIDPI_IMAGES = YES; 439 | GCC_ENABLE_OBJC_GC = supported; 440 | GCC_GENERATE_DEBUGGING_SYMBOLS = NO; 441 | GCC_MODEL_TUNING = G4; 442 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 443 | GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Cocoa.framework/Headers/Cocoa.h"; 444 | INFOPLIST_FILE = "GPULife saver-Info.plist"; 445 | INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; 446 | LIBRARY_STYLE = BUNDLE; 447 | OTHER_CFLAGS = ""; 448 | OTHER_LDFLAGS = ""; 449 | OTHER_REZFLAGS = ""; 450 | PRODUCT_NAME = GPULife; 451 | SDKROOT_x86_64 = ""; 452 | SECTORDER_FLAGS = ""; 453 | WARNING_CFLAGS = ( 454 | "-W", 455 | "-Wall", 456 | "-Wno-unused-parameter", 457 | ); 458 | WRAPPER_EXTENSION = saver; 459 | }; 460 | name = Default; 461 | }; 462 | C2D820570897ABEC008CB8EC /* Development */ = { 463 | isa = XCBuildConfiguration; 464 | buildSettings = { 465 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 466 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 467 | SDKROOT = macosx10.7; 468 | }; 469 | name = Development; 470 | }; 471 | C2D820580897ABEC008CB8EC /* Deployment */ = { 472 | isa = XCBuildConfiguration; 473 | buildSettings = { 474 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 475 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 476 | SDKROOT = macosx10.7; 477 | }; 478 | name = Deployment; 479 | }; 480 | C2D820590897ABEC008CB8EC /* Default */ = { 481 | isa = XCBuildConfiguration; 482 | buildSettings = { 483 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 484 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 485 | SDKROOT = macosx10.7; 486 | }; 487 | name = Default; 488 | }; 489 | /* End XCBuildConfiguration section */ 490 | 491 | /* Begin XCConfigurationList section */ 492 | C2D8204E0897ABEC008CB8EC /* Build configuration list for PBXNativeTarget "GPULife" */ = { 493 | isa = XCConfigurationList; 494 | buildConfigurations = ( 495 | C2D8204F0897ABEC008CB8EC /* Development */, 496 | C2D820500897ABEC008CB8EC /* Deployment */, 497 | C2D820510897ABEC008CB8EC /* Default */, 498 | ); 499 | defaultConfigurationIsVisible = 0; 500 | defaultConfigurationName = Default; 501 | }; 502 | C2D820520897ABEC008CB8EC /* Build configuration list for PBXNativeTarget "GPULife saver" */ = { 503 | isa = XCConfigurationList; 504 | buildConfigurations = ( 505 | C2D820530897ABEC008CB8EC /* Development */, 506 | C2D820540897ABEC008CB8EC /* Deployment */, 507 | C2D820550897ABEC008CB8EC /* Default */, 508 | ); 509 | defaultConfigurationIsVisible = 0; 510 | defaultConfigurationName = Default; 511 | }; 512 | C2D820560897ABEC008CB8EC /* Build configuration list for PBXProject "GPULife" */ = { 513 | isa = XCConfigurationList; 514 | buildConfigurations = ( 515 | C2D820570897ABEC008CB8EC /* Development */, 516 | C2D820580897ABEC008CB8EC /* Deployment */, 517 | C2D820590897ABEC008CB8EC /* Default */, 518 | ); 519 | defaultConfigurationIsVisible = 0; 520 | defaultConfigurationName = Default; 521 | }; 522 | /* End XCConfigurationList section */ 523 | }; 524 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 525 | } 526 | -------------------------------------------------------------------------------- /GPULifeSaverView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GPULifeSaverView.h 3 | // GPULife 4 | // 5 | // Created by Michael Ash on 5/13/05. 6 | // Copyright 2005 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | @class GPULifeView; 14 | 15 | @interface GPULifeSaverView : ScreenSaverView { 16 | GPULifeView *lifeView; 17 | 18 | IBOutlet NSWindow *configureSheet; 19 | IBOutlet NSButton *limitFPSCheckbox; 20 | IBOutlet NSSlider *fpsSlider; 21 | IBOutlet NSButton *displayFPSCheckbox; 22 | IBOutlet NSTextField *fpsField; 23 | IBOutlet NSSlider *zoomSlider; 24 | IBOutlet NSTextField *zoomField; 25 | IBOutlet NSSlider *initialFillSlider; 26 | IBOutlet NSTextField *generationField; 27 | 28 | IBOutlet NSBox *colorWellBox; 29 | NSDictionary *colorWells; 30 | 31 | NSString *fpsString; 32 | } 33 | 34 | - (void)limitFPSChecked:sender; 35 | - (void)limitFPSSlider:sender; 36 | - (void)limitFPSField:sender; 37 | - (void)ok:sender; 38 | - (void)cancel:sender; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /GPULifeSaverView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GPULifeSaverView.m 3 | // GPULife 4 | // 5 | // Created by Michael Ash on 5/13/05. 6 | // Copyright 2005 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "GPULifeSaverView.h" 10 | 11 | #import "GPULifeView.h" 12 | 13 | 14 | @implementation GPULifeSaverView 15 | 16 | static NSString * const kLimitFPSDefaultsName = @"LimitFPS"; 17 | static NSString * const kLimitFPSValueDefaultsName = @"LimitFPSValue"; 18 | static NSString * const kDisplayFPSDefaultsName = @"DisplayFPS"; 19 | static NSString * const kZoomDefaultsName = @"Zoom"; 20 | static NSString * const kInitialFillDefaultsName = @"InitialFill"; 21 | static NSString * const kGenerationDefaultsName = @"GenerationRate"; 22 | static NSString * const kCornerColorsDefaultsName = @"CornerColors"; 23 | 24 | + (void)initialize 25 | { 26 | [[ScreenSaverDefaults defaultsForModuleWithName: 27 | [[NSBundle bundleForClass:[self class]] bundleIdentifier]] registerDefaults: 28 | [NSDictionary dictionaryWithObjectsAndKeys: 29 | [NSNumber numberWithBool:YES], kLimitFPSDefaultsName, 30 | [NSNumber numberWithDouble:30.0], kLimitFPSValueDefaultsName, 31 | [NSNumber numberWithBool:NO], kDisplayFPSDefaultsName, 32 | [NSNumber numberWithInt:2], kZoomDefaultsName, 33 | [NSNumber numberWithInt:12], kInitialFillDefaultsName, 34 | [NSNumber numberWithInt:1], kGenerationDefaultsName, 35 | [NSArchiver archivedDataWithRootObject:[NSArray arrayWithObjects: 36 | [NSColor redColor], [NSColor blueColor], [NSColor greenColor], [NSColor whiteColor], nil]], 37 | kCornerColorsDefaultsName, 38 | nil]]; 39 | } 40 | 41 | - (GPULifeColor3)structForNSColor:(NSColor *)c 42 | { 43 | GPULifeColor3 ret; 44 | c = [c colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; 45 | [c getRed:&ret.r green:&ret.g blue:&ret.b alpha:NULL]; 46 | float max = MAX(MAX(ret.r, ret.g), ret.b); 47 | 48 | // make sure the color isn't too black so the shader can still find it 49 | if(max < 0.101) 50 | { 51 | if(max == 0.0) 52 | ret.r = ret.g = ret.b = 0.101; 53 | else 54 | { 55 | ret.r *= 0.101 / max; 56 | ret.g *= 0.101 / max; 57 | ret.b *= 0.101 / max; 58 | } 59 | } 60 | return ret; 61 | } 62 | 63 | - (void)reinitLifeView 64 | { 65 | [lifeView removeFromSuperview]; 66 | [lifeView release]; 67 | 68 | lifeView = [[GPULifeView alloc] initWithFrame:[self bounds]]; 69 | [lifeView setUsesTimer:NO]; 70 | 71 | ScreenSaverDefaults *defaults = [ScreenSaverDefaults defaultsForModuleWithName: 72 | [[NSBundle bundleForClass:[self class]] bundleIdentifier]]; 73 | [lifeView setShowsFPS:[defaults boolForKey:kDisplayFPSDefaultsName]]; 74 | [lifeView setZoom:[defaults integerForKey:kZoomDefaultsName]]; 75 | [lifeView setGenerationRate:[defaults integerForKey:kGenerationDefaultsName]]; 76 | [lifeView setInitialFill:[defaults integerForKey:kInitialFillDefaultsName]]; 77 | 78 | GPULifeColor3 colorsArray[4]; 79 | NSArray *colors = [NSUnarchiver unarchiveObjectWithData:[defaults objectForKey:kCornerColorsDefaultsName]]; 80 | int i; 81 | for(i = 0; i < 4; i++) 82 | colorsArray[i] = [self structForNSColor:[colors objectAtIndex:i]]; 83 | [lifeView setCornerColors:colorsArray]; 84 | 85 | [self addSubview:lifeView]; 86 | } 87 | 88 | - (id)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview 89 | { 90 | self = [super initWithFrame:frame isPreview:isPreview]; 91 | if (self) { 92 | [self reinitLifeView]; 93 | } 94 | return self; 95 | } 96 | 97 | - (void)dealloc 98 | { 99 | [lifeView release]; 100 | [colorWells release]; 101 | [configureSheet release]; 102 | [super dealloc]; 103 | } 104 | 105 | - (void)startAnimation 106 | { 107 | ScreenSaverDefaults *defaults = [ScreenSaverDefaults defaultsForModuleWithName: 108 | [[NSBundle bundleForClass:[self class]] bundleIdentifier]]; 109 | if([defaults boolForKey:kLimitFPSDefaultsName]) 110 | [self setAnimationTimeInterval:1.0 / [[defaults objectForKey:kLimitFPSValueDefaultsName] doubleValue]]; 111 | else 112 | [self setAnimationTimeInterval:0.0]; 113 | [super startAnimation]; 114 | } 115 | 116 | - (void)stopAnimation 117 | { 118 | [super stopAnimation]; 119 | } 120 | 121 | - (void)drawRect:(NSRect)rect 122 | { 123 | } 124 | 125 | - (void)animateOneFrame 126 | { 127 | [lifeView display]; 128 | } 129 | 130 | - (BOOL)hasConfigureSheet 131 | { 132 | return YES; 133 | } 134 | 135 | - (void)fillDictionary:(NSMutableDictionary*)dict withColorWellsInView:(NSView *)superview 136 | { 137 | NSEnumerator *enumerator = [[superview subviews] objectEnumerator]; 138 | NSView *view; 139 | while((view = [enumerator nextObject])) 140 | { 141 | if([view isKindOfClass:[NSColorWell class]]) 142 | [dict setObject:view forKey:[NSNumber numberWithInt:[view tag]]]; 143 | else 144 | [self fillDictionary:dict withColorWellsInView:view]; 145 | } 146 | } 147 | 148 | - (NSWindow*)configureSheet 149 | { 150 | if(!configureSheet) 151 | { 152 | [NSBundle loadNibNamed:@"ScreenSaver" owner:self]; 153 | 154 | NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init]; 155 | [self fillDictionary:tempDict withColorWellsInView:colorWellBox]; 156 | [colorWells release]; 157 | colorWells = [tempDict copy]; 158 | } 159 | 160 | ScreenSaverDefaults *defaults = [ScreenSaverDefaults defaultsForModuleWithName:[[NSBundle bundleForClass:[self class]] bundleIdentifier]]; 161 | 162 | [limitFPSCheckbox setState:[defaults boolForKey:kLimitFPSDefaultsName] ? NSOnState : NSOffState]; 163 | double fpsLimit = [[defaults objectForKey:kLimitFPSValueDefaultsName] doubleValue];; 164 | [fpsSlider setDoubleValue:fpsLimit]; 165 | [fpsField setDoubleValue:fpsLimit]; 166 | [displayFPSCheckbox setState:[defaults boolForKey:kDisplayFPSDefaultsName] ? NSOnState : NSOffState]; 167 | int zoom = [defaults integerForKey:kZoomDefaultsName]; 168 | [zoomSlider setIntValue:zoom]; 169 | [zoomField setIntValue:zoom]; 170 | [initialFillSlider setIntValue:[defaults integerForKey:kInitialFillDefaultsName]]; 171 | [generationField setIntValue:[defaults integerForKey:kGenerationDefaultsName]]; 172 | 173 | NSArray *colors = [NSUnarchiver unarchiveObjectWithData:[defaults objectForKey:kCornerColorsDefaultsName]]; 174 | int i; 175 | for(i = 0; i < 4; i++) 176 | [[colorWells objectForKey:[NSNumber numberWithInt:i]] setColor:[colors objectAtIndex:i]]; 177 | 178 | [self limitFPSChecked:limitFPSCheckbox]; 179 | 180 | return configureSheet; 181 | } 182 | 183 | - (void)limitFPSChecked:sender 184 | { 185 | [fpsSlider setEnabled:[sender state] == NSOnState]; 186 | [fpsField setEnabled:[sender state] == NSOnState]; 187 | } 188 | 189 | - (void)limitFPSSlider:sender 190 | { 191 | double fpsLimit = [fpsSlider doubleValue]; 192 | [fpsField setDoubleValue:fpsLimit]; 193 | } 194 | 195 | - (void)limitFPSField:sender 196 | { 197 | double fpsLimit = [fpsField doubleValue]; 198 | [fpsSlider setDoubleValue:fpsLimit]; 199 | } 200 | 201 | - (void)ok:sender 202 | { 203 | ScreenSaverDefaults *defaults = [ScreenSaverDefaults defaultsForModuleWithName:[[NSBundle bundleForClass:[self class]] bundleIdentifier]]; 204 | 205 | [defaults setBool:[limitFPSCheckbox state] == NSOnState forKey:kLimitFPSDefaultsName]; 206 | [defaults setObject:[NSNumber numberWithDouble:[fpsField doubleValue]] forKey:kLimitFPSValueDefaultsName]; 207 | [defaults setBool:[displayFPSCheckbox state] == NSOnState forKey:kDisplayFPSDefaultsName]; 208 | [defaults setInteger:[zoomField intValue] forKey:kZoomDefaultsName]; 209 | [defaults setInteger:[initialFillSlider intValue] forKey:kInitialFillDefaultsName]; 210 | [defaults setInteger:[generationField intValue] forKey:kGenerationDefaultsName]; 211 | 212 | NSMutableArray *array = [NSMutableArray array]; 213 | int i; 214 | for(i = 0; i < 4; i++) 215 | [array addObject:[[colorWells objectForKey:[NSNumber numberWithInt:i]] color]]; 216 | [defaults setObject:[NSArchiver archivedDataWithRootObject:array] forKey:kCornerColorsDefaultsName]; 217 | 218 | [defaults synchronize]; 219 | 220 | [NSApp endSheet:configureSheet]; 221 | 222 | [self reinitLifeView]; 223 | 224 | [[NSColorPanel sharedColorPanel] orderOut:nil]; 225 | } 226 | 227 | - (void)cancel:sender 228 | { 229 | [NSApp endSheet:configureSheet]; 230 | 231 | [[NSColorPanel sharedColorPanel] orderOut:nil]; 232 | } 233 | 234 | @end 235 | -------------------------------------------------------------------------------- /GPULifeView.h: -------------------------------------------------------------------------------- 1 | // 2 | // GPULifeView.h 3 | // GPULife 4 | // 5 | // Created by Michael Ash on 5/12/05. 6 | // Copyright 2005 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import 12 | 13 | 14 | #if !CGFLOAT_DEFINED 15 | typedef float CGFloat; 16 | #endif 17 | 18 | typedef struct { 19 | CGFloat r, g, b; 20 | } GPULifeColor3; 21 | 22 | @interface GPULifeView : NSOpenGLView { 23 | BOOL inited; 24 | GLuint tex; 25 | GLuint shader; 26 | int xsize, ysize; 27 | 28 | BOOL usingFPSTex; 29 | GLuint fpsTex; 30 | int fpsTexXSize, fpsTexYSize; 31 | 32 | int zoom; 33 | 34 | int generationRate; 35 | int initialFill; 36 | 37 | int numFrames; 38 | double lastClock; 39 | 40 | GPULifeColor3 cornerColors[4]; 41 | 42 | id fpsTarget; 43 | SEL fpsSelector; 44 | 45 | BOOL usesTimer; 46 | } 47 | 48 | - (void)setZoom:(int)z; 49 | - (void)setGenerationRate:(int)r; 50 | - (void)setInitialFill:(int)f; 51 | - (void)setCornerColors:(GPULifeColor3 *)c; 52 | - (void)setFPSTarget:o selector:(SEL)s; 53 | - (void)setShowsFPS:(BOOL)yorn; 54 | - (void)setUsesTimer:(BOOL)yorn; 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /GPULifeView.m: -------------------------------------------------------------------------------- 1 | // 2 | // GPULifeView.m 3 | // GPULife 4 | // 5 | // Created by Michael Ash on 5/12/05. 6 | // Copyright 2005 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "GPULifeView.h" 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | 18 | @implementation GPULifeView 19 | 20 | + (void)initialize 21 | { 22 | srandomdev(); 23 | } 24 | 25 | - (id)initWithFrame:(NSRect)frame { 26 | NSOpenGLPixelFormatAttribute attribs[] = { 27 | NSOpenGLPFADoubleBuffer, 28 | 0 29 | }; 30 | NSOpenGLPixelFormat *myFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; 31 | self = [super initWithFrame:frame pixelFormat:myFormat]; 32 | [myFormat release]; 33 | if (self) 34 | { 35 | zoom = 1; 36 | generationRate = 1; 37 | initialFill = 12; 38 | usesTimer = YES; 39 | 40 | GPULifeColor3 initialColors[4] = { 41 | {0, 0, 1}, 42 | {0, 1, 0}, 43 | {1, 0, 0}, 44 | {0, 1, 1} 45 | }; 46 | [self setCornerColors:initialColors]; 47 | } 48 | return self; 49 | } 50 | 51 | - (void)dealloc 52 | { 53 | glDeleteTextures(1, &tex); 54 | glDeleteProgramsARB(1, &shader); 55 | if(usingFPSTex) 56 | glDeleteTextures(1, &fpsTex); 57 | 58 | [super dealloc]; 59 | } 60 | 61 | - (void)setZoom:(int)z 62 | { 63 | if(inited) 64 | { 65 | NSLog(@"%s can only be called before the the view's first display", __func__); 66 | return; 67 | } 68 | zoom = z; 69 | } 70 | 71 | - (void)setGenerationRate:(int)r 72 | { 73 | generationRate = r; 74 | } 75 | 76 | - (void)setInitialFill:(int)f 77 | { 78 | if(inited) 79 | { 80 | NSLog(@"%s can only be called before the the view's first display", __func__); 81 | return; 82 | } 83 | initialFill = f; 84 | } 85 | 86 | - (void)setCornerColors:(GPULifeColor3 *)c 87 | { 88 | memcpy(cornerColors, c, sizeof(cornerColors)); 89 | } 90 | 91 | - (void)setFPSTarget:o selector:(SEL)s 92 | { 93 | if([o respondsToSelector:s]) 94 | { 95 | fpsTarget = o; 96 | fpsSelector = s; 97 | } 98 | else 99 | { 100 | fpsTarget = nil; 101 | fpsSelector = NULL; 102 | } 103 | } 104 | 105 | - (void)setShowsFPS:(BOOL)yorn 106 | { 107 | if(yorn) 108 | [self setFPSTarget:self selector:@selector(setFPSTextureWithString:)]; 109 | else 110 | { 111 | [self setFPSTarget:nil selector:NULL]; 112 | if(usingFPSTex) 113 | { 114 | glDeleteTextures(1, &fpsTex); 115 | usingFPSTex = NO; 116 | } 117 | } 118 | } 119 | 120 | - (void)setUsesTimer:(BOOL)yorn 121 | { 122 | if(inited) 123 | { 124 | NSLog(@"%s can only be called before the the view's first display", __func__); 125 | return; 126 | } 127 | usesTimer = yorn; 128 | } 129 | 130 | - (void)createTexture 131 | { 132 | uint32_t *data = malloc(xsize * ysize * sizeof(*data)); 133 | int i; 134 | for(i = 0; i < xsize * ysize; i++) 135 | data[i] = (random() % 100) >= initialFill ? 0 : 0xFFFFFFFFUL; 136 | 137 | glGenTextures(1, &tex); 138 | glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); 139 | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); 140 | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); 141 | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 142 | glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 143 | glPixelStorei(GL_UNPACK_ROW_LENGTH, xsize); 144 | glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 145 | 0, 146 | GL_RGBA, 147 | xsize, 148 | ysize, 149 | 0, 150 | GL_BGRA, 151 | GL_UNSIGNED_INT_8_8_8_8_REV, 152 | data); 153 | free(data); 154 | } 155 | 156 | - (void)loadShader 157 | { 158 | NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"LifeShader" ofType:@""]; 159 | NSString *source = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL]; 160 | const char *sourceC = [source UTF8String]; 161 | 162 | glGenProgramsARB(1, &shader); 163 | glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader); 164 | glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(sourceC), sourceC); 165 | glDisable(GL_FRAGMENT_PROGRAM_ARB); 166 | } 167 | 168 | - (void)reshape 169 | { 170 | if(!inited) 171 | { 172 | xsize = [self bounds].size.width / zoom; 173 | ysize = [self bounds].size.height / zoom; 174 | [self createTexture]; 175 | [self loadShader]; 176 | inited = YES; 177 | 178 | if(usesTimer) 179 | [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(timer) userInfo:NULL repeats:YES]; 180 | } 181 | 182 | 183 | /* select clearing color */ 184 | glClearColor (0.0, 0.0, 0.0, 1.0); 185 | glClear (GL_COLOR_BUFFER_BIT); 186 | 187 | /* initialize viewing values */ 188 | double w = NSWidth([self bounds]); 189 | double h = NSHeight([self bounds]); 190 | glViewport(0, 0, (GLsizei) w, (GLsizei) h); 191 | glMatrixMode(GL_PROJECTION); 192 | glLoadIdentity(); 193 | gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h); 194 | glMatrixMode(GL_MODELVIEW); 195 | glLoadIdentity(); 196 | 197 | /* 198 | glEnable (GL_BLEND); 199 | 200 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 201 | 202 | glEnable(GL_TEXTURE_2D); 203 | */ 204 | //glEnable(GL_TEXTURE_RECTANGLE_EXT); 205 | } 206 | 207 | - (void)timer 208 | { 209 | [self setNeedsDisplay:YES]; 210 | } 211 | 212 | double curTime(void) 213 | { 214 | static struct mach_timebase_info timebase; 215 | mach_timebase_info(&timebase); 216 | 217 | return (double)((mach_absolute_time() * timebase.numer) / timebase.denom) / 1000.0; 218 | } 219 | 220 | - (void)setFPSTextureWithString:(NSString *)str 221 | { 222 | NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys: 223 | [NSColor whiteColor], NSForegroundColorAttributeName, 224 | [NSFont userFixedPitchFontOfSize:16], NSFontAttributeName, 225 | nil]; 226 | NSSize size = [str sizeWithAttributes:attrs]; 227 | NSRect rect = NSMakeRect(0, 0, size.width, size.height); 228 | NSImage *image = [[NSImage alloc] initWithSize:size]; 229 | [image lockFocus]; 230 | [str drawInRect:rect withAttributes:attrs]; 231 | NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:rect]; 232 | [image unlockFocus]; 233 | [image release]; 234 | 235 | int bytesPerRow = [imageRep bytesPerRow]; 236 | int bitsPerPixel = [imageRep bitsPerPixel]; 237 | BOOL hasAlpha = [imageRep hasAlpha]; 238 | void *data = [imageRep bitmapData]; 239 | 240 | if(usingFPSTex) 241 | glDeleteTextures(1, &fpsTex); 242 | 243 | glGenTextures(1, &fpsTex); 244 | glBindTexture(GL_TEXTURE_RECTANGLE_EXT, fpsTex); 245 | glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP); 246 | glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP); 247 | glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 248 | glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 249 | glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 250 | glPixelStorei(GL_UNPACK_ROW_LENGTH, bytesPerRow / (bitsPerPixel >> 3)); 251 | glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 252 | 0, 253 | GL_RGBA, 254 | size.width, 255 | size.height, 256 | 0, 257 | hasAlpha ? GL_RGBA : GL_RGB, 258 | GL_UNSIGNED_BYTE, 259 | data); 260 | usingFPSTex = YES; 261 | fpsTexXSize = size.width; 262 | fpsTexYSize = size.height; 263 | 264 | [imageRep release]; 265 | } 266 | 267 | - (void)measureFPS 268 | { 269 | const int framesToMeasure = 50; 270 | 271 | numFrames++; 272 | if(lastClock == 0) 273 | { 274 | numFrames--; 275 | lastClock = curTime(); 276 | } 277 | else if(numFrames >= framesToMeasure) 278 | { 279 | double now = curTime(); 280 | double totalTime = now - lastClock; 281 | float floatTime = (float)totalTime / 1000000.0; 282 | float fps = (float)numFrames/floatTime; 283 | numFrames = 0; 284 | lastClock = now; 285 | [fpsTarget performSelector:fpsSelector withObject:[NSString stringWithFormat:@"fps = %.2f", fps]]; 286 | } 287 | } 288 | 289 | - (void)drawTexture 290 | { 291 | glBegin(GL_QUADS); 292 | 293 | glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, 0); 294 | glMultiTexCoord3fARB(GL_TEXTURE1_ARB, cornerColors[0].r, cornerColors[0].g, cornerColors[0].b); 295 | glVertex2f(0, 0); 296 | 297 | glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0, ysize); 298 | glMultiTexCoord3fARB(GL_TEXTURE1_ARB, cornerColors[1].r, cornerColors[1].g, cornerColors[1].b); 299 | glVertex2f(0, ysize); 300 | 301 | glMultiTexCoord2fARB(GL_TEXTURE0_ARB, xsize, ysize); 302 | glMultiTexCoord3fARB(GL_TEXTURE1_ARB, cornerColors[2].r, cornerColors[2].g, cornerColors[2].b); 303 | glVertex2f(xsize, ysize); 304 | 305 | glMultiTexCoord2fARB(GL_TEXTURE0_ARB, xsize, 0); 306 | glMultiTexCoord3fARB(GL_TEXTURE1_ARB, cornerColors[3].r, cornerColors[3].g, cornerColors[3].b); 307 | glVertex2f(xsize, 0); 308 | 309 | glEnd(); 310 | } 311 | 312 | - (void)step 313 | { 314 | glActiveTextureARB(GL_TEXTURE0_ARB); 315 | glEnable(GL_TEXTURE_RECTANGLE_ARB); 316 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 317 | glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); 318 | glEnable(GL_FRAGMENT_PROGRAM_ARB); 319 | glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader); 320 | 321 | [self drawTexture]; 322 | 323 | glDisable(GL_TEXTURE_RECTANGLE_ARB); 324 | glDisable(GL_FRAGMENT_PROGRAM_ARB); 325 | 326 | // plot some random pixels 327 | int i; 328 | glBegin(GL_QUADS); 329 | for(i = 0; i < generationRate; i++) 330 | { 331 | int x = random() % xsize; 332 | int y = random() % ysize; 333 | 334 | 335 | glColor4f(1.0, 1.0, 1.0, 1.0); 336 | glVertex2f(x, y); 337 | glVertex2f(x, y + 1); 338 | glVertex2f(x + 1, y + 1); 339 | glVertex2f(x + 1, y); 340 | } 341 | glEnd(); 342 | 343 | glReadBuffer(GL_BACK); 344 | glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 345 | 0, 346 | 0, 347 | 0, 348 | 0, 349 | 0, 350 | xsize, 351 | ysize); 352 | } 353 | 354 | - (void)drawRect:(NSRect)rect { 355 | [self step]; 356 | 357 | if(zoom != 1) 358 | { 359 | glEnable(GL_TEXTURE_RECTANGLE_ARB); 360 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 361 | glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); 362 | 363 | glPushMatrix(); 364 | 365 | glScalef(zoom, zoom, 1); 366 | [self drawTexture]; 367 | 368 | glPopMatrix(); 369 | 370 | glDisable(GL_TEXTURE_RECTANGLE_ARB); 371 | } 372 | 373 | if(usingFPSTex) 374 | { 375 | glEnable(GL_TEXTURE_RECTANGLE_EXT); 376 | glEnable(GL_BLEND); 377 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 378 | glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 379 | glBindTexture(GL_TEXTURE_RECTANGLE_EXT, fpsTex); 380 | 381 | glPushMatrix(); 382 | glTranslatef(5, 5, 0); 383 | 384 | //glColor4f(0.0, 0.0, 0.0, 0.0); 385 | 386 | glBegin(GL_QUADS); 387 | 388 | glTexCoord2i(0, fpsTexYSize); 389 | glVertex2i(0, 0); 390 | 391 | glTexCoord2i(0, 0); 392 | glVertex2i(0, fpsTexYSize); 393 | 394 | glTexCoord2i(fpsTexXSize, 0); 395 | glVertex2i(fpsTexXSize, fpsTexYSize); 396 | 397 | glTexCoord2i(fpsTexXSize, fpsTexYSize); 398 | glVertex2i(fpsTexXSize, 0); 399 | 400 | glEnd(); 401 | 402 | glPopMatrix(); 403 | 404 | glDisable(GL_BLEND); 405 | glDisable(GL_TEXTURE_RECTANGLE_EXT); 406 | } 407 | 408 | [[self openGLContext] flushBuffer]; 409 | 410 | if(fpsTarget) 411 | [self measureFPS]; 412 | } 413 | 414 | @end 415 | -------------------------------------------------------------------------------- /GPULife_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'GPULife' target in the 'GPULife' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | GPULife 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.apple.myCocoaApplication 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundlePackageType 16 | APPL 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0.1 21 | NSMainNibFile 22 | MainMenu 23 | NSPrincipalClass 24 | NSApplication 25 | 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007 Michael Ash 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /LifeShader: -------------------------------------------------------------------------------- 1 | !!ARBfp1.0 2 | 3 | # "one" contains the value we add to a tex coord to get neighboring tex coords 4 | # this should be 1.0 and -1.0 for rectangle extension textures 5 | PARAM one = {1.0, -1.0, 0.0, 0.0}; 6 | PARAM blackThreshold = {0.1, 0.1, 0.1, 0.1}; 7 | PARAM white = {1.0, 1.0, 1.0, 1.0}; 8 | PARAM black = {0.0, 0.0, 0.0, 0.0}; 9 | 10 | # get texture values for all eight neighbors 11 | TEMP neighborCoord; 12 | TEMP neighborColor; 13 | MOV neighborColor, {0.0, 0.0, 0.0, 0.0}; 14 | 15 | # compute four neighbors, store into numNeighbors1.xyzw 16 | TEMP numNeighbors1; 17 | 18 | # +x direction 19 | ADD neighborCoord, fragment.texcoord[0], one.xzzz; 20 | TEX neighborColor, neighborCoord, texture[0], RECT; 21 | DP3 neighborColor, neighborColor, white; # get the sum of all color components 22 | SGE numNeighbors1.x, neighborColor, blackThreshold; # clamp to 0 or 1 based on threshold 23 | 24 | # -x direction 25 | ADD neighborCoord, fragment.texcoord[0], one.yzzz; 26 | TEX neighborColor, neighborCoord, texture[0], RECT; 27 | DP3 neighborColor, neighborColor, white; # get the sum of all color components 28 | SGE numNeighbors1.y, neighborColor, blackThreshold; # clamp to 0 or 1 based on threshold 29 | 30 | # +y direction 31 | ADD neighborCoord, fragment.texcoord[0], one.zxzz; 32 | TEX neighborColor, neighborCoord, texture[0], RECT; 33 | DP3 neighborColor, neighborColor, white; # get the sum of all color components 34 | SGE numNeighbors1.z, neighborColor, blackThreshold; # clamp to 0 or 1 based on threshold 35 | 36 | # -y direction 37 | ADD neighborCoord, fragment.texcoord[0], one.zyzz; 38 | TEX neighborColor, neighborCoord, texture[0], RECT; 39 | DP3 neighborColor, neighborColor, white; # get the sum of all color components 40 | SGE numNeighbors1.w, neighborColor, blackThreshold; # clamp to 0 or 1 based on threshold 41 | 42 | # compute four neighbors, store into numNeighbors2.xyzw 43 | TEMP numNeighbors2; 44 | 45 | # +xy direction 46 | ADD neighborCoord, fragment.texcoord[0], one.xxzz; 47 | TEX neighborColor, neighborCoord, texture[0], RECT; 48 | DP3 neighborColor, neighborColor, white; # get the sum of all color components 49 | SGE numNeighbors2.x, neighborColor, blackThreshold; # clamp to 0 or 1 based on threshold 50 | 51 | # -x+y direction 52 | ADD neighborCoord, fragment.texcoord[0], one.yxzz; 53 | TEX neighborColor, neighborCoord, texture[0], RECT; 54 | DP3 neighborColor, neighborColor, white; # get the sum of all color components 55 | SGE numNeighbors2.y, neighborColor, blackThreshold; # clamp to 0 or 1 based on threshold 56 | 57 | # +x-y direction 58 | ADD neighborCoord, fragment.texcoord[0], one.xyzz; 59 | TEX neighborColor, neighborCoord, texture[0], RECT; 60 | DP3 neighborColor, neighborColor, white; # get the sum of all color components 61 | SGE numNeighbors2.z, neighborColor, blackThreshold; # clamp to 0 or 1 based on threshold 62 | 63 | # -x-y direction 64 | ADD neighborCoord, fragment.texcoord[0], one.yyzz; 65 | TEX neighborColor, neighborCoord, texture[0], RECT; 66 | DP3 neighborColor, neighborColor, white; # get the sum of all color components 67 | SGE numNeighbors2.w, neighborColor, blackThreshold; # clamp to 0 or 1 based on threshold 68 | 69 | # now squish the two numNeighbors down to a single vector with identical components 70 | DP4 numNeighbors1, numNeighbors1, {1.0, 1.0, 1.0, 1.0}; 71 | DP4 numNeighbors2, numNeighbors2, {1.0, 1.0, 1.0, 1.0}; 72 | 73 | TEMP numNeighbors; 74 | ADD numNeighbors, numNeighbors1, numNeighbors2; 75 | 76 | # finally, get our current value 77 | TEMP curValue; 78 | TEX curValue, fragment.texcoord[0], texture[0], RECT; 79 | DP3 curValue, curValue, white; 80 | SGE curValue, curValue, blackThreshold; 81 | 82 | # set gteq2 equal to 1 if we have at least 2 neighbors 83 | TEMP gteq2; 84 | SGE gteq2, numNeighbors, {1.5, 1.5, 1.5, 1.5}; 85 | 86 | # set gteq3 equal to 1 if we have at least 3 neighbors 87 | TEMP gteq3; 88 | SGE gteq3, numNeighbors, {2.5, 2.5, 2.5, 2.5}; 89 | 90 | # set gteq4 equal to 1 if we have at least 4 neighbors 91 | TEMP gteq4; 92 | SGE gteq4, numNeighbors, {3.5, 3.5, 3.5, 3.5}; 93 | 94 | # compute this formula: curValue * gteq2 + gteq3 95 | # gives 0 if cell starves or stays dead, 1 if cell survives or is born 96 | MAD curValue, curValue, gteq2, gteq3; 97 | # clamp to 0 or 1 98 | SGE curValue, curValue, white; 99 | 100 | # finally, subtract gteq4 101 | # if gteq4 is 1, then curValue is also 1, so this will always give either 1 or 0 102 | SUB curValue, curValue, gteq4; 103 | 104 | MUL result.color, curValue, fragment.texcoord[1]; 105 | 106 | MOV result.color.a, 1.0; 107 | 108 | END 109 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // GPULife 4 | // 5 | // Created by Michael Ash on 5/12/05. 6 | // Copyright __MyCompanyName__ 2005. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **) argv); 14 | } 15 | -------------------------------------------------------------------------------- /website/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | GPULife for Mac OS X 4 | 5 | 6 |

GPULife for Mac OS X

7 |

Introducing the Game of Life screensaver with the highest system requirements in history!

8 | 9 | 10 | 11 |

But it may be one of the fastest....

12 | 13 |

This Life screensaver runs almost entirely on your graphics card. The logic is written as an OpenGL shader, with just a bit of extra programming to glue it all together. This screensaver gets 22fps on my PowerBook G4 running at a 1x zoom fullscreen at 1280x854 while using only 10% of the CPU.

14 | 15 |
16 | 17 |

News: GPULife 1.0.1 is now a universal binary. So you can run GPULife on all those blazing fast Intel Chip Based Macs. Enjoy! And on that note, if anybody could tell me whether it runs on the new Mini, I would love to know.

18 | 19 |

Because it's a shader, and a rather complicated shader, it needs a hefty graphics card to work. So far, it's been tested and known to work on these cards:

20 |
    21 |
  • ATI Mobility Radeon 9700
  • 22 |
  • ATI Mobility Radeon 9200
  • 23 |
  • ATI Radeon 9200
  • 24 |
  • ATI Radeon 9600 Pro
  • 25 |
  • ATI Radeon 9600 XT
  • 26 |
  • ATI Radeon X800
  • 27 |
  • NVIDIA GeForce FX Go5200
  • 28 |
  • NVIDIA GeForce FX 5200
  • 29 |
30 |

If you have one of these cards, or something better, it will probably work fine. If you don't, it may not. However, the worst that can happen is that it won't work. If your screen comes out pure black, or pure white, or never changes, it's probably because of the graphics card.

31 | 32 |

If it works on your system and your card is not on this list, please e-mail me so I can update the list.

33 | 34 |

Download

35 | 36 |

Download GPULife (26kB) - Requires Mac OS X 10.3 (possibly higher) and a hefty video card.

37 | 38 |

After downloading, double-click the GPULife.saver file. It will open System Preferences and prompt you to install the screensaver.

39 | 40 |

For questions, comments, support, etc., e-mail Michael Ash.

41 | 42 | 43 | 44 |

Options

45 | 46 |

Limit framerate: This option allows you to limit the rate at which the screensaver updates, to keep from using 100% of your graphics card's power. If unchecked, the screensaver will run as fast as your hardware will allow. If checked, you can set a maximum framerate using the slider and textbox to the right.

47 | 48 |

Show framerate: If checked, the current framerate will be displayed in the lower left corner of your screen.

49 | 50 |

Zoom: This allows you to control the zoom factor of the screensaver; at 1, one pixel is one Life cell.

51 | 52 |

Initial fill: When the screensaver starts, the field is filled with a random assortment of live and dead cells. This slider control the proportion of live cells. Both extremes are likely to rapidly result in a very dead space; best results are found in the middle.

53 | 54 |

Add random cells (per step): The screensaver will add the given number of live cells to the grid at every step. A small number of random cells can keep the grid from stagnating into still or repeating forms.

55 | 56 |

Corner colors: Liven up your screensaver by setting custom colors for the live cells. Dead cells are always black. Colors that are too close to black can confuse the engine, so dark are automatically brightened slightly.

57 | 58 |

What is Life?

59 | 60 |

More properly called Conway's Game of Life, Life is a cellular automaton. It's a computer simulation which takes place on a grid; each square in the grid is a cell which is either alive or dead. In Life, each cell counts its eight neighbors (four cardinal directions plus diagonals). If a live cell has two or three neighbors, it stays alive, otherwise it dies. If a dead cell has three neighbors, it is born, otherwise it stays dead. Through these simple rules, complex patterns evolve.

61 | 62 |

For more information, see Conway's Game of Life at the Wikipedia. 63 | 64 |

GPULife is copyright 2005 by Michael Ash

65 | 66 | 67 | -------------------------------------------------------------------------------- /website/life.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeash/GPULife/6c1c3908bc9ffba4131ec42622918dae86be8c93/website/life.png -------------------------------------------------------------------------------- /website/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikeash/GPULife/6c1c3908bc9ffba4131ec42622918dae86be8c93/website/settings.png --------------------------------------------------------------------------------