I'd like to use a Metal
shader to apply a toon/cell shading to materials used in the scene. The shader I'm trying to implement is Apple's own AAPLCelShader
found in the MetalShaderShowcase. I'm a little new to implementing shaders in SceneKit
so I could be doing everything completely wrong.
From what I understand in the documentation a Metal
or GL shader can be used to modify SceneKit
rendering as of iOS 9 and Xcode 7. The documentation suggests that this is done in the same way as GL shaders.
My method is to try and get the path for the .metal
file and then load it into a string to be used in the SCNMaterial
shaderModifiers
property in the form of a [String: String] dictionary, as you would with a GL shader (though I've yet to get that working properly).
My code is:
var shaders = [String: String]()
let path = NSBundle.mainBundle().pathForResource("AAPLCelShader", ofType: "metal")!
do{
let celShader = try String(contentsOfFile: path, encoding: NSUTF8StringEncoding)
shaders[SCNShaderModifierEntryPointLightingModel] = celShader
}catch let error as NSError{
error.description
}
scene.rootNode.enumerateChildNodesUsingBlock({ (node, stop) -> Void in
node.geometry?.firstMaterial?.shaderModifiers = shaders
})
This is being run on a test scene with a single box geometry in it that is being loaded from a .scn
file. The file loading works fine so that's not an issue.
The error comes from the second line where I try and find the path, it gives me the "found nil while unwrapping optional value" which would be expected with the force unwrapping, other than the fact that the file it is trying to load is most certainly in the bundle and the same code works fine with other file types, just not .metal
ones.
Am I going about this completely the wrong way? I can't understand why it won't access the file other than an issue with me misusing the metal file.
Is there a simpler or better way to implement cell shading and eventually a bold outline on edges?