【问题标题】:How to make metal shaders not clamp texture writes to (0-1) range?如何使金属着色器不将纹理写入(0-1)范围?
【发布时间】:2018-09-17 14:53:00
【问题描述】:

这个金属着色器的输入是来自 iOS 相机的 bgra 图像(在 0-1 范围内),输出应该是 rgba 缩放到 0-255 范围(注意内核中的 x256)。但我不明白为什么内核的输出似乎被限制在 0-1 范围内。 Metal 会在它们的纹理写入中烘烤一个夹子吗?还是我错过了什么?

kernel void bgraScaleKernel(
        texture2d<float, access::read> inputImage [[texture(0)]],
        texture2d<float, access::write> outputImage [[texture(1)]],
        const device int *starting [[ buffer(0) ]],
        uint2 gid [[thread_position_in_grid]])
{
    uint i = gid.x+starting[0]; 
    uint j = gid.y+starting[1]; 
    float4 pixel_new = (inputImage.read(uint2 (i, j)).bgra)*256;
    outputImage.write(pixel_new, (uint2)(i,j));
};

我有一堆其他过滤器层在此之后应用,它们假设 rgba (0-255) 浮点值(它从 OpenCL 移植并更改它也需要更改 Androi、Windows 和 Mac 版本)。所以我需要金属层的输出在 0-255 范围内。

【问题讨论】:

  • 你绑定到texture(1)的纹理的像素格式是什么?
  • 是的,肯。这就是问题所在。我正在使用 MTLPixelFormatRGBA8Unorm。 MTLPixelFormatRGBA32Float 不做那种钳制。我不明白为什么他们会限制写入值。似乎有点控制欲。这不应该取决于程序员吗?我的意思是我必须将所有东西都切换到 RGBA32Float,除了最后一层 - 因为当然纹理到图像功能只需要 unorms。所以我将一个 isFinalLayer 标志一直传递到代码的纹理构造部分。对我来说似乎没有必要,但可能是因为我更习惯于 OCL。
  • 这就是像素格式中的“Unorm”所代表的意思。
  • 由于您正在编写自定义过滤器,我想您已经找到了我所坚持的成功。我正在尝试将一个简单的晕影滤镜应用于使用金属的实时摄像机馈送。结果非常缓慢且滞后,如果您能告诉我缺少什么,请检查一下:stackoverflow.com/q/53898780/1364053

标签: ios metal


【解决方案1】:

8Unorm 像素格式使用 [0, 255] 范围内的整数表示内存中的值,但在着色器中,这些值以 [0.0, 1.0] 范围内的浮点数表示。

要获得您显然想要的结果,您只需将您从inputImage 读取的浮点值直接分配给outputImage,而无需乘以256(或255)。金属为您做到这一点。通过自己做,您使大多数值大于 1.0,因此 Metal 在自己转换为 8Unorm 之前将它们钳制到 1.0。

【讨论】:

  • 既然您正在编写自定义过滤器,我想您已经找到了我所坚持的成功。我正在尝试将一个简单的晕影滤镜应用于使用金属的实时摄像机馈送。结果非常缓慢且滞后,如果您能告诉我缺少什么,请检查一下:stackoverflow.com/q/53898780/1364053
猜你喜欢
  • 1970-01-01
  • 2018-12-02
  • 2018-09-24
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-16
  • 1970-01-01
相关资源
最近更新 更多