Closed. This question needs debugging details。它当前不接受答案。
想要改善这个问题吗?更新问题,以便将其作为on-topic用于堆栈溢出。
3年前关闭。
Improve this question
这是我的问题,当我加载纹理时,将它们作为SRGB加载以将它们转换为线性空间。当我写入窗口系统提供的默认帧缓冲区时,我启用了GL_FRAMEBUFFER_SRGB,以便写入帧缓冲区会将颜色从线性空间转换为SRGB空间。
现在的问题是,我正在渲染到屏幕外的FBO中,然后将其涂抹到默认的帧缓冲区中。这样做时,打开或关闭GL_FRAMEBUFFER_SRGB无效。我尝试使用默认帧缓冲区绑定(bind)和屏幕外FBO绑定(bind)启用GL_FRAMEBUFFER_SRGB,它们不起作用。
但是,如果我将GL_SRGB指定为绑定(bind)为屏幕外FBO的颜色缓冲区的纹理的内部格式,则起作用了。我假设在这种情况下,当启用GL_FRAMEBUFFER_SRGB时,从片段着色器到纹理的写入会将其从线性空间转换为SRGB空间。
我想知道,似乎没有从FBO向默认帧缓冲区发送GL_FRAMEBUFFER_SRGB转换。由于我想在线性空间中工作,直到最终传输到默认帧缓冲区的后缓冲区,如何在将屏幕外FBO涂抹到默认帧缓冲区时如何应用转换?我猜想将屏幕外FBO采样为纹理并在默认帧缓冲区上渲染四边形会应用SRGB转换,但是没有办法使用framebufferblit进行此转换吗? 源和目标颜色缓冲区均具有标准的NON-sRGB格式:blit将复制像素值,无论 源缓冲区的格式为sRGB,目标缓冲区的格式为NON-sRGB。仅在启用了 源缓冲区为NON-sRGB格式,目标缓冲区为sRGB格式。只有在启用了 源和目标都具有sRGB格式。只有在启用了
现在,故事可能就在这里。但事实并非如此。具有sRGB格式的帧缓冲区blit的行为在GL历史中发生了许多变化。
第18.3.1节OpenGL 4.3 core profile specification确实声明:
这意味着在GL 4.3以下版本中,无论
现在在OpenGL 3.3中,没有提及使用sRGB格式进行blitting的行为。相关部分为4.3.2“复制像素”,并且仅规定:
这意味着它还将绕过目标缓冲区的线性到sRGB转换,并且完全不对源转换做任何声明。
同样不是说驱动程序在历史上也没有忽略规范,而是在进行sRGB转换时做了他们认为最好的事情。参见例如the artice "March 2015 OpenGL drivers status and FB sRGB conversions"。也有this nice patch to the piglet OpenGL test suite谈论问题并提出了某种可悲的想法:
但是,以我的经验,大多数当前的GL> = 4.4驱动程序都按照指定的方式进行转换,因此情况不再那么糟糕。但是,我也不会一辈子下注。
想要改善这个问题吗?更新问题,以便将其作为on-topic用于堆栈溢出。
3年前关闭。
Improve this question
这是我的问题,当我加载纹理时,将它们作为SRGB加载以将它们转换为线性空间。当我写入窗口系统提供的默认帧缓冲区时,我启用了GL_FRAMEBUFFER_SRGB,以便写入帧缓冲区会将颜色从线性空间转换为SRGB空间。
现在的问题是,我正在渲染到屏幕外的FBO中,然后将其涂抹到默认的帧缓冲区中。这样做时,打开或关闭GL_FRAMEBUFFER_SRGB无效。我尝试使用默认帧缓冲区绑定(bind)和屏幕外FBO绑定(bind)启用GL_FRAMEBUFFER_SRGB,它们不起作用。
但是,如果我将GL_SRGB指定为绑定(bind)为屏幕外FBO的颜色缓冲区的纹理的内部格式,则起作用了。我假设在这种情况下,当启用GL_FRAMEBUFFER_SRGB时,从片段着色器到纹理的写入会将其从线性空间转换为SRGB空间。
我想知道,似乎没有从FBO向默认帧缓冲区发送GL_FRAMEBUFFER_SRGB转换。由于我想在线性空间中工作,直到最终传输到默认帧缓冲区的后缓冲区,如何在将屏幕外FBO涂抹到默认帧缓冲区时如何应用转换?我猜想将屏幕外FBO采样为纹理并在默认帧缓冲区上渲染四边形会应用SRGB转换,但是没有办法使用framebufferblit进行此转换吗?
最佳答案
GL_FRAMEBUFFER_SRGB
与您认为的不符:而不是将frambuffer格式从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
extension spec的操作方法。
是的,这正是它应该如何工作的方式。 GL_FRAMEBUFFER_SRGB
启用位仅是一种禁用通常会进行格式转换的SRGB转换的方法,而并非相反。
让我们看一下迄今为止最新的OpenGL规范:OpenGL 4.6 core profile specification,第18.3.1节“加宽像素矩形”(重点是我的):
在第17.3.7节“sRGB转换”中指出:
请注意,第17.3.7节将明确指出,在写入颜色缓冲区时,仅在启用GL_FRAMEBUFFER_SRGB
的情况下才会应用线性到sRGB的转换。
因此,这为我们提供了以下可能性:
GL_FRAMEBUFFER_SRGB
的设置如何,均不会发生sRGB转换。 GL_FRAMEBUFFER_SRGB
的情况下,才能完成从sRGB到线性的转换。 GL_FRAMEBUFFER_SRGB
的情况下,才能完成从线性到sRGB的转换。 GL_FRAMEBUFFER_SRGB
的情况下,才能完成从sRGB到线性AND到sRGB的转换。请注意,此处的转换可能会变成无操作。这也包括使用双线性过滤的情况:GL规范不需要在转换后将sRGB源上的双线性过滤应用于线性空间,也可以在转换之前应用它。 现在,故事可能就在这里。但事实并非如此。具有sRGB格式的帧缓冲区blit的行为在GL历史中发生了许多变化。
第18.3.1节OpenGL 4.3 core profile specification确实声明:
这意味着在GL 4.3以下版本中,无论
GL_FRAMEBUFFER_SRGB
enable的设置如何,总是在具有sRGB格式时完成源缓冲区的转换。对于目标缓冲区,此设置仍然有用。现在在OpenGL 3.3中,没有提及使用sRGB格式进行blitting的行为。相关部分为4.3.2“复制像素”,并且仅规定:
这意味着它还将绕过目标缓冲区的线性到sRGB转换,并且完全不对源转换做任何声明。
同样不是说驱动程序在历史上也没有忽略规范,而是在进行sRGB转换时做了他们认为最好的事情。参见例如the artice "March 2015 OpenGL drivers status and FB sRGB conversions"。也有this nice patch to the piglet OpenGL test suite谈论问题并提出了某种可悲的想法:
但是,以我的经验,大多数当前的GL> = 4.4驱动程序都按照指定的方式进行转换,因此情况不再那么糟糕。但是,我也不会一辈子下注。
10-04 11:28