Why does OpenGL lighten my scene when multisampling with an FBO?

1.3k views Asked by At

I just switched my OpenGL drawing code from drawing to the display directly to using an off-screen FBO with render buffers attached. The off-screen FBO is blitted to the screen correctly when I allocate normal render buffer storage.

However, when I enable multisampling on the render buffers (via glRenderbufferStorageMultisample), every color in the scene seems like it has been brightened (thus giving different colors than the non-multisampled part).

I suspect there's some glEnable option that I need to set to maintain the same colors, but I can't seem to find any mention of this problem elsewhere.

Any ideas?

2

There are 2 answers

0
Sam On BEST ANSWER

I stumbled upon the same problem, due to the lack of proper downsampling because of mismatching sample locations. What worked for me was:

  • A separate "single sample" FBO with identical attachments, format and dimension (with texture or renderbuffer attached) to blit into for downsampling and then draw/blit this to the window buffer
  • Render into a multisample window buffer with multisample texture having the same sample count as input, by passing all corresponding samples per fragment using a GLSL fragment shader. This worked with sample shading enabled and is the overkill approach for deferred shading as you can calculate light, shadow, AO, etc. per sample.
  • I did also rather sloppy manual downsampling to single sample framebuffers using GLSL, where I had to fetch each sample separately using texelFetch().

Things got really slow with multisampling. Although CSAA performed better than MSAA, I recommend to take a look at FXAA shaders for postprocessing as a considerable alternative, when performance is an issue or those rather new extensions required, such as ARB_texture_multisample, are not available.

Accessing samples in 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;
}

11) Should blits be allowed between buffers of different bit sizes?

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

13) How should BlitFramebuffer color space conversion be specified? Do we allow context clamp state to affect the blit?

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

The solution that worked for me was changing the renderbuffer color format. I picked GL_RGBA32F and GL_DEPTH_COMPONENT32F (figuring that I wanted the highest precision), and the NVIDIA drivers interpret that differently (I suspect sRGB compensation, but I could be wrong).

The renderbuffer image formats I found to work are GL_RGBA8 with GL_DEPTH_COMPONENT24.