sRGB纹理。它是否正确?

时间:2012-04-27 09:17:02

标签: opengl textures

我最近一直在阅读有关sRGB格式的内容,以及它们如何允许硬件自动执行典型显示器的色彩校正。作为阅读的一部分,我看到你可以使用普通纹理和返回结果的pow函数来模拟这一步。

无论如何,我想问两个问题,因为我之前从未使用过这个功能。首先,任何人都可以从我的截图中确认这是你期望看到的吗?左图是普通RGBA,右图是sRGB目标。场景中没有环境照明,模型是沼泽标准Phong(灯光是聚光灯)。

Left shows RGBA, right shows SRGBA

我想问的第二个问题是硬件实际执行的修正是什么?例如,我正在向FBO写帧,后来我使用FBO颜色缓冲区将一个屏幕大小的四边形渲染到后台缓冲区(我打算很快切换到延迟着色)。我应该使用附加到FBO的sRGB纹理,还是只需要指定sRGB纹理作为后缓冲区目标?如果您使用的是sRGB,那么所有纹理资源都应该是sRGB吗?

1 个答案:

答案 0 :(得分:38)

注意:以下讨论假定您了解sRGB色彩空间是什么,伽马校正是什么,线性RGB色彩空间是什么,等等。这主要侧重于OpenGL技术的实现。

如果您想深入讨论这些主题,我建议您查看HDR/Gamma correction上的教程(了解线性色彩空间和伽玛)以及sRGB images and how they handle gamma correction上的教程。

  

首先,任何人都可以从我的屏幕截图中确认这是您期望看到的吗?

我不确定我明白你的意思是什么。如果您应用适当的伽马校正(这是sRGB或多或少的功能),您通常会在图像的较暗区域获得更多细节并获得“更明亮”的结果。

然而,考虑它的正确方法是直到你做了正确的伽马校正你的所有图像都是错误的。您的图像太暗,伽马校正现在使它们成为合适的亮度。你做出的关于事物应该是什么颜色以及应该是多么明亮的光线的每一个决定都是错误的

  

我想问的第二个问题是硬件实际执行的修正是什么时候?

这是一个非常不同的问题,而不是“继续”封面的“例如”部分。

sRGB图像(请记住:纹理包含图像,但帧缓冲区也可以包含图像)可以在以下上下文中使用:

  • 将数据从用户直接传输到图像(例如,使用glTexSubImage2D等)。 OpenGL 假定您正在提供已存在于sRGB色彩空间中的数据。因此,上传时不会转换数据。之所以这样做是因为它最有意义:通常,您从艺术家那里获得的任何图像都将在sRGB色彩空间中,除非艺术家花了很大力气将其放入其他颜色空间。实际上,每个图像编辑器都直接在sRGB中工作。

  • 通过采样器读取着色器中的值(即:访问纹理)。这也很简单。 OpenGL知道图像中的纹素数据是在sRGB颜色空间中。 OpenGL假定着色器需要线性 RGB颜色数据。因此,所有尝试从具有sRGB image format的纹理进行采样将导致sRGB-> lRGB转换。哪个是免费的,顺便说一句。

    从好的方面来说,如果你有能够支持GL 3.x +的硬件,你几乎肯定会在线性色彩空间中完成滤波,这是有意义的。 sRGB是一个非线性色彩空间,因此sRGB值的线性插值总是错误的。

  • 将片段着色器输出的值存储到帧缓冲区图像中。这是稍微复杂的地方。即使您渲染的帧缓冲图像位于sRGB色彩空间中,也不足以强制转换。你必须明确glEnable(GL_FRAMEBUFFER_SRGB);这告诉OpenGL您从片段着色器中写入的值是线性颜色空间值。因此,OpenGL需要在将它们存储在图像

    中时将它们转换为sRGB

    同样,如果你有GL 3.x +硬件,你几乎肯定会在线性色彩空间中进行混合。也就是说,OpenGL将从帧缓冲区读取sRGB值,将其转换为线性RGB值,将其与传入的线性RGB值(您从着色器中写入的值)混合,将混合值转换为sRGB色彩空间并存储它。再一次,这就是你想要的;在sRGB颜色空间中混合总是很糟糕。

现在我们明白了,让我们来看看你的例子。

  

例如我正在向FBO写入帧,然后我使用FBO颜色缓冲区将一个屏幕大小的四边形渲染到后台缓冲区(我打算很快切换到延迟着色)。

问题在于你没有问正确的问题。在进入延迟渲染时,您需要记住的是尤其是,这是一个问题:

这是否为线性RGB?

通常,您应该尽可能长时间地将任何中间数据存储在伽马校正空间中。所以任何中间缓冲区(即:你积累灯光的地方)都应该是sRGB。

这不是关于转换的成本;这真的是关于你在做什么。如果您正在进行延迟渲染,那么您可能也在进行HDR照明等等。所以你的光累积缓冲区需要是浮点数。浮动缓冲区总是线性的;它们没有理由不是线性的。

如果你想利用免费的伽马校正(你可以),你的最终图像,默认帧缓冲,必须是sRGB。如果您在HDR浮点缓冲区中完成所有工作,然后将结果进行色调映射以进行最终显示,则应将其写入sRGB图像。