假设我从一个具有sRGB颜色配置文件的jpg文件中加载一个纹理,在加载时没有转换为线性RGB。当矩形显示在屏幕上时,我看不出图像有任何问题。颜色与在其中一个编辑器中打开它的颜色相同。
问题是,由于没有转换,RGB值保持在sRGB范围内。硬件如何知道不需要转换,或者为什么GPU不转换。基本上为什么XYZ->sRGB转换没有发生。
我很困惑,因为如果我把sRGB数据输入到某个东西中,它最终会再次转换为sRGB,这会改变颜色,但它不会。
首先,OpenGL默认情况下不进行任何颜色转换。让我们从最小的配置开始,包括输入图像、窗口缓冲区(由OpenGL渲染)和监视器。每个可能由不同的颜色空间定义,但在最简单的情况下,它看起来是这样的:
[RGB image|sRGB] -> [OpenGL Window Buffer|sRGB] -> [Monitor|sRGB]
默认情况下,显示器配置为使用sRGB预设,即使是支持更宽颜色范围的显示器,也可以避免不正确的颜色输出。默认情况下,渲染到OpenGL窗口缓冲区中不会执行任何颜色转换,因此,如果输入图像在sRGB颜色空间中,则它在OpenGLWindow Buffer中将保持不变。OS Composer通常只将OpenGL Window Buffer复制到屏幕上-这一步也不意味着颜色转换。所以基本上所有的步骤都是通过输入图像,如果它在sRGB颜色空间中,您可以看到预期的结果。
现在考虑另一种场景:在启用照明的情况下,应用输入图像将纹理映射到3D对象上照明方程只有在线性RGB颜色空间中才有意义,因此在没有额外配置的情况下,OpenGL基本上会采用非线性sRGB图像值,将它们作为参数传递给未修改的着色方程,并将结果写入OpenGL窗口缓冲区,该缓冲区将传递给配置为sRGB颜色空间的监视器。结果是可以承受的,但在物理上是不正确的。
为了解决不正确照明的问题,OpenGL引入了sRGB感知功能,这样用户就可以明确地说输入图像是否在sRGB或线性RGB颜色空间中,以及GLSL程序颜色值的结果是否应该从线性RGB颜色空间隐式转换为非线性sRGB颜色空间。因此:
[GLSL Texture Input|sRGB -> linear RGB implicit conversion] ->
-> [GLSL Lighting Equation|linear RGB] ->
-> [GLSL output|linear RGB -> sRGB implicit conversion]
只有通过使用GL_SRGB8_ALPHA8
纹理格式和在渲染到屏幕外或窗口缓冲区时使用GL_FRAMEBUFFER_SRGB
以这种方式显式配置OpenGL时,才会执行隐式转换步骤。整个概念可能很难理解,甚至更难实现。
注意,在这种情况下;线性RGB";实际上意味着线性化的sRGB颜色空间,因为它经常被省略线性RGB实际的含义。这是因为对于颜色数学(照明和其他),重要的是只有RGB值在任何线性颜色空间的输入和输出上是线性的,但当谈到隐式sRGB->线性RGB和线性RGB->sRGB转换-这些显然依赖于sRGB和OpenGL规范定义的RGB值的转换。事实上,有更多的线性RGB颜色空间不代表sRGB颜色空间
现在考虑您的Input Image
不在sRGB颜色空间中,而是使用其他一些RGB颜色配置文件。OpenGL除了线性RGB和sRGB之外,没有提供太多其他纹理格式,因此应该通过图像读取器或通过特殊的GLSL程序实时执行颜色空间转换来将此类图像正确转换为sRGB颜色空间。
现在考虑将监视器配置为非sRGB配置文件,如AdobeRGB。在这种情况下,通过sRGB图像到OpenGL窗口将产生失真的颜色。通过让Windows知道您的显示器在另一个颜色配置文件中,您将帮助Photoshop等一些应用程序正确转换颜色,但OpenGL对Windows中配置的这些颜色配置文件一无所知!该应用程序负责应用颜色配置文件信息以执行正确的颜色转换(通过特殊的GLSL程序或其他方式)。通过在非sRGB颜色空间应用程序中使用输入图像,还可以选择执行non-sRGB -> sRGB -> another non-sRGB
颜色转换或实现GLSL程序,该程序将在没有代理sRGB的情况下(或通过代理XYZ)直接执行到目标颜色空间的颜色转换,以避免因瞬态转换而丢失颜色精度信息。
在OpenGL查看器中支持任意的颜色配置文件,而不是设计为图像查看器,可能会涉及太多的复杂性。然而,有些系统定义了几个标准颜色空间,由系统编辑器执行隐式转换,这比使用其特殊的查找表和公式支持任意颜色配置文件要可靠得多。
例如,macOS定义了NSWindow::setColorSpace property
,它允许应用程序明确指定在哪个颜色空间窗口缓冲区中填充,这样系统本身就可以执行到实际监视器颜色配置文件的必要转换。安卓系统定义了一个类似的界面,用于支持与旧sRGB颜色配置文件相比具有扩展颜色范围的新P3 Display颜色配置文件。然而,这意味着OpenGL渲染器实际上知道如何在这个特定的颜色空间中输出结果——这是另一个主题(还有一组额外的OpenGL扩展帮助开发人员朝着这个方向发展)。。。到目前为止,我还没有听说过Windows中有类似的API,但我可能会错过一些东西。