简体   繁体   English

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

[英]metal compute shader: setting alpha to zero does not yield complete transparency

I am trying to modify this guy's code: 我正在尝试修改此人的代码:

https://github.com/FlexMonkey/MetalVideoCapture https://github.com/FlexMonkey/MetalVideoCapture

which takes in video from the iphone / ipad camera and filters it with some Metal GPU compute kernels in real time. 它可以从iphone / ipad摄像头获取视频,并使用一些Metal GPU计算内核对其进行实时过滤。

I would like to alter the Metal code to do some simple chroma keying, where we make a certain color in the video transparent (ie for that color alpha = 0). 我想更改“金属代码”以执行一些简单的色度键控,使视频中的某种颜色透明(即该颜色的alpha = 0)。

The problem is that the resulting video output from the metal compute kernel never reaches full transparency, even if you force alpha to zero at the end of the metal compute kernel: 问题是,即使您在金属计算内核的末尾将alpha强制设置为零,金属计算内核产生的视频输出也永远不会达到完全透明:

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

The resultant video is only partially transparent. 生成的视频仅部分透明。

Note that I am setting layer.opaque = false for the MTKView where the rendering is being done. 请注意,我正在为渲染完成的MTKView设置layer.opaque = false。

Does anyone know why this might be happening? 有谁知道为什么会这样?

This is the result with alpha = 0 and a red background for the UIView: 这是alpha = 0且UIView红色背景的结果:

So Columbo's answer worked for me and here is the code for my chromakey filter: 因此,哥伦布的答案对我有用,这是我的抠像过滤器的代码:

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);
}

My guess would be that your layer is using premultiplied alpha ( mentioned here ). 我的猜测是您的图层使用的是预乘alpha( 此处提到 )。 If that's the case, then you have two easy solutions: 如果是这样,那么您有两个简单的解决方案:

  1. Change the layer from premultiplied alpha compositing to use non-premultiplied alpha compositing. 将图层从预乘alpha合成更改为使用非预乘alpha合成。
  2. Change the compute kernels to perform the alpha premultiplication. 更改计算内核以执行alpha预乘。

To do #2 you would change something like this: 要执行#2,您将更改以下内容:

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

To something like this: 对于这样的事情:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM