如何将非纹理数据传递到SCNTechnique Metal着色器 [英] How to pass non-texture data to SCNTechnique Metal shaders
问题描述
我可以将类型为sampler2D
的自定义参数传递给SCNTechnique
的Metal fragment function
,并且我可以进行第二次传递:
I can a pass custom parameter of type sampler2D
to the Metal fragment function
of an SCNTechnique
and I have a working 2nd pass:
PList:
<key>inputs</key>
<dict>
<key>imageFromPass1</key>
<string>COLOR</string>
<key>myCustomImage</key>
<string>myCustomImage_sym</string>
</dict>
...
<key>symbols</key>
<dict>
<key>myCustomImage_sym</key>
<dict>
<key>type</key>
<string>sampler2D</string>
</dict>
</dict>
相关的Obj-C代码:
Relevant Obj-C code:
[technique setValue: UIImagePNGRepresentation(myCustomTexture) forKey:@"myCustomImage_sym"];
金属功能参数:
fragment half4 myFS(out_vertex_t vert [[stage_in]],
texture2d<float, access::sample> imageFromPass1 [[texture(0)]],
texture2d<float, access::sample> myCustomImage [[texture(1)]],
constant SCNSceneBuffer& scn_frame [[buffer(0)]]) { ...
我在着色器功能中访问并使用所有这些输入.可行!
I access and use all these inputs in the shader function. It Works!
但是,当我添加类型为float
...
However, when I add another custom parameter of type float
...
<key>blob_pos</key>
<string>blob_pos_sym</string>
...
<key>blob_pos_sym</key>
<dict>
<key>type</key>
<string>float</string>
</dict>
[_sceneView.technique setValue:[NSNumber numberWithFloat:0.5f] forKey:@"blob_pos_sym"];
constant float& blob_pos [[buffer(2)]]
...传递的值永远不会到达着色器功能.
... the passed values never reach the shader function.
- 使用最多6个不同的buffer(N)值
- 在顶点函数中具有自定义参数
- 输入vec3和float3而不是float
- 将我的浮点数编码为NSData的不同方法
-
将浮点数包装在结构中
- using different buffer(N) values up to 6
- having the custom parameter in the vertex function
- type vec3 and float3 instead of type float
- different means of encoding my float to NSData
wrapping my float in a struct
[technique setValue:[NSValue valueWithSCNVector3: SCNVector3Make(0.5, 0.5, 0.5)] forKey:@"blob_pos_"];
SCNVector3 xx = SCNVector3Make(0.5, 0.5, 0.5);
[technique setValue:[NSData dataWithBytes:&xx length:sizeof(xx)] forKey:@"blob_pos_"];
[technique setValue:[NSData dataWithBytesNoCopy:&xx length:sizeof(xx)] forKey:@"blob_pos_"];
simd_float3 x = simd_make_float3(0.5, 0.5, 0.5);
[technique setValue:[NSData dataWithBytes:&x length:sizeof(x)] forKey:@"blob_pos_"];
float y = 0.5;
[technique setValue:[NSData dataWithBytes:&y length:sizeof(y)] forKey:@"blob_pos_"];
struct MyStruct {
float x;
};
struct MyStruct myStruct = {
0.5
};
[technique setValue:[NSValue valueWithBytes:&myStruct objCType:@encode(struct MyStruct)] forKey:@"blob_pos_"];
[technique setObject:[NSValue valueWithBytes:&myStruct objCType:@encode(struct MyStruct)] forKeyedSubscript:@"blob_pos_"];
...这一切都失败了.
... and it all failed.
然后我查看了 handleBindingOfSymbol:usingBlock: ...但这只是GLSL.
Then I looked at handleBindingOfSymbol:usingBlock: ... but it is GLSL only.
我发现它是Metal的对应版本, handleBindingOfBufferNamed:frequency:usingBlock: ...在SCNTechnique中不可用.
I found it's Metal counterpart, handleBindingOfBufferNamed:frequency:usingBlock: ... which is not available in SCNTechnique.
我用Google搜索了 SCN技术金属 ...并实现了 all 项目仅使用sampler2D参数.
I Googled SCNTechnique Metal ... and realized all of the projects used sampler2D parameters only.
最后,我了解到这不是新事物,而是调试开发人员多年了.
Finally I learned that this isn't new but bugs developers for years.
在我将此浮点编码为纹理之前,请让我知道缺少的部分,以使其按预期的方式工作.
Before I go and encode this float in a texture, let me know the missing bit to make it work the way intended.
推荐答案
您必须使用结构来包装您的输入符号,并确保使用[SCNTechnique setObject:forKeyedSubscript:]
将符号值传递给您的技术. setObject:forKeyedSubscript:的文档中提到了Metal并没有解释如何在Metal函数中接收值,这是不幸的.
You have to use a struct to wrap your input symbols and be sure to use [SCNTechnique setObject:forKeyedSubscript:]
to pass in your symbol values to your technique. The documentation for setObject:forKeyedSubscript: mentions Metal however it doesn't explain how to receive the value in a Metal function, which is unfortunate.
使用您的示例:
技术定义:
"inputs": [
"imageFromPass1": "COLOR",
"myCustomImage": "myCustomImage_sym",
"blob_pos": "blob_pos_sym",
],
...
"symbols": [
"myCustomImage_sym": ["type": "sampler2D"],
"blob_pos_sym": ["type": "float"]
]
Obj-C:
[_sceneView.technique setObject:[NSNumber numberWithFloat:0.5f] forKeyedSubscript:@"blob_pos_sym"];
金属:
typedef struct {
float blob_pos; // Must be spelled exactly the same as in inputs dictionary.
} Inputs;
fragment half4 myFS(out_vertex_t vert [[stage_in]],
texture2d<float, access::sample> imageFromPass1 [[texture(0)]],
texture2d<float, access::sample> myCustomImage [[texture(1)]],
constant Inputs& myInputs [[buffer(0)]]) {
float blob_pos = myInputs.blob_pos;
...
这篇关于如何将非纹理数据传递到SCNTechnique Metal着色器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!