背景:我正在尝试解决iTerm2中的问题:https://gitlab.com/gnachman/iterm2/issues/6703#note_71933498
iTerm2对于所有纹理(包括MTKView的可绘制纹理)都使用默认的像素格式
``` fragment float4 iTermBackgroundColorFragmentShader(iTermBackgroundColorVertexFunctionOutput in [[stage_in]]) { return float4(0, 0.16, 0.20, 1); } ```
我还尝试了对 Apple 的 示例应用程序 (
MTLPixelFormatBGRA8Unorm
。在我的机器上,如果我的纹理函数返回颜色C,那么在“以sRGB显示”模式下,数字色彩计应用程序将显示屏幕上的颜色为C。我不知道这为什么有效!它应该将我的纹理函数的原始颜色值转换为sRGB,导致它们改变,对吧?例如,当我的片段函数为窗口的背景颜色返回(0, 0.16, 0.20, 1)
时,我看到的就是这样:
这很奇怪,但我可以接受直到有人抱怨它在他们的设备上不起作用(请参阅上面链接的问题)。对于他们来说,我的片段函数返回的值通过通用 -> sRGb 转换并且看起来不正确。这是一个黑苹果,所以可能是驱动程序错误或其他原因,但这促使我更深入地了解了这个问题。
如果我在所有地方将像素格式更改为MTLPixelFormatBGRA8Unorm_sRGB
,那么我得到的颜色就无法解释:
片段函数保持不变,返回(0, 0.16, 0.2, 1)
。它正在渲染到我使用MTLPixelFormatBGRA8Unorm_sRGB
像素格式创建的纹理上(如果有影响的话,不是可绘制的,尽管可绘制具有相同的像素格式),我可以在GPU调试器中看到这个纹理被分配了你在上面看到的过亮的值。在这个截图中,数字颜色计显示了“中间纹理”缩略图的颜色:
``` fragment float4 iTermBackgroundColorFragmentShader(iTermBackgroundColorVertexFunctionOutput in [[stage_in]]) { return float4(0, 0.16, 0.20, 1); } ```
我还尝试了对 Apple 的 示例应用程序 (
MetalTexturedMesh
) 进行修改,使用 sRGB 像素格式并从其片段着色器返回相同的颜色,结果得到了相同的结果。这是我所做的更改。我只能得出结论,我不理解 Metal 如何定义像素格式,并且找不到任何合理的解释来解释我所看到的行为。
MTLTexture
的一个-getBytes:...
方法并转储它。在此之前不要忘记将纹理与CPU同步。另外,当您说您希望(0, 0.16, 0.20)变为(0, 41, 51)时,这是使用非sRGB像素格式吗? - Ken Thomases7C 6E 00 FF
。这肯定不是数字颜色计报告的内容,但它也与我的预期相去甚远。我本来希望得到33 29 00 ff
。由于纹理函数是硬编码为return float4(0, 0.16, 0.20, 1);
并且像素格式是sRGB,我希望蓝色通道中的0.2
会产生0.2*255=51(十进制)= 0x33,而不是0x7c。我还可以看到它明显比在没有金属的情况下绘制的相同颜色(例如,在-drawRect:中)更亮。 - George