Search code examples
openglframebuffermultisampling

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


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?


Solution

  • 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.