【问题标题】:metal compute shader: setting alpha to zero does not yield complete transparency金属计算着色器:将 alpha 设置为零不会产生完全透明
【发布时间】:2016-09-12 02:27:01
【问题描述】:

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

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 的红色背景的结果:

所以哥伦布的回答对我有用,这里是我的色键过滤器的代码:

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

【问题讨论】:

    标签: ios swift shader gpu metal


    【解决方案1】:

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

    1. 将图层从预乘 Alpha 合成更改为使用非预乘 Alpha 合成。
    2. 更改计算内核以执行 alpha 预乘。

    要执行 #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);
    

    【讨论】:

    • 如果我将每个像素的 alpha 硬编码为 0,我不明白为什么我应该看到任何视频。它不应该是完全透明的吗?我的理解是,将图像预乘 alpha 会使那些 alpha 不是 1.0 的像素变暗。当我将每个像素的 alpha 值强制为零时,我看不出这会如何影响透明度。
    • 这个网站解释了预乘混合的数学和推理:blogs.msdn.microsoft.com/shawnhar/2009/11/06/…
    • 好的,所以我的下一个问题是:有没有办法改变金属计算管道的 alpha 预乘状态?我在这里看到了一个为渲染管道执行此操作的示例:metalbyexample.com/translucency-and-transparency>,但不是使用计算管道执行此操作的示例。
    • 我认为建议的技术仍然适用。问题的症结在于,您的颜色数据必须采用预乘 alpha 格式才能由 Core Animation 正确合成,因此在管道结束时(无论是计算着色器写入可绘制对象,还是返回颜色来自片段函数),您应该将 RGB 乘以 alpha。
    猜你喜欢
    • 2015-02-03
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 2012-04-22
    • 2014-02-06
    • 1970-01-01
    • 2013-02-23
    • 1970-01-01
    相关资源
    最近更新 更多