【问题标题】:Transparent MTKView not blending properly with windows behind it透明的 MTKView 无法与其后面的窗口正确融合
【发布时间】:2018-12-23 13:20:51
【问题描述】:

我有一个简单的 macOS 应用程序,它有一个 MTKView——它只是一个窗口内的 MTKView。片段着色器总是这样:

return float4(1, 0, 0, 0.01)

那是带有 1% alpha 的红色。

属于 MTKView 的 CAMetalLayer 是不透明的,窗口也是如此:

_mtkView.layer.opaque = NO;
_mtkView.window.opaque = NO;
_mtkView.window.backgroundColor = [NSColor clearColor];
_mtkView.window.hasShadow = NO;

当我将此窗口放在另一个应用程序的窗口上时,我希望其他应用程序的像素保持不变。相反,我看到黑色像素变成了红色,而白色像素几乎没有变化。

在下面的屏幕截图中,三角形的颜色为 float4(1,0,0,0.01),并且在另一个窗口中显示了一个半黑半白的图像:

我本以为三角形的左半边是黑色,略带红色,而不是鲜红色。

如果我的片段着色器被更改为这样做:

return float4(1, 0, 0, 0.001);

然后它是完全透明的:来自其他窗口的像素完全不变地显示出来。这让我觉得我在窗口服务器中遇到了一个未经充分测试的代码路径,但我希望我能做些什么来让它工作。

我尝试了什么

  • 更改 NSThemeFrame 的外观(无效)
  • 开启 PresentWithTransaction(无效)
  • GPU 调试器确认可绘制对象具有预期值

【问题讨论】:

  • 确保图层的compositingFilterbackgroundFiltersnil。将视图的 framebufferOnly 设置为 false 会改变什么吗?
  • compositingFilter 和 backgroundFilters 对于 CAMetalLayer 和它的超层都是 nil 和空的。在 CAMetalLayer 上设置 framebufferOnly=NO 无效。
  • 作为一个实验,如果您将 Metal 视图包含在使用普通 Cocoa 绘图绘制半黑半白图像的 layer-back 视图中会发生什么?也就是说,消除窗口之间的合成,只验证视图层合成。同样,尝试不使用 Metal 的实验,仅使用透明填充并绘制大部分透明三角形的图层支持视图,然后看看它是如何合成的。
  • 这是个好主意。它没有正确合成,并显示相同的症状。
  • …并且当使用具有非透明图层的图层托管视图时,它确实正确合成,其内容是具有透明三角形的 NSImage。

标签: macos cocoa metal


【解决方案1】:

苹果写道:

CoreAnimation 合成器要求其所有输入都是 预乘 alpha。有关更多信息,请参阅这些参考: https://en.wikipedia.org/wiki/Alpha_compositing https://blogs.msdn.microsoft.com/shawnhar/2009/11/06/premultiplied-alpha/

当 RGB 预乘 alpha 时,任何 RGB 分量 > 通过硬件的混合未定义 alpha 分量。

修改片段着色器以返回 (0.1, 0, 0, 0.1),即 “0.1 alpha, full red”会产生预期的结果。

确实,这解决了我的问题。相关的提交是https://github.com/gnachman/iTerm2/commit/70a93885b1f67bda843ba546aca0eca67b750088,我在其中修改了程序以绘制到屏幕外纹理,然后将其复制到可绘制对象中,同时将红色、绿色和蓝色分量乘以 alpha。

由于某种我无法理解的原因,我的测试程序还需要转换为线性色彩空间。

【讨论】:

  • 请问您在哪里找到了该文档?我想我遇到了类似的问题,但在 Apple 的 Metal 文档中找不到任何关于此的提及。
  • 我提交了一份雷达,他们回复了该消息。如果他们记录下来就好了!
猜你喜欢
  • 2015-10-25
  • 2021-04-17
  • 1970-01-01
  • 2013-04-02
  • 2019-07-15
  • 2018-05-18
  • 2013-02-21
  • 1970-01-01
  • 2011-03-26
相关资源
最近更新 更多