19

I have a rendering system where I draw to an FBO with a multisampled renderbuffer, then blit it to another FBO with a texture in order to resolve the samples in order to read off the texture to perform post-processing shading while drawing to the backbuffer (FBO index 0).

Now I'd like to get some correct sRGB output... The problem is the behavior of the program is rather inconsistent between when I run it on OS X and Windows and this also changes depending on the machine: On Windows with the Intel HD 3000 it will not apply the sRGB nonlinearity but on my other machine with a Nvidia GTX 670 it does. On the Intel HD 3000 in OS X it will also apply it.

So this probably means that I'm not setting my GL_FRAMEBUFFER_SRGB enable state at the right points in the program. However I can't seem to find any tutorials that actually tell me when I ought to enable it, they only ever mention that it's dead easy and comes at no performance cost.

I am currently not loading in any textures so I haven't had a need to deal with linearizing their colors yet.

To force the program to not simply spit back out the linear color values, what I have tried is simply comment out my glDisable(GL_FRAMEBUFFER_SRGB) line, which effectively means this setting is enabled for the entire pipeline, and I actually redundantly force it back on every frame.

I don't know if this is correct or not. It certainly does apply a nonlinearization to the colors but I can't tell if this is getting applied twice (which would be bad). It could apply the gamma as I render to my first FBO. It could do it when I blit the first FBO to the second FBO. Why not?

I've gone so far as to take screen shots of my final frame and compare raw pixel color values to the colors I set them to in the program:

I set the input color to RGB(1,2,3) and the output is RGB(13,22,28).

That seems like quite a lot of color compression at the low end and leads me to question if the gamma is getting applied multiple times.

I have just now gone through the sRGB equation and I can verify that the conversion seems to be only applied once as linear 1/255, 2/255, and 3/255 do indeed map to sRGB 13/255, 22/255, and 28/255 using the equation 1.055*C^(1/2.4)+0.055. Given that the expansion is so large for these low color values it really should be obvious if the sRGB color transform is getting applied more than once.

So, I still haven't determined what the right thing to do is. does glEnable(GL_FRAMEBUFFER_SRGB) only apply to the final framebuffer values, in which case I can just set this during my GL init routine and forget about it hereafter?

4

1 回答 1

26

启用后,对具有 sRGB 图像格式GL_FRAMEBUFFER_SRGB的图像的所有写入都将假定输入颜色(正在写入的颜色)在线性颜色空间中。因此,它将它们转换为 sRGB 颜色空间。

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

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

至于这个:

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

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

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

于 2012-07-08T21:21:49.303 回答