什么时候调用glEnable(GL_FRAMEBUFFER_SRGB)?

时间:2012-07-08 19:59:04

标签: opengl colors framebuffer srgb

我有一个渲染系统,我使用多重采样渲染缓冲区绘制到FBO,然后将其blit到具有纹理的另一个FBO,以便解析样本以便在绘制时读取纹理以执行后处理着色后备缓冲区(FBO索引0)。

现在我想获得一些正确的sRGB输出...问题是当我在OS X和Windows上运行它时,程序的行为相当不一致,这也会因机器而异:On使用Intel HD 3000的Windows不会应用sRGB非线性,而是使用Nvidia GTX 670的其他机器。在OS X中的Intel HD 3000上,它也将应用它。

所以这可能意味着我没有在程序中的正确位置设置GL_FRAMEBUFFER_SRGB启用状态。但是,我似乎无法找到任何实际告诉我什么时候应该启用它的教程,他们只会提到它很容易并且没有性能成本。

我目前没有加载任何纹理,所以我还没有必要处理它们的颜色线性化。

要强制程序不要简单地吐出线性颜色值,我试过的只是注释掉我的glDisable(GL_FRAMEBUFFER_SRGB)行,这实际上意味着为整个管道启用了这个设置,而我实际上是冗余的强迫它回到每一帧。

我不知道这是否正确。它肯定会对颜色应用非线性化,但我无法判断它是否会被应用两次(这会很糟糕)。当我渲染给我的第一个FBO时,它可以应用伽玛。当我把第一个FBO送到第二个FBO时,它可以做到这一点。为什么不?

我已经拍摄了最终帧的屏幕截图,并将原始像素颜色值与我在程序中设置的颜色进行比较:

我将输入颜色设置为RGB(1,2,3),输出为RGB(13,22,28)。

这似乎是低端的相当多的色彩压缩,让我质疑伽玛是否被多次应用。

我刚刚通过sRGB方程式,我可以验证转换似乎只应用一次,因为线性1/255,2 / 255和3/255确实映射到sRGB 13 / 255,22 / 255和28/255使用等式1.055*C^(1/2.4)+0.055。鉴于这些低颜色值的扩展是如此之大,如果sRGB颜色变换被多次应用,那么它应该是显而易见的。

所以,我仍然无法确定正确的做法是什么。 glEnable(GL_FRAMEBUFFER_SRGB)仅适用于最终的帧缓冲区值,在这种情况下,我可以在GL初始化例程中设置它并在以后忘记它吗?

1 个答案:

答案 0 :(得分:20)

启用GL_FRAMEBUFFER_SRGB时,对an sRGB image format图像的所有写入都将假定输入颜色(正在写入的颜色)位于线性颜色空间中。因此,它会将它们转换为sRGB色彩空间。

对sRGB格式的的图像的任何写入都不应受到影响。因此,如果您正在写入浮点图像,则不会发生任何事情。因此,您应该能够将其打开并保持这种状态;当你渲染到sRGB帧缓冲区时,OpenGL会知道。

通常,您希望尽可能长时间地在线性色彩空间中工作。在后处理之后,只有最终渲染应该涉及sRGB色彩空间。因此,您的多重采样帧缓冲区应该保持线性(尽管您应该为其颜色提供更高的分辨率以保持准确性。使用GL_RGB10_A2GL_R11F_G11F_B10FGL_RGBA16F作为最后的手段。)

至于此:

  

在使用Intel HD 3000的Windows上,它不会应用sRGB非线性

这几乎可以肯定是因为英特尔嘲笑编写OpenGL驱动程序。如果启用GL_FRAMEBUFFER_SRGB时它没有做正确的事情,那是因为英特尔,而不是你的代码。

当然,也可能是英特尔的驱动程序没有给你一个sRGB图像(如果你渲染到默认的帧缓冲区)。