我最近读了一些关于sRGB格式的文章,以及它们是如何允许硬件自动执行典型显示器的色彩校正的。作为我阅读的一部分,我看到你可以用一个普通的纹理和返回结果上的一个pow函数来模拟这一步。
无论如何,我想问两个问题,因为我以前从未使用过这个功能。首先,有没有人能从我的截图中确认这就是你期望看到的?左边的图片是普通的RGBA,右边的图片是一个sRGB目标。场景中没有环境光,模型为沼泽标准Phong (灯光为聚光灯)。

我想问的第二个问题是,在什么情况下,硬件实际执行了校正?例如,我正在向FBO写入帧,然后使用FBO颜色缓冲区将屏幕大小的四边形渲染到后台缓冲区(我打算很快切换到延迟着色)。我应该使用附加到FBO的sRGB纹理,还是只需要指定一个sRGB纹理作为后台缓冲区目标?如果你使用的是sRGB,那么所有的纹理资源都应该是sRGB吗?
发布于 2012-04-27 18:07:38
注意:下面的讨论假设您了解什么是sRGB色彩空间,什么是伽马校正,什么是线性RGB色空间,等等。本文主要关注该技术的OpenGL实现。
如果您想深入讨论这些主题,我建议您查看我在HDR/Gamma correction上的教程(以了解线性色彩空间和gamma),以及sRGB images and how they handle gamma correction上的教程。
首先,有人能从我的截图中确认这就是你期望看到的吗?
我不太明白你这个问题是什么意思。如果您应用适当的gamma校正(这是sRGB或多或少所做的),您通常会在图像的较暗区域获得更多细节,并获得“更亮”的结果。
然而,正确的思考方式是,在你做适当的伽马校正之前,你所有的图像都是错误的。您的图像太暗了,gamma校正现在使它们具有适当的亮度。你对事物应该是什么颜色以及光线应该有多亮所做的每一个决定都是错误的。
我想问的第二个问题是,在什么时候由硬件实际执行校正?
这是一个与你继续讨论封面的“例如”部分非常不同的问题。
sRGB图像(请记住:纹理包含图像,但帧缓冲区也可以包含图像)可用于以下上下文:
在积极的一面,如果你有GL 3.x+功能的硬件,你几乎肯定会在线性色彩空间中完成过滤,在那里它是有意义的。sRGB是非线性颜色空间,因此sRGB值的线性插值始终是从片段着色器输出到帧缓冲区图像的wrong.
glEnable(GL_FRAMEBUFFER_SRGB);这会告诉OpenGL从片段着色器写入的值是线性颜色空间值。因此,在将它们存储在图像中时,OpenGL需要将它们转换为sRGB同样,如果你有GL 3.x+硬件,你几乎肯定会在线性色彩空间中得到混合。也就是说,OpenGL将从帧缓冲区读取RGB值,将其转化为线性RGB值,将其与传入的线性RGB值(从着色器中写入的值)混合,将混合后的值转化为sRGB颜色空间并存储。同样,这正是您想要的;在sRGB色彩空间中混合总是不好的。
现在我们理解了这一点,让我们来看看你的例子。
例如,我正在向FBO写入帧,然后我将使用FBO颜色缓冲区渲染一个屏幕大小的四边形到后台缓冲区(我打算很快切换到延迟着色)。
这样做的问题是你没有问对问题。你需要记住的是这个问题,特别是当你进入延迟渲染的时候:
这是不是线性RGB?
通常,您应该尽可能长时间地将任何中间数据存储在gamma校正空间中。因此,任何中间缓冲区(即:您积累灯光的地方)都不应该是sRGB的。
这不是关于转换的成本;而是关于你正在做什么。如果你在做延迟渲染,那么你可能也在做HDR照明等等。所以你的光积累缓冲区需要是浮点型的。并且浮动缓冲区总是线性的;它们没有理由不是线性的。
如果要利用自由gamma校正(确实如此),则最终图像(默认帧缓冲区)必须为sRGB。如果您在HDR浮动缓冲区中完成所有工作,然后将结果色调映射到最终显示,则应将其写入sRGB图像。
https://stackoverflow.com/questions/10347995
复制相似问题