2

我想澄清一下 sRGB 颜色空间及其在 OpenGL 中的每通道 8 位表示。在深入研究该主题后,我发现将图像存储在 sRGB 中只是为了补偿监视器所做的相反伽马操作,该操作出于兼容性原因“模仿”了旧 CTR 本质上所做的操作。人眼具有类似非线性响应的事实只是一个巧合,与伽马校正无关(正如许多令人困惑的文章声称的那样),因为无论如何输出将再次是线性的

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

4

2 回答 2

4

范围是一样的。不是_

存储之前的线性值是浮点数。因此它们比每通道 8 位格式具有更高的精度。

如果您将它们存储在线性RGB 图像中,您将获取输入范围 [0, 1] 并将它们均匀地映射到 [0, 255]。

但是,如果您进行 sRGB 转换,那么您将采用 [0, 1] 范围并通过大约 2.2 的非线性伽马映射将它们映射到 [0, 255]。虽然这种非线性映射不会神奇地创建更多值,但它所做的是有效地为您在范围的较高部分提供比较低部分更高的精度。

在 sRGB 转换中,输入范围 [0.5, 1] 中的值映射到 [56, 255]。这是输入范围的 50% 覆盖的输出范围的 75% 以上。这使您可以更好地表示输入中较大的值。

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

对于内存与视觉质量的权衡,sRGB 总体上优于每通道 8 位的线性 RGB。

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

这取决于您在谈论什么操作。

sRGB 纹理是将其 RGB 信息存储在 sRGB 颜色空间中的纹理。但是,假设着色器操作需要线性RGB 颜色空间中的数据,而不是sRGB。因此,使用 sRGB 格式意味着纹理提取会将它们从 sRGB 读取的像素转换为linearRGB

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

该转换还允许混合读取 sRGB 目标像素,将它们转换为线性,与传入的 linearRGB 值混合,然后将它们转换回 sRGB 以进行写入

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

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

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

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

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

于 2017-11-03T14:48:38.413 回答
1

伽玛很好

我发现将图像存储在 sRGB 中只是为了补偿显示器所做的相反伽马操作......人眼具有类似非线性响应的事实只是一个巧合,与伽马校正无关...... .假设这个理解是正确的

这种理解是不正确的。出于感知原因,需要使用伽马曲线存储图像以增加黑暗区域的数据密度。如果没有伽玛,您将需要 12 位来实现与使用 8 位和伽玛曲线获得的相同图像保真度。

老式电视本来可以设计为使用线性化信号,但实际上当时的设计技术将伽玛从理论上的 1.5 增加到常用的 2.4。作为系统设计的一项功能,伽马的使用降低了广播信号中对噪声的感知。

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

OpenGL

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

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

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

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

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

sRGB 标签在那里,因此当您拥有一个 sRGB 图像时,该图像的颜色值用 ~1/2.2 曲线编码,这些值会线性化。

于 2019-06-21T09:53:02.927 回答