金属计算着色器:将alpha设置为零不会产生完全透明度

时间:2016-09-12 02:27:02

标签: ios swift shader gpu metal

我正在尝试修改这个人的代码:

https://github.com/FlexMonkey/MetalVideoCapture

从iphone / ipad相机中获取视频,并实时过滤一些Metal GPU计算内核。

我想改变Metal代码来做一些简单的色度键控,我们在视频中使某种颜色透明(即对于那种颜色alpha = 0)。

问题是,即使你在金属计算内核的末尾强制alpha为零,金属计算内核产生的视频输出也永远不会达到完全透明:

outTexture.write(float4(float3(rgb), 0.0), gid);

结果视频只是部分透明。

请注意,我正在设置 layer.opaque = false 对于正在进行渲染的MTKView。

有谁知道为什么会这样?

这是结果,alpha = 0,UIView为红色背景:

所以Columbo的回答对我有用,这里是我的chromakey过滤器的代码:

kernel void ChromaKey(texture2d<float, access::read> yTexture [[texture(0)]],
                                   texture2d<float, access::read> cbcrTexture [[texture(1)]],
                                   texture2d<float, access::write> outTexture [[texture(2)]],
                                   uint2 gid [[thread_position_in_grid]])
{
    float2 green = float2(54.0/255.0, 34.0/255.0);
    float threshold = 0.05;
    float3 colorOffset = float3(-(16.0/255.0), -0.5, -0.5);
    float3x3 colorMatrix = float3x3(
                                    float3(1.164,  1.164, 1.164),
                                    float3(0.000, -0.392, 2.017),
                                    float3(1.596, -0.813, 0.000)
                                    );

    uint2 cbcrCoordinates = uint2(gid.x / 2, gid.y / 2);
    float y = yTexture.read(gid).r;
    float2 cbcr = cbcrTexture.read(cbcrCoordinates).rg;
    float alpha = smoothstep(threshold, threshold + 0.5, distance(cbcr, green));
    float3 ycbcr = float3(y, cbcr);
    float4 rgba = alpha * float4(colorMatrix * (ycbcr + colorOffset), 1.0);
    outTexture.write(rgba, gid);
}

1 个答案:

答案 0 :(得分:2)

我的猜测是你的图层使用预乘alpha(mentioned here)。如果是这种情况,那么您有两个简单的解决方案:

  1. 将图层从预乘alpha合成更改为使用非预乘alpha合成。
  2. 更改计算内核以执行alpha预乘。
  3. 要做#2你会改变这样的事情:

    float alpha = <something_or_other>;
    float3 rgb = colorMatrix * (ycbcr + colorOffset);
    outTexture.write(float4(float3(rgb), alpha), gid);
    

    对于这样的事情:

    float alpha = <something_or_other>;
    float3 rgb = (colorMatrix * (ycbcr + colorOffset)) * alpha;
    outTexture.write(float4(float3(rgb), alpha), gid);