如何将非纹理数据传递到SCNTechnique Metal着色器 [英] How to pass non-texture data to SCNTechnique Metal shaders

查看:81
本文介绍了如何将非纹理数据传递到SCNTechnique Metal着色器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以将类型为sampler2D的自定义参数传递给SCNTechniqueMetal 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屋!

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