8位sRGB和OpenGL混淆

时间:2017-11-03 08:33:16

标签: opengl srgb

我想问一下有关sRGB色彩空间及其在OpenGL中的每通道8位表示的说明。在深入研究这个主题之后,我发现在sRGB中存储图像只是为了补偿由监视器完成的相反的伽玛操作,即模仿"出于兼容性原因,旧的CTR本质上是做什么的。人眼具有类似的非线性响应这一事实只是一个巧合,与伽马校正无关(正如许多令人困惑的文章所声称的那样),因为输出将是linear again anyway

假设这种理解是正确的,在OpenGL中我们有纹理的GL_SRGB8_ALPHA8格式,每个通道有8位。然而,由于0~255的范围与线性RGB纹理相同,这是否意味着将每通道纹理的线性8位转换为sRGB,颜色值保持不变,并且简单的标记为#34;告诉OpenGL:看看0~255范围是不是线性的,所以将它们解释为曲线? 每通道sRGB 16bit图像(例如16位PNG)怎么样?

2 个答案:

答案 0 :(得分:3)

范围相同。 The values are not

存储前的线性值是浮点数。因此,它们的精度高于每通道8位格式。

如果将它们存储在linearRGB图像中,则需要输入范围[0,1]并将它们均匀映射到[0,255]。

但是如果你进行sRGB转换,那么你将获得[0,1]范围并通过大约2.2的非线性伽马映射将它们映射到[0,255]。虽然这种非线性映射并没有神奇地创造出更多的值,但它所做的却有效地使你在范围的较高部分比下部更精确。

在sRGB转换中,输入范围[0.5,1]中的值映射到[56,255]。这超过了输出范围的50%,超出输入范围的50%。这样可以更好地表示输入中较大的值。

线性映射均匀地失去精度。 sRGB映射在较暗区域中比在较轻的区域中失去更高的精度。或者换句话说,在线性映射的较亮区域中保留更精确。

对于内存与视觉质量的权衡,sRGB整体上比linearRGB每通道8位更好。

  

然而,由于0~255的范围与线性RGB纹理相同,这是否意味着将每通道纹理的线性8位转换为sRGB,颜色值保持不变,简单的“标志”告诉OpenGL:看这个0~255范围不是线性的,所以将它们解释为曲线?

这取决于你所说的操作。

sRGB纹理是一种纹理,可将其RGB信息存储在sRGB色彩空间中。但是,假设着色器操作需要linearRGB色彩空间中的数据,而不是sRGB。所以using an sRGB format means that texture fetches will convert the pixels they read from sRGB to linearRGB

使用sRGB格式从片段着色器写入到附加FBO的图像可能会也可能不会执行转换。此处,必须使用GL_FRAMEBUFFER_SRGB明确启用转换。想法是某些操作将在sRGB颜色空间中生成值(例如,GUI。大多数图像是在sRGB颜色空间中创建的),而其他操作将生成linearRGB(正常渲染)中的值。因此,您可以选择开启或关闭转化。

转换还允许混合到read sRGB destination pixels, convert them to linear, blend with the incoming linearRGB values, and then convert them back to sRGB for writing

上传到sRGB图像并从sRGB图像下载将直接在sRGB颜色空间中写入和读取像素值。

  

每通道图像的sRGB 16位(例如16位PNG)怎么样?

他们呢? OpenGL没有每通道16位的sRGB格式。

sRGB转换通常通过256项表查找完成。对于每个sRGB值,都有一个预先计算的线性值。

因此,就像任何其他情况一样,图像格式提供的东西与OpenGL不匹配,你必须手动转换它们。

答案 1 :(得分:1)

伽玛很好

  

我发现将图像存储在sRGB中只是为了补偿监视器执行的相反的伽玛操作...人眼具有类似的非线性响应这一事实只是一个巧合,没有什么可做的。做伽玛校正... 假设这种理解是正确的

这种理解是不正确的。出于感知原因,必须存储带有伽玛曲线的图像,以增加暗区中的数据密度。如果没有伽玛,则需要8位和12位伽玛曲线才能获得相同的图像保真度。

本来可以将老式电视设计为使用线性信号,但实际上,当今的设计技术将伽玛值从理论上的1.5提高到了常用的2.4。根据系统设计,使用伽马会减少广播信号中的噪声感知。

伽玛类型的传输曲线通过加权每个人的非线性视觉感知的可用带宽来充分利用有限的带宽。

OPENGL

关于您的问题,如果内部格式参数是GL_SRGB,GL_SRGB8,GL_SRGB_ALPHA或GL_SRGB8_ALPHA8,则 将纹理视为将红色,绿色或蓝色分量编码在sRGB色彩空间中

这意味着图像中的值被假定为伽玛编码值,而GL_RGB8被认为是线性值。

  

但是,由于0〜255的范围与线性RGB纹理相同,这是否意味着要将每个通道的线性8bit纹理转换为sRGB,颜色值保持不变,并且简单的“标志”告诉OpenGL :看起来0〜255的范围不是线性的,将其解释为曲线吗? sRGB每通道16位图像(例如16位PNG)如何处理?

该范围或位深度与是否使用伽玛曲线完全无关。

图像出于感知原因需要使用伽玛。线性纹理贴图或凹凸贴图则没有。如果在线性凹凸贴图上使用GL_SRGB8标签,则GL将在您不想使用的线性数据上使用sRGB伽玛-也就是说,它将对线性1.0值应用大约2.2的幂曲线,但这不是除非您的凹凸贴图是具有伽玛曲线的图像。

其中存在sRGB标签,因此,当您拥有一个sRGB图像,该图像的颜色值用〜1 / 2.2曲线编码时,这些值将线性化。