具有两个透明纹理的Alpha混合无法正常工作

问题描述 投票:0回答:1

我有目标纹理:enter image description here

这里,除了红色部分,整个纹理将是透明的(alpha = 0)。红色的alpha值为0.5。我使用矩形平面来呈现此纹理。

然后我有此源纹理。它也是带有黑色部分的透明纹理。黑色的alpha值为0.5。我使用了另一个矩形平面来呈现此纹理,然后将MTLRenderPipelineDescriptor混合更改为

pipelineDescriptor.colorAttachments[0].isBlendingEnabled = true
pipelineDescriptor.colorAttachments[0].rgbBlendOperation = .add
pipelineDescriptor.colorAttachments[0].alphaBlendOperation = .add
pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = .one
pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = .one
pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = .oneMinusSourceAlpha
pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = .oneMinusSourceAlpha

这里的混合在两个纹理之间正常工作。

enter image description here

然后,我尝试将这两个纹理合并为一个目标纹理。使用MTLComputeCommandEncoder。我的内核功能:

kernel void compute(
                    texture2d<float, access::read_write> des [[texture(0)]],
                    texture2d<float, access::read> src [[texture(1)]],
                    uint2 gid [[thread_position_in_grid]])
{
    float4 srcColor = src.read(gid);
    float4 desColor = des.read(gid);
    float srcAlpha = srcColor.a;

    float4 outColor = srcColor  + desColor * (1 - srcAlpha);

    des.write(outColor, gid);
}

但是混合后的颜色将与以前不同。混合颜色比以前的颜色浅。enter image description here

如何在内核函数中正确混合两个透明纹理?我的解决方案出了什么问题?

ios metal alphablending
1个回答
2
投票

我认为您正在使用预乘alpha ...

改为尝试此方法(不是预乘alpha):

float4 srcColor = src.read(gid);
float4 desColor = des.read(gid);

float4 outColor;
outColor.a = srcColor.a + desColor.a * (1f - srcColor.a);
if (outColor.a == 0f) {
  outColor.r = 0f;
  outColor.g = 0f;
  outColor.b = 0f;
} else {
  outColor.r = (srcColor.r * srcColor.a + desColor.r * desColor.a * (1f - srcColor.a)) / outColor.a;
  outColor.g = (srcColor.g * srcColor.a + desColor.g * desColor.a * (1f - srcColor.a)) / outColor.a;
  outColor.b = (srcColor.b * srcColor.a + desColor.b * desColor.a * (1f - srcColor.a)) / outColor.a;
}
© www.soinside.com 2019 - 2024. All rights reserved.