Zeb*_*ish 2 c++ opengl gamma framebuffer
这是我的问题,当我加载纹理时,我将它们作为SRGB加载,以将它们转换为线性空间.当我写入窗口系统提供的默认帧缓冲区时,我启用了GL_FRAMEBUFFER_SRGB,以便写入帧缓冲区将颜色从线性空间转换为SRGB空间.
现在的问题是我正在渲染到屏幕外的FBO,然后将其blit到默认的帧缓冲区.执行此操作时,打开或关闭GL_FRAMEBUFFER_SRGB无效.我尝试使用默认的帧缓冲区绑定启用GL_FRAMEBUFFER_SRGB,并且使用屏幕外FBO绑定,它们不起作用.
但是,如果我将GL_SRGB指定为我作为屏幕外FBO的颜色缓冲区绑定的纹理的内部格式,则可以起作用.我假设在这种情况下启用GL_FRAMEBUFFER_SRGB时,从片段着色器到纹理的写入将其从线性空间转换为SRGB空间.
我想知道,从FBO到默认帧缓冲区的blit似乎没有应用GL_FRAMEBUFFER_SRGB转换.因为我想在线性空间中工作,直到最后转移到默认帧缓冲区的后备缓冲区,我如何应用转换,因为我将屏幕外FBO blit到默认帧缓冲区?我想将屏幕外FBO作为纹理采样并在默认帧缓冲区上渲染四边形将应用SRGB转换,但是没有办法用framebufferblit进行这种转换吗?
打开
GL_FRAMEBUFFER_SRGB或关闭此功能时无效.我已经尝试GL_FRAMEBUFFER_SRGB使用默认的帧缓冲区绑定启用它们,并且使用屏幕外FBO绑定,它们不起作用.
GL_FRAMEBUFFER_SRGB没有什么你认为它的作用:它不把任何对应的FrameBuffer 格式从RGB为sRGB.
GL_FRAMEBUFFER_SRGB当已经指定了帧缓冲区的格式将只具有任何作用sRGB,例如,通过附加纹理internalFormat的GL_SRGB8或GL_SRGB8_ALPHA8作为颜色缓冲器到FBO.如果您希望sRGB转换为默认帧缓冲区,则必须使用特定于窗口系统的API来明确创建PixelFormat/Visual/FBConfig /支持sRGB的任何内容.看看有关如何做到这一点的GL / GLX / WGL _ARB_FRAMEBUFFER_SRGB扩展规范.
但是,如果我
GL_SRGB将纹理的内部格式指定为屏幕外FBO的颜色缓冲区,那么该怎么办呢?我假设在这种情况下GL_FRAMEBUFFER_SRGB启用从片段着色器到纹理的写入将其从线性空间转换为SRGB空间.
是的,这正是应该如何运作的.该GL_FRAMEBUFFER_SRGB使能位仅仅是一种手段禁止在格式通常会做他们,而不是周围的其他方式SRGB转换.
我想知道,从FBO到默认帧缓冲区的blit似乎没有应用GL_FRAMEBUFFER_SRGB转换.
让我们来看看迄今为止最新的OpenGL规范:OpenGL 4.6核心配置文件规范,第18.3.1节"Blitting Pixel Rectangles"(强调我的):
当从读缓冲区获取值时,如果
FRAMEBUFFER_SRGB启用并且FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING对应于读缓冲区的帧缓冲附件的值 是SRGB(参见第9.2.3节),则红色,绿色和蓝色分量将从非线性sRGB转换颜色空间根据公式8.17.当值写入绘制缓冲区时,blit操作会绕过大部分片段管道.影响blit的唯一片段操作是像素所有权测试,剪刀测试和sRGB转换(参见17.3.7节).颜色,深度和模板掩模(参见第17.4.2节)将被忽略
第17.3.7节"sRGB转换"说明:
如果
FRAMEBUFFER_SRGB启用并且与FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING目标缓冲区对应的帧缓冲附件的值为SRGB(参见第9.2.3节),则混合后的R,G和B值将通过[公式如下]转换为非线性sRGB颜色空间. ..]
请注意,第17.3.7节将明确指出,在写入颜色缓冲区时,只有在GL_FRAMEBUFFER_SRGB启用时才会应用线性到sRGB转换.
所以这给我们留下了以下可能性:
源和目标颜色缓冲区都具有标准的NON-sRGB格式:blit将复制像素值,无论如何GL_FRAMEBUFFER_SRGB设置,都不会发生sRGB转换.
源缓冲区具有sRGB格式,目标具有NON-sRGB格式.当且仅当 GL_FRAMEBUFFER_SRGB启用时,才会执行从sRGB到线性的转换.
源缓冲区具有NON-sRGB格式,目标具有sRGB格式.当且仅当 GL_FRAMEBUFFER_SRGB启用时,才会执行从线性到sRGB的转换.
源和目标都有sRGB格式.当且仅当 GL_FRAMEBUFFER_SRGB启用时,才会执行从sRGB到线性AND线性到sRGB的转换.请注意,转换可能会归结为此处的无操作.这包括双线性滤波的情况:GL规范不要求在转换后在线性空间中应用sRGB源上的双线性滤波,它也可以在之前应用.
现在,故事可能就在这里.但事实并非如此.具有sRGB格式的帧缓冲区blits的行为在GL历史记录中经历了许多变化.
第18.3.1节OpenGL 4.3核心配置文件规范确实说明:
当从读缓冲区获取值时,如果
FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING对应于读缓冲区的帧缓冲附件的值 是SRGB(参见第9.2.3节),则红色,绿色和蓝色分量将根据非线性sRGB颜色空间进行转换.等式[第二段与4.6之前的qoute相同]
这意味着直到GL 4.3,源缓冲区的转换始终在具有sRGB格式时进行,无论GL_FRAMEBUFFER_SRGB启用设置如何.但是,对于目标缓冲区,此设置仍然相关.
现在在OpenGL 3.3中,没有提到使用sRGB格式进行blitting的行为.相关部分是4.3.2"复制像素",仅说明:
Blit操作绕过片段管道.影响blit的唯一片段操作是像素所有权测试和剪刀.
这意味着它还将绕过目标缓冲区的线性到sRGB转换,并且根本不会声明源转换.
此外,驱动程序在历史上也忽略了规范并且在sRGB转换方面做了他们认为最好的事情.例如,参见artice"2015年3月OpenGL驱动程序状态和FB sRGB转换".小猪OpenGL测试套件还有一个很好的补丁,它讨论了问题并提出了一些有些令人悲伤的结论:
我认为简短的总结是:OpenGL中的sRGB几乎和它可能的一样破碎.:(至少,我曾经谈过的每个游戏开发者都这么告诉我.呃.
但是,根据我的经验,大多数当前的GL> = 4.4驱动程序按规定执行转换,因此情况不再那么糟糕.但我也不会打赌我的生活.