我有一个渲染系统,先使用多重采样的渲染缓冲区(FBO)进行绘图,然后再使用纹理将其复制到另一个FBO中以解析采样并读取纹理,从而在绘制到背景缓冲区(即FBO索引0)时执行后处理阴影。
现在我想获得一些正确的sRGB输出...问题是程序的行为在OS X和Windows上相当不一致,这也取决于计算机:在具有Intel HD 3000的Windows上,它不会应用sRGB非线性度量,但在我的其他Nvidia GTX 670计算机上却会应用。 在OS X上的Intel HD 3000也会应用它。
这可能意味着我没有在程序的正确点设置GL_FRAMEBUFFER_SRGB
启用状态。但是,我似乎找不到任何真正告诉我何时应该启用它的教程,他们只是提到它很容易,并且不需要付出性能代价。
我目前没有加载任何纹理,因此我没有必要处理线性化它们的颜色。
为了强制程序不仅仅回显线性颜色值,我尝试注释掉我的glDisable(GL_FRAMEBUFFER_SRGB)
行,这实际上意味着此设置在整个管道中都已启用,并且我实际上每帧都多余地强制它重新启用。
我不知道这是否正确。 它确实对颜色应用了非线性度量,但我不能确定这是否被应用了两次(这将是不好的)。 它可以在我渲染到第一个FBO时应用gamma。 它可以在我将第一个FBO复制到第二个FBO时应用gamma。 为什么不呢?
我甚至进行了屏幕截图,比较最终帧的原始像素颜色值与程序中设置的颜色:
我将输入颜色设置为RGB(1,2,3),输出为RGB(13,22,28)。
这似乎是低端颜色压缩很大,并让我怀疑gamma是否被多次应用。
我刚刚仔细研究了sRGB方程,可以确认转换似乎只应用了一次,因为线性的1/255、2/255和3/255确实使用方程1.055*C^(1/2.4)+0.055
映射到sRGB中的13/255、22/255和28/255。由于这些低颜色值的扩展非常大,如果sRGB颜色变换被应用多次,那么这应该是显而易见的。
所以,我仍然没有确定正确的做法。在这种情况下,glEnable(GL_FRAMEBUFFER_SRGB)
是否只适用于最终帧缓冲区的值?如果是这样的话,我可以在我的GL初始化程序中设置它,然后忘记它吗?
GL_FRAMEBUFFER_SRGB
并且在此之后永远不再触碰它时,即使在Windows中使用Intel HD 3000,它也会执行正确的转换。只是似乎需要在更多的代码路径上启用它,而不仅仅是在Nvidia上。 - Steven Lu