范围是一样的。值不是。_
存储之前的线性值是浮点数。因此它们比每通道 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 不匹配的任何其他情况一样,您必须手动转换它们。