使用带有Scene Kit Shader修改器的Metal的自定义变量声明 [英] Custom Variable Declarations Using Metal With Scene Kit Shader Modifiers
问题描述
我很难将制服传递给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屋!