使用带有Scene Kit Shader修改器的Metal的自定义变量声明 [英] Custom Variable Declarations Using Metal With Scene Kit Shader Modifiers

查看:74
本文介绍了使用带有Scene Kit Shader修改器的Metal的自定义变量声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难将制服传递给Scene Kit的着色器修改器.在使用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"

但是当我将其更改为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"

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

 // The uniform "twistFactor" must be assigned a value.
 torus.setValue(1.0, forKey: "twistFactor")

我想我可以切换回使用OpenGL来解决这个问题,但是Apple着色器修改器文档中的前几行很难上班,这让人感到沮丧.

// For Metal, a pragma directive and one custom variable on each line:
#pragma arguments
float intensity;

我看到各种各样的帖子围绕着相同的基本问题在不同的论坛上徘徊,如果他们能够为此提供更清晰的文档,那就太好了.

我收到以下错误消息:

program_source:2566:50:错误:使用未声明的标识符"twistFactor"

在此先感谢您的帮助!

解决方案

您可以使用#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"
 

I am having difficulty passing uniforms to Scene Kit's shader modifiers. This seems to work fine when using OpenGL but not when using Metal.

I have used SCNProgram successfully before but wanted to take advantage of SceneKit's tessellator instead of setting up compute shaders for tessellation.

But I want to use the code I have already written in Metal rather than using OpenGL.

There is unfortunately not a great deal of examples of how to do this. This Swift Playground illustrates how to do this nicely in 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"

But when I change it to Metal it doesn't work:

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"

This is how I'm providing the value, using key-value coding:

 // The uniform "twistFactor" must be assigned a value.
 torus.setValue(1.0, forKey: "twistFactor")

I guess I could just switch back to using OpenGL to get round this but it's a little frustrating that the first couple of lines from Apple's shader modifier documentation are so tricky to get working.

// For Metal, a pragma directive and one custom variable on each line:
#pragma arguments
float intensity;

I've seen various posts floating around different forums with the same basic issue, it'd be great if they could provide clearer documentation for this.

I get the following error message:

program_source:2566:50: error: use of undeclared identifier 'twistFactor'

Thanks in advance for any help!

解决方案

You can use the #pragma declaration marker to help SceneKit differentiate the shader modifier arguments from local functions:

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"

这篇关于使用带有Scene Kit Shader修改器的Metal的自定义变量声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆