在 SceneKit 中使用 Metal 着色器

And*_*ard 4 shader scenekit swift metal ios9

我想使用Metal着色器将卡通/单元着色应用于场景中使用的材质。我尝试实现的着色器是 AppleAAPLCelShaderMetalShaderShowcase中找到的自己的着色器。我对实现着色器有点陌生,SceneKit所以我可能会做完全错误的事情。

根据我在文档中的理解,从 iOS 9 和 Xcode 7 开始,aMetal或 GL 着色器可用于修改SceneKit渲染。文档表明,这与 GL 着色器的完成方式相同。

我的方法是尝试获取文件的路径,然后将其加载到一个字符串中,以 [String: String] 字典的形式在属性中.metal使用,就像使用 GL 着色器一样(尽管我还没有SCNMaterial shaderModifiers使其正常工作)。

我的代码是:

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
})
Run Code Online (Sandbox Code Playgroud)

这是在一个测试场景上运行的,其中有一个从.scn文件加载的盒子几何体。文件加载工作正常,所以这不是问题。

该错误来自我尝试查找路径的第二行,它给了我“在展开可选值时发现零”,这是强制展开所预期的,除了它尝试加载的文件是最重要的事实之外。当然,在捆绑包中,相同的代码可以很好地处理其他文件类型,但不能处理其他文件.metal类型。

我的处理方式完全错误吗?我不明白为什么它不会访问该文件,除了我滥用金属文件的问题。

是否有更简单或更好的方法来实现单元格阴影并最终在边缘上实现粗体轮廓?

小智 5

AAPLCelShader.metal是一个完整的vertex/ rastex /fragment 实现,这与 ShaderModifiers 不同:将被注入到已经完成的着色器中的源代码。

\n\n

相反,您可以使用 AAPLCelShader.metal 中的顶点和片段函数创建SCNProgram 。与 GLSL 相比,Metal 的优点在于您可以使用Metal 函数的名称,而不是源代码字符串,这更容易使用,并且可以在运行时之前编译函数,而 GLSL 则不然支持。(这仍然没有达到应有的效果,Swift 会将 Metal 函数识别为正确类型、可重构、命名空间闭包。)当然,虽然 GLSL SCNPrograms 将转换为 Metal,但对于兼容的硬件,Metal SCNPrograms 不会被翻译为过时的设备。

\n\n

至于从 SceneKit 到 rastex 的映射(错误命名的ColorInOut)成员的映射:

\n\n
float4 position [[position]];\nfloat shine;\nfloat3 normal_cameraspace;\nfloat3 eye_direction_cameraspace;\nfloat3 light_direction_cameraspace;\n
Run Code Online (Sandbox Code Playgroud)\n\n

\xe2\x80\xa6 不幸的是,我还没有给你答案。

\n