我最近尝试创建一个透明的MTKView,在其中可以绘制一些几何图形,包括部分透明的几何图形,并且能够正确地与位于MTKView后面的任何视图进行合成。在尝试实现这一目标时,我遇到了两个问题:
1. 在不透明区域上绘制部分透明的三角形会使该区域不再是不透明的。 2. 部分透明像素的颜色与背景没有正确混合,包括多重采样的抗锯齿像素。
我创建了一个测试案例,至少可以演示第一个问题,可能还包括第二个问题。在测试案例中,混合模式设置为:
这大概是我在网上看到的推荐做法。
我的测试案例在一个不同颜色的网格上渲染了三个三角形。按照绘制顺序,首先渲染白色(float4(1, 1, 1, 1))的三角形,然后是蓝色(float4(0, 0, 1, 0.5))的三角形,最后是红色(float4(1, 0, 0, 0.5))的三角形。MTKView的清除颜色设置为所有通道的0。
左边是我从测试案例中得到的输出,右边是我期望的输出(在一个插图程序中绘制)。 如您所见,部分透明的三角形使不透明的白色三角形的不透明度消失。此外,我在左侧绘制的三角形看起来比它们应该的更透明,对像素进行采样可以证实这一点。例如,我期望黑色瓷砖和蓝色三角形重叠的像素应该是
此外,多重采样也出现了奇怪的问题:当白色三角形与白色瓷砖和仅有一个透明三角形相交时,似乎根本没有进行多重采样。
我在这个回答中看到,核心动画希望视图使用预乘alpha。确实,将MTKView的清除颜色设置为float4(1, 0, 0, 1)会给场景带来红色的色调,而使用直接alpha时我不希望有任何差异。然而,我的担忧是,我有部分透明的几何体同时重叠着不透明的几何体和完全没有任何东西的情况下,从片段着色器输出预乘alpha的解决方案能处理这种情况吗?也许通过调整混合模式参数可以解决这个问题?那么多重采样呢?它似乎没有解决使用预乘alpha的问题。
我的测试案例在这里可用:https://github.com/Aquilosion/metal-composite
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