本文介绍了将Metal Texture2d_Array传递给SceneKit着色器修改器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为SCNMaterial(使用SCNShaderModifierEntryPointSurface)创建着色器修改器,并将Metal texture2d_array作为自定义输入传递.为此,我尝试使用类型为SCNMaterialProperty的键值编码设置参数.从SCNMaterialProperty属性contents上的SceneKit手册中:

I want to create shader modifier for SCNMaterial (with SCNShaderModifierEntryPointSurface) and pass Metal texture2d_array as custom input. To achieve that I try to use key-value coding setting parameter of type SCNMaterialProperty. From SceneKit manual on SCNMaterialProperty property contents:

您可以使用以下任意一种类型为此属性设置一个值:

You can set a value for this property using any of the following types:

  • ...
  • 纹理(SKTexture,MDLTexture, MTLTexture 或GLKTextureInfo)
  • ...
  • ...
  • A texture (SKTexture, MDLTexture, MTLTexture, or GLKTextureInfo)
  • ...

所以,我构造了MTLTexture:

  • 使用类型MTLTextureType2DArray
  • 创建MTLTextureDescriptor
  • 使用MTLDevice的newTextureWithDescriptor创建MTLTexture:
  • 使用[texture replaceRegion:mipmapLevel:withBytes:bytesPerRow:];
  • 用数据填充纹理
  • Create MTLTextureDescriptor with type MTLTextureType2DArray
  • Create MTLTexture with MTLDevice's newTextureWithDescriptor:
  • Fill texture with data using [texture replaceRegion:mipmapLevel:withBytes:bytesPerRow:];

然后创建SCNMaterialProperty,将创建​​的MTLTexture分配给其contents并将其传递给材料:

Then I create SCNMaterialProperty, assign my created MTLTexture to its contents and pass it to material:

[material setValue:aTexture forKey:@"tex"];

然后我附加此着色器修改器:

Then I attach this shader modifier:

#pragma arguments
texture2d_array tex;

#pragma body
// do sampling from 1st slice
constexpr sampler smp(coord::normalized, address::repeat, filter::nearest);
_surface.diffuse = tex.sample(smp, _surface.diffuseTexcoord, 0);

然后我得到:

回溯:

我也尝试直接使用[material setValue:aTexture forKey:@"tex"];传递纹理,但是随后出现错误:

I also tried to pass texture directly with [material setValue:aTexture forKey:@"tex"]; But then I'm getting error:

/Library/Caches/com.apple.xbs/Sources/Metal/Metal-56.6/ToolsLayers/Debug/MTLDebugRenderCommandEncoder.mm:1600:
failed assertion `textureType mismatch at texture binding at index 8 for tex[0].'

此外,我尝试在SCNMaterialProperty内容中传递MTLTexture2D,但C3DImageGetImage类型的异常失败.直接通过[material setValue:forKey]传递MTLTexture2D会导致所有白色都被采样-错误的纹理被采样.

Also, I tried passing MTLTexture2D in SCNMaterialProperty contents and It fails with exception in C3DImageGetImage type. Passing MTLTexture2D directly via [material setValue:forKey] results in everything white - wrong texture being sampled.

在分析捕获GPU框架"输出时,我发现在绘制调用期间绑定了错误的纹理.

When analysing 'Capture GPU Frame' output, I see that wrong texture bound during draw call.

也许有人设法将texture2d_array传递给shader修改器?有可能吗?我可以使用金属命令缓冲区手动绑定,但是如何基于每种材料访问它呢?

Maybe someone managed to pass texture2d_array to shader modifier? Is it possible at all? I could use metal command buffer to bind manually, but how to get access to it on per-material basis?

谢谢大家.

推荐答案

        #include <metal_stdlib>
        #include <metal_texture>
        using namespace metal;
        #pragma arguments
        texture2d<float> mask;

        #pragma body
        constexpr sampler quadSampler(address::clamp_to_edge, filter::linear);

        _surface.diffuse = mask.sample(quadSampler, _surface.diffuseTexcoord);

然后迅速

let mask = SCNMaterialProperty(contents: MDLTexture(named: "gameFrame.png")!)
doorFrame.geometry?.firstMaterial?.setValue(mask, forKey: "mask")

这篇关于将Metal Texture2d_Array传递给SceneKit着色器修改器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 00:57