macos - 透明 MTKView 未与其后面的窗口正确混合

标签 macos cocoa metal

我有一个简单的 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),并且在另一个窗口中通过它显示出半黑半白的图像:

Screenshot showing the problem

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

如果我的片段着色器更改为执行此操作:

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

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

我尝试了什么

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

最佳答案

苹果写道:

The CoreAnimation compositor requires all of its inputs be premultipled by alpha. See these references for more information: https://en.wikipedia.org/wiki/Alpha_compositing https://blogs.msdn.microsoft.com/shawnhar/2009/11/06/premultiplied-alpha/

When RGB are premultipled by alpha, then any RGB component that is > the alpha component is undefined through the hardware’s blending.

Modifying your fragment shader to return (0.1, 0, 0, 0.1), which is “0.1 alpha, full red” produces the expected results.

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

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

关于macos - 透明 MTKView 未与其后面的窗口正确混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51354283/

相关文章:

ios - 在设备(iOS)上编码 ASTC?

metal - 片段函数似乎写得正确,但 Metal 提示

swift - 使用 takeSnapshot 的 WKWebView 间歇性空白/部分屏幕截图

php - 如何使用 PHP 在 OS X 10.5.8 中启用 Sqlite3?

ios - 将 HTML 字符串下载到 iOS 中的 NSString 或 Swift String 变量中

objective-c - 当你在 lldb 中打印一个 Swift 对象 (po) 时会发生什么?

macos - 在osx特立独行中发布opencv的问题:ld:找不到架构x86_64的符号

macos - 获取鼠标在整个屏幕 Mac OS X 中的位置

cocoa - setFrame 创建的 NSView 在两个维度上都比预期小 15 像素

metal - Metal如何将图像 block 分配到每个线程组?