我想使用Metal着色器将toon / cell着色应用于场景中使用的材质.我试图实现的着色器是在 MetalShaderShowcase中找到的Apple自己的AAPLCelShader.我对在SceneKit中实现着色器有点新意,所以我可能做的
根据我在文档中的理解,可以使用Metal或GL着色器来修改iOS 9和Xcode 7中的SceneKit渲染.文档建议这与GL着色器一样.
我的方法是尝试获取.metal文件的路径,然后将其加载到字符串中,以[String:String]字典的形式在SCNMaterial shaderModifiers属性中使用,就像使用GL着色器一样(尽管我还没有让它正常工作).
我的代码是:
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 })
这是在测试场景上运行的,其中包含从.scn文件加载的单个框几何体.文件加载工作正常,这不是一个问题.
错误来自我尝试找到路径的第二行,它给了我“在展开可选值时找到nil”,这可以通过强制解包来预期,除了它试图加载的文件最多的事实当然在捆绑包中,相同的代码与其他文件类型一起正常工作,而不是.metal.
我完全错误地采取了这种方式吗?我无法理解为什么它不会访问该文件,而不是我滥用金属文件的问题.
是否有更简单或更好的方法来实现单元格着色并最终在边缘上使用粗体轮廓?
AAPLCelShader.metal是一个完整的顶点/ rastex /片段实现,它不是shaderModifiers的源代码:将被注入已完成着色器的源代码.相反,您可以使用AAPLCelShader.metal中的顶点和片段函数创建SCNProgram.与GLSL相比,Metal的优点在于您可以使用names of Metal functions而不是源代码字符串,这更容易使用,并且导致在运行时编译函数,而GLSL不支持这些函数. (这仍然不如它应该是那样好,Swift会将Metal函数识别为正确类型,可重构,命名空间的闭包.)当然,虽然GLSL SCNPrograms将转换为Metal,但对于兼容硬件,Metal SCNPrograms不会被翻译为过时的设备.
至于从SceneKit到rastex(错误命名的ColorInOut)成员的映射:
float4 position [[position]]; float shine; float3 normal_cameraspace; float3 eye_direction_cameraspace; float3 light_direction_cameraspace;
……遗憾的是,我还没有找到答案.