假设我从一个具有sRGB颜色配置文件的jpg文件中加载一个纹理,加载时没有转换为线性RGB。当屏幕上显示一个矩形时,我看不到图像有任何问题。颜色与在其中一个编辑器中打开它的颜色相同。
问题是,由于没有转换,RGB值仍然在sRGB范围内。硬件如何知道不需要转换,或者为什么GPU没有转换。基本上,为什么XYZ -> sRGB转换没有发生。
我非常困惑,因为如果我将sRGB数据输入到最终将其再次转换为sRGB的内容中,将会改变颜色,但它不会。
发布于 2021-01-22 01:15:11
首先,在默认的下,OpenGL不会进行任何颜色转换。让我们从最小的配置开始,由输入图像、窗口缓冲区(由OpenGL渲染)和监视器组成。每种颜色都可能由不同的颜色空间定义,但在最简单的情况下,它将如下所示:
[RGB image|sRGB] -> [OpenGL Window Buffer|sRGB] -> [Monitor|sRGB]
默认情况下,显示器配置为使用sRGB preset,即使是支持更宽颜色范围的显示器,以避免错误的颜色输出。默认情况下,渲染到OpenGL窗口缓冲区不会执行任何颜色转换,因此如果输入图像在sRGB色彩空间中,它在OpenGL窗口缓冲区中将保持相同。OS Composer通常只是将OpenGL窗口缓冲区复制到屏幕上-这一步也不意味着颜色转换。所以基本上所有的步骤都只是传递输入图像,如果它是在sRGB色彩空间中,你会看到预期的结果。
现在考虑另一个场景:将纹理贴图的输入图像应用到启用了照明的3D对象上。照明方程式仅在线性RGB色彩空间中有意义,因此在没有额外配置的情况下,OpenGL将基本上采用非线性sRGB图像值,将它们作为参数原封不动地传递到着色方程式,并将结果写入OpenGL窗口缓冲区,该缓冲区将传递到配置为sRGB色彩空间的监视器。结果将是负担得起的,但物理上是不正确的。
为了解决错误照明的问题,OpenGL引入了sRGB-awareness功能,这样用户就可以明确地说出输入图像是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时,才会执行隐式转换的步骤。整个概念might be tricky to understand and even trickier to implement。
请注意,在这种情况下,“线性RGB”实际上意味着线性化的sRGB色彩空间,因为它经常被省略什么是线性RGB的实际含义。这是因为对于色彩数学(照明和其他)来说,重要的只是RGB值在任何线性色彩空间中的输入和输出都是线性的,但是当谈到隐式sRGB ->线性RGB和线性RGB线性-> sRGB转换时-这些转换显然依赖于sRGB和OpenGL规范定义的RGB值的转换。在现实中,有更多的线性RGB色彩空间并不代表sRGB色彩空间。
现在考虑你的Input Image不是在sRGB色彩空间中,而是使用了另一个RGB色配置文件。OpenGL没有提供太多的其他纹理格式来保存线性RGB和sRGB,所以这样的图像到sRGB色彩空间的适当转换应该由图像阅读器或通过执行色彩空间动态转换的特殊GLSL程序来完成。
现在考虑将一个监视器配置为非sRGB配置文件,如AdobeRGB。在这种情况下,将sRGB图像传递到OpenGL窗口将产生扭曲的颜色。通过让视窗知道您的显示器在另一个颜色配置文件中,您将帮助一些应用程序,如Photoshop正确转换颜色,但OpenGL对这些在Windows中配置的颜色配置文件一无所知!它是一个应用程序,负责应用颜色配置文件信息来执行适当的颜色转换(通过特殊的GLSL程序或通过其他方式)。通过在非sRGB应用程序中处理输入图像,还可以选择执行non-sRGB -> sRGB -> another non-sRGB颜色转换或执行GLSL程序,该程序将执行颜色转换,而无需代理sRGB(或通过代理XYZ)直接转换到目标颜色空间,以避免由于瞬时转换而丢失颜色精度信息。
在OpenGL查看器中支持未设计为图像查看器的任意颜色配置文件可能会涉及太多复杂性。但是,某些系统定义了几个标准色彩空间来由system composer执行隐式转换-这比使用其特殊的查找表和公式支持任意颜色配置文件要可靠得多。
例如,macOS定义了NSWindow::setColorSpace property,它允许应用程序明确指定填充哪个色彩空间窗口缓冲区,以便系统本身执行到实际显示器色彩配置文件的必要转换。用于支持新的P3显示器颜色配置文件的Android system defines a similar interface,与旧的sRGB颜色配置文件相比,该颜色配置文件的颜色范围更广。然而,这意味着OpenGL渲染器实际上知道如何在这个特定的色彩空间中输出结果-这是另一个主题(还有一组额外的OpenGL扩展可以帮助开发人员在这个方向上)……到目前为止,我还没有听说Windows中有类似的API,但我可能会错过一些东西。
https://stackoverflow.com/questions/65831143
复制相似问题