The idea of this repo is to make a macOS screensaver out of my solid-light-works repo which is an attempt to render some of Anthony McCall's solid light works using three.js and WebGL. I intend to write the screensaver in Swift using Metal.
The first step was to create a basic macOS screensaver in Swift using Metal. This has not been easy. I have not been able to find much in the way of examples. I did the following:
- Created a project using the
Screen Saver
template - Removed the Objective-C files and added a Swift file (
SolidLightWorksView.swift
) as per How to Make a Custom Screensaver for Mac OS X - Added a new target based on the
Cross-platform
template choosing Swift and Metal- I would have used the
App
template but I am running XCode 11.3 on macOS 10.14.4 and I found that if I created an App with a User Interface of type SwiftUI, I could not run it because it required macOS 10.15.
- I would have used the
- Hacked away at
SolidLightWorksView.swift
based onGameViewController.swift
- Started the process of debugging to figure out why the screensaver wasn't working and how to fix it
In order to debug my screensaver, I did something horrible but effective - I used NSAlert
as a logging mechanism e.g.:
let alert = NSAlert()
alert.informativeText = "Unable to load texture. Error info: \(error)"
alert.addButton(withTitle: "OK")
alert.runModal()
This allowed me to pinpoint where the problem was occurring. The call to device.makeDefaultLibrary()
was returning nil
.
I figured out this was a bundling issue - the main bundle was for /Applications/System Preferences.app
rather than my screensaver's bundle. I fixed this by explicltly loading my bundle using init(for:)
.
let bundle = Bundle(for: SolidLightWorksView.self)
I have only just started this project. At the moment, all I have done is take the code generated by the Cross-platform
Swift/Metal template and get it working as a screensaver. Hence, everything else is still to do.
Draw screenDraw axesPort three-line-2d to MetalDraw a static waveDraw a travelling waveImplement first of the forms (without membrane): Doubling BackDraw the remaining vocabulary: ellipse, line, circle waveImplement the remaining forms (without membrane)Periodically switch between formsPort the membrane geometry and shader to Metal- Implement first of the forms (with membrane): Doubling Back
- Implement the remaining forms (with membrane)
- Randomly switch between camera positions
Implement camera lookat- Implement rotating camera
Add a screensaver configuration sheet with option to show forms without membranes
Here are a few notes regarding the maths behind the forms.
Anthony McCall talks about a vocabulary of forms (see Anthony McCall: Notebooks and Conversations pp. 171-172):
- the Circle
- the Straight Line
- the Travelling Wave
- the Wipe
- the Circle Wave
Two travelling waves travelling in opposite directions - one of them to the right and the other upwards. I used the following reference for details of an equation for a travelling wave:
Two circle waves. I found the following blog article that provides more details including equations:
Ellipses, straight lines and travelling waves. The rotating straight line needs to be clipped to a rectangle. I used the following reference to do this:
I think this is a travelling wave along the radius of an ellipse which rotates clockwise around the ellipse. The tricky part was figuring out the point of intersection between the rotating travelling wave and the path of the ellipse. I used the following references to achieve this: