使用带有场景套件着色器修改器的 Metal 自定义变量声明

Eoi*_*Roe 2 shader modifier scenekit metal

我在将制服传递给场景套件的着色器修改器时遇到困难。这在使用 OpenGL 时似乎工作正常,但在使用 Metal 时则不然。

我之前曾成功使用过 SCNProgram,但想利用 SceneKit 的曲面细分器,而不是为曲面细分设置计算着色器。

但我想使用我已经用 Metal 编写的代码,而不是使用 OpenGL。

不幸的是,关于如何做到这一点的例子并不多。这个 Swift Playground 演示了如何在 OpenGL 中很好地做到这一点。

https://github.com/markpmlim/Twister/blob/master/Twister.playground/Contents.swift

//Geometry - Metal will translate the OpenGL code.
let geometryShaderModifier =
"uniform float twistFactor;\n" +
"mat4 rotationAroundX(float angle) {\n" +
"return mat4(1.0,    0.0,         0.0,        0.0,\n" +
"            0.0,    cos(angle), -sin(angle), 0.0,\n" +
"            0.0,    sin(angle),  cos(angle), 0.0,\n" +
"            0.0,    0.0,         0.0,        1.0);\n" +
"}\n" +
"#pragma body\n" +
"float rotationAngle = _geometry.position.x * twistFactor;\n" +
"mat4 rotationMatrix = rotationAroundX(rotationAngle);\n" +
"_geometry.position *= rotationMatrix;\n" +
"vec4 twistedNormal = vec4(_geometry.normal, 1.0) * rotationMatrix;\n" +
"_geometry.normal   = twistedNormal.xyz;\n"
Run Code Online (Sandbox Code Playgroud)

但是当我将其更改为 Metal 时,它不起作用:

let geometryShaderModifier =
"#pragma arguments \n" +
"float twistFactor;\n" +
"float4x4 rotationAroundX(float angle) {\n" +
"return float4x4(1.0,    0.0,         0.0,        0.0,\n" +
"                0.0,    cos(angle), -sin(angle), 0.0,\n" +
"                0.0,    sin(angle),  cos(angle), 0.0,\n" +
"                0.0,    0.0,         0.0,        1.0);\n" +
"}\n" +
"#pragma body\n" +
"float rotationAngle = _geometry.position.x * twistFactor;\n" +
"float4x4 rotationMatrix = rotationAroundX(rotationAngle);\n" +
"_geometry.position *= rotationMatrix;\n" +
"float4 twistedNormal = float4(_geometry.normal, 1.0) * rotationMatrix;\n" +
"_geometry.normal   = twistedNormal.xyz;\n"
Run Code Online (Sandbox Code Playgroud)

这就是我使用键值编码提供值的方式:

 // The uniform "twistFactor" must be assigned a value.
 torus.setValue(1.0, forKey: "twistFactor")
Run Code Online (Sandbox Code Playgroud)

我想我可以切换回使用 OpenGL 来解决这个问题,但有点令人沮丧的是,Apple 着色器修改器文档的前几行很难工作。

// For Metal, a pragma directive and one custom variable on each line:
#pragma arguments
float intensity;
Run Code Online (Sandbox Code Playgroud)

我看到不同论坛上流传着许多具有相同基本问题的帖子,如果他们能够为此提供更清晰的文档,那就太好了。

我收到以下错误消息:

程序源:2566:50:错误:使用未声明的标识符“twistFactor”

预先感谢您的任何帮助!

mnu*_*ges 7

您可以使用#pragma declaration标记来帮助 SceneKit 区分着色器修改器参数和本地函数:

let geometryShaderModifier =
    "#pragma arguments\n" +
     "float twistFactor;\n" +
     "#pragma declaration\n" + // HERE
     "float4x4 rotationAroundX(float angle) {\n" +
     "return float4x4(1.0,    0.0,         0.0,        0.0,\n" +
     "                0.0,    cos(angle), -sin(angle), 0.0,\n" +
     "                0.0,    sin(angle),  cos(angle), 0.0,\n" +
     "                0.0,    0.0,         0.0,        1.0);\n" +
     "}\n" +
     "#pragma body\n" +
     "float rotationAngle = _geometry.position.x * twistFactor;\n" +
     "float4x4 rotationMatrix = rotationAroundX(rotationAngle);\n" +
     "_geometry.position *= rotationMatrix;\n" +
     "float4 twistedNormal = float4(_geometry.normal, 1.0) * rotationMatrix;\n" +
     "_geometry.normal   = twistedNormal.xyz;\n"
Run Code Online (Sandbox Code Playgroud)