sRGB FBO渲染到纹理

时间:2012-02-26 22:01:40

标签: opengl srgb

在我的渲染器中,我在多重采样的FBO上产生一个消除锯齿的场景,该场景被blit到FBO,其颜色附件是纹理。然后在渲染到帧缓冲区期间读取纹理。

我想更新它,以便获得正确的伽玛结果。使用sRGB帧缓冲区的好处是,通过将非线性sRGB值直接存储在帧缓冲区中,它可以让我有更好的色彩精度。

我不确定的是我应该做些什么改变,以及不同设置会改变什么。

看起来extension ARB_framebuffer_sRGB正在处理与sRGB帧缓冲区的读取和混合操作。在我的情况下,我需要使用指定sRGB表示类型的纹理,这意味着我将使用扩展名EXT_texture_sRGB ...使用线性纹理格式将禁用sRGB转换。

编辑:但我刚看到这个:

  

3)是否有能力支持sRGB帧缓冲更新和混合      是framebuffer的一个属性?

     

决议:是的。它应该是某些像素格式的功能      (很可能只是RGB8和RGBA8)说sRGB混合可以      启用。

     

这允许实现简单地标记现有的RGB8      和RGBA8像素格式作为支持sRGB混合然后      只提供sRGB更新和混合的功能      这样的格式。

现在我不太确定要为纹理的像素格式指定什么。

好的,那渲染缓冲区怎么样? ARB_framebuffer_sRGB doc没有提及有关renderbuffers的任何内容。是否可以将glRenderbufferStorageMultisample与sRGB格式一起使用,以便我可以启用sRGB存储混合?

另外,在指定glTexImage2D的内部格式时,GL_SRGB_ALPHAGL_SRGB8_ALPHA8之间的区别是什么?

1 个答案:

答案 0 :(得分:5)

  

我不确定的是我应该做些什么改变才能得到这个

那是因为你的问题似乎不确定你要做什么。

所有这些内容的关键是始终知道输入数据是什么以及输出数据是什么。

您的第一步是了解每个纹理中存储的内容。特定纹理是否存储sRGB色彩空间中的线性数据或数据?如果它存储线性数据,则使用其中一种线性图像格式。如果它存储sRGB色彩空间数据,则使用其中一种sRGB图像格式。

这可确保您在着色器中获取所需的数据。当需要将它们写入/混合到帧缓冲区时,您现在需要决定如何处理它。

您的屏幕需要将预伽马校正的值预测为显示设备的伽玛值。因此,如果提供线性值,则会得到不正确的颜色输出。

但是,有时候,您希望写入中间值。例如,如果您正在进行前向或延迟渲染,则会将累积的光照写入浮点缓冲区,然后使用HDR色调映射将其粗体显示为[0,1]图像。可以再次使用后处理技术。只有[0,1]的输出需要是sRGB色彩空间中的图像。

在编写要转换为sRGB的线性RGB值时,必须启用GL_FRAMEBUFFER_SRGB。这是一个特殊的启用(请注意纹理没有办法关闭sRGB解码)因为有时候,你想要写入已经在sRGB中的值。这通常是GUI界面小部件的情况,它是使用sRGB颜色空间中已有的颜色设计和构建的。

我在教程系列中介绍了与writing gamma-correct valuesreading them from textures相关的问题。第一个解释了为什么伽玛是重要的并且在着色器中明确地进行伽马校正。第二个链接介绍了如何在纹理和帧缓冲区中使用sRGB图像。

  

好的,那渲染缓冲区怎么样? ARB_framebuffer_sRGB doc没有提及任何有关渲染缓冲区的内容。

为什么会这样? ARB_framebuffer_sRGB只对帧缓冲区及其中图像的性质感兴趣。它既不知道也不关心那些图像来自何处。它不关心它是否谈论默认的帧缓冲,附加到FBO的纹理,附加到FBO的渲染缓冲区,或者明天会有新人提出的东西。

扩展名说明目标图像在sRGB色彩空间中以及启用GL_FRAMEBUFFER_SRGB时发生的情况。图像的来源取决于你。

  

另外,在指定glTexImage2D的内部格式时,GL_SRGB_ALPHA和GL_SRGB8_ALPHA8有什么区别?

一个是大小的。另一个不是。从理论上讲,GL_SRGB_ALPHA可以为您提供实现所需的任何深度。它可以为每个组件提供2位。您可以自由选择自己想要的内容。

在实践中,我怀疑你会发现不同之处。话虽如此,总是尽可能使用大小的内部格式。了解你想要什么,并防止实现做一些愚蠢的事情是很好的。 OpenGL甚至有一些大小为required to be supported explicitly as stated的格式。