【问题标题】:8bit sRGB and OpenGL confusion8bit sRGB 和 OpenGL 混淆
【发布时间】:2017-11-03 08:33:16
【问题描述】:

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

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

【问题讨论】:

    标签: opengl srgb


    【解决方案1】:

    范围是一样的。 The values are not.

    存储之前的线性值是浮点数。因此它们比每通道 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。所以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 颜色空间中创建的),而其他操作将在线性RGB(正常渲染)中生成值。因此,您可以选择开启或关闭转换。

    转换还允许混合到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 每通道 16 位图像(例如 16 位 PNG)怎么样?

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

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

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

    【讨论】:

      【解决方案2】:

      伽玛很好

      我发现将图像存储在 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 曲线编码的颜色值时,这些值会线性化。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-28
        • 1970-01-01
        • 2016-09-01
        • 2011-08-01
        相关资源
        最近更新 更多