透明 MTKView 中的 alpha 混合参数是否正确?

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

我最近尝试创建一个透明的

MTKView
,我可以在其中绘制一些几何图形,包括部分透明的几何图形,并将结果与该
MTKView
后面的任何视图正确合成。我在尝试实现此目标时遇到了两个问题:

  1. 在不透明区域上绘制部分透明的三角形会使该区域不再不透明。
  2. 部分透明像素的颜色未与背景正确混合,包括多重采样中的抗锯齿像素。

我创建了一个测试用例,它演示了“至少”第一个问题,也可能是第二个问题。其中,混合设置为: colorAttachmentDescriptor.isBlendingEnabled = true colorAttachmentDescriptor.pixelFormat = .bgra8Unorm_srgb colorAttachmentDescriptor.rgbBlendOperation = .add colorAttachmentDescriptor.alphaBlendOperation = .add colorAttachmentDescriptor.sourceRGBBlendFactor = .sourceAlpha colorAttachmentDescriptor.sourceAlphaBlendFactor = .sourceAlpha colorAttachmentDescriptor.destinationRGBBlendFactor = .oneMinusSourceAlpha colorAttachmentDescriptor.destinationAlphaBlendFactor = .oneMinusSourceAlpha

(我认为)这通常是我在网上看到的推荐。

我的测试用例在不同颜色的网格顶部渲染三个三角形。按照绘制顺序,首先渲染白色 (

float4(1, 1, 1, 1)

) 三角形,然后渲染蓝色 (

float4(0, 0, 1, 0.5)
),最后渲染红色 (
float4(1, 0, 0, 0.5)
)。所有通道的
MTKView
的清晰颜色设置为 0。
左边是我从测试用例中得到的输出,右边是我期望的输出(在插图程序中绘制):

如您所见,部分透明的三角形消除了不透明的白色三角形的不透明度。此外,我在左侧绘制的三角形看起来比应有的透明得多,对像素进行采样也证实了这一点。例如,我期望黑色瓷砖和蓝色三角形重叠的像素为

float3(0, 0, 0.5)

,但它看起来更接近

float3(0, 0, ~0.737)
多重采样也发生了一些奇怪的事情:白色三角形与白色瓷砖相交并且只有一个透明三角形相交,似乎根本没有进行任何多重采样。

我在

这个答案

中看到核心动画期望视图使用预乘alpha,并且确实将MTKView的清晰颜色设置为

float4(1, 0, 0, 1)
确实给场景带来了微红的色调,而使用直接alpha我希望在那里没有区别。然而我担心的是,我有部分透明的几何体与不透明的几何体重叠,但同时什么也没有——从片段着色器输出预乘 alpha 的解决方案可以处理这种情况吗?也许通过调整混合模式参数?多重采样怎么样,它似乎无法解决使用预乘 alpha 的问题?
我的测试用例可以在这里找到:

https://github.com/Aquilosion/metal-composite

metal alphablending
1个回答
0
投票

不要使用

srgb

帧缓冲区或纹理
这实际上让我受益匪浅:我将 

MTKView

的像素格式和颜色附件描述符更改为

bgra8Unorm
(从
bgra8Unorm_srgb
)。我还在原始项目中对纹理进行了相同的更改。我认为这个特定的变化是让多重采样正确混合的原因。
为什么这有帮助?我的猜测是,如果帧缓冲区的输出格式设置为线性 RGB(而不是 sRGB),则在绘制场景时混合计算会更加正确。由于屏幕上的结果似乎仍然是正确的 sRGB,我猜想 Core Animation 之后会将非 sRGB 场景转换为 sRGB(或屏幕正在使用的其他任何内容)以进行补偿。

不要使用预乘 alpha

我的所有着色器都直接返回 alpha,并且一切似乎都正常。我链接的答案与此相矛盾,所以我不确定为什么会出现这种情况。可能在旧版本中存在差异——我还没有对此进行任何研究。

(请注意,将 RGB 的透明颜色设置为非 0 值,但 0 alpha 似乎意味着它

确实

需要预乘 alpha,所以我不能 100% 确定这一点,除了正在进行的混合确实反正看起来很准确。我想只要你的clear color全为0,就应该是准确的。) 调整混合参数

我使用了以下混合参数,我认为这些参数对于直接 alpha 混合是正确的:

.isBlendingEnabled = true .rgbBlendOperation = .add .alphaBlendOperation = .add .sourceRGBBlendFactor = .sourceAlpha .sourceAlphaBlendFactor = .one .destinationRGBBlendFactor = .oneMinusSourceAlpha .destinationAlphaBlendFactor = .oneMinusSourceAlpha

我不知道为什么我在问题中包含的混合参数如此受欢迎,因为这些参数产生了更正确的结果,大多数人除了阿尔法混合之外将如何工作(我曾想过!)

© www.soinside.com 2019 - 2024. All rights reserved.