为啥在使用 FBO 进行多重采样时,OpenGL 会使我的场景变亮?

Posted

技术标签:

【中文标题】为啥在使用 FBO 进行多重采样时,OpenGL 会使我的场景变亮?【英文标题】:Why does OpenGL lighten my scene when multisampling with an FBO?为什么在使用 FBO 进行多重采样时,OpenGL 会使我的场景变亮? 【发布时间】:2012-02-01 23:23:12 【问题描述】:

我刚刚将我的 OpenGL 绘图代码从直接绘制到显示切换到使用附加了渲染缓冲区的屏幕外 FBO。当我分配正常的渲染缓冲区存储时,屏幕外 FBO 被正确地传送到屏幕上。

但是,当我在渲染缓冲区上启用多重采样(通过 glRenderbufferStorageMultisample)时,场景中的每种颜色似乎都已变亮(因此提供的颜色与非多重采样部分不同)。

我怀疑我需要设置一些 glEnable 选项以保持相同的颜色,但我似乎在其他地方找不到任何提及此问题的内容。

有什么想法吗?

【问题讨论】:

您能否提供问题的快照和预期的正确结果? 【参考方案1】:

我偶然发现了同样的问题,因为由于样本位置不匹配而缺乏适当的下采样。对我有用的是:

一个单独的“单样本”FBO,具有相同的附件、格式和尺寸(附有纹理或渲染缓冲区),用于进行下采样,然后将其绘制/blit 到窗口缓冲区 通过使用 GLSL 片段着色器传递每个片段的所有对应样本,使用具有与输入相同样本计数的多样本纹理渲染到多样本窗口缓冲区。这在启用样本着色的情况下工作,并且是延迟着色的过度杀伤方法,因为您可以计算每个样本的光、阴影、AO 等。 我还使用 GLSL 对单个样本帧缓冲区进行了相当草率的手动下采样,我不得不使用 texelFetch() 分别获取每个样本。

多重采样让事情变得非常缓慢。尽管 CSAA 的性能优于 MSAA,但我建议将 FXAA 着色器作为后处理的一个重要替代方案,当性能成为问题或所需的那些相当新的扩展(例如 ARB_texture_multisample)不可用时。

在 GLSL 中访问示例:

vec4 texelDownsampleAvg(sampler2DMS sampler,ivec2 texelCoord,const int sampleCount)

    vec4 accum = texelFetch(sampler,texelCoord,0);
    for(int sample = 1; sample < sampleCount; ++sample) 
        accum += texelFetch(sampler,texelCoord,sample);
    
    return accum / sampleCount;

http://developer.download.nvidia.com/opengl/specs/GL_EXT_framebuffer_multisample.txt

http://developer.download.nvidia.com/opengl/specs/GL_EXT_framebuffer_blit.txt

11) 不同位大小的缓冲区之间是否应该允许 blits?

Resolved: Yes, for color buffers only.  Attempting to blit
between depth or stencil buffers of different size generates
INVALID_OPERATION.

13) BlitFramebuffer色彩空间转换应该如何进行 指定的?我们是否允许上下文钳位状态影响 闪电战?

Resolved: Blitting to a fixed point buffer always clamps,
blitting to a floating point buffer never clamps.  The context
state is ignored.

http://www.opengl.org/registry/specs/ARB/sample_shading.txt

Blitting multisampled FBO with multiple color attachments in OpenGL

【讨论】:

【参考方案2】:

对我有用的解决方案是更改渲染缓冲区颜色格式。我选择了GL_RGBA32FGL_DEPTH_COMPONENT32F(认为我想要最高精度),而 NVIDIA 驱动程序对此的解释不同(我怀疑 sRGB 补偿,但我可能是错的)。

我发现可以使用的渲染缓冲区图像格式是 GL_RGBA8GL_DEPTH_COMPONENT24

【讨论】:

听起来,好像这种格式等于您窗口的像素格式,其中颜色格式转换可能是您所说的原因。我已经使用 GLSL sn-p 将 RGB16F 转换为 RGB8,其中可以隐含转换。即便如此,我还看不到 sRGB 的原因,因为这肯定是驱动程序优化错误,因为 sRGB 有专门的扩展。 那是我不理解的部分。您的解决方案比我需要的解决方案更普遍,但它是更正确的答案。 我不声称我的答案是正确的,只要我自己不知道确切的原因。使用 GLSL 进行下采样是一种效率低下的解决方法,而不是我认为是“最先进”的任何方法。 另一个想法是,你的 alpha 值会发生什么?是否有任何混合或 alpha 测试/功能处于活动状态?如果您渲染成多重采样 RGB32F 或禁用这些测试会发生什么?我会尽快试用。

以上是关于为啥在使用 FBO 进行多重采样时,OpenGL 会使我的场景变亮?的主要内容,如果未能解决你的问题,请参考以下文章

将OpenGL帧缓冲区对象与Qt(QOpenGLWidget)一起使用,绘制到帧缓冲区时如何禁用多重采样

激活多重采样(Windows)时如何防止空的OpenGL窗口?

SDL/opengl 多重采样不起作用

OpenGL 如何解析像素格式基于整数的多采样 FBO 附加颜色缓冲区?

使用 Android 上的 OpenGL ES 2.0,在帧缓冲区上渲染时是不是可以保留多重采样?

glReadPixels() 设置 GL_INVALID_OPERATION 错误