Search code examples
openglopentkmultisampling

Multisampling framebuffer incomplete and I don't know why


this my code to create a "Surface":

private void Create(int width, int height, SurfaceFormat format)
{
    bool multisample = format.Multisample > 1;
    if (multisample)
        GL.Enable(EnableCap.Multisample);
    int samples = Math.Max(1, Math.Min(format.Multisample, 4));
    TextureTarget target = multisample ? TextureTarget.Texture2DMultisample : TextureTarget.Texture2D;
    Width = width;
    Height = height;
    textureHandle = GL.GenTexture();
    //bind texture

    GL.BindTexture(target, textureHandle);
    Log.Error("Bound Texture: " + GL.GetError());
    if (!multisample)
    {
        GL.TexParameter(target, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
        GL.TexParameter(target, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
        GL.TexParameter(target, TextureParameterName.TextureWrapS, (int)format.WrapMode);
        GL.TexParameter(target, TextureParameterName.TextureWrapT, (int)format.WrapMode);
    }

    Log.Debug("Created Texture Parameters: " + GL.GetError());
    if (format.Multisample < 2)
        GL.TexImage2D(target, 0, format.InternalFormat, Width, Height, 0, format.PixelFormat, format.SourceType, format.Pixels);
    else
        GL.TexImage2DMultisample(TextureTargetMultisample.Texture2DMultisample, samples, format.InternalFormat, Width, Height, false);
    Log.Debug("Created Image: " + GL.GetError());
    //unbind texture
    GL.BindTexture(target, 0);
    //create depthbuffer
    if (format.DepthBuffer)
    {
        GL.GenRenderbuffers(1, out dbHandle);
        GL.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, dbHandle);

        if(multisample)
            GL.RenderbufferStorageMultisample(RenderbufferTarget.RenderbufferExt, samples, RenderbufferStorage.Rgba8, Width, Height);
        else
            GL.RenderbufferStorage(RenderbufferTarget.RenderbufferExt, RenderbufferStorage.DepthComponent24, Width, Height);
    }

    //create fbo
    fboHandle = GL.GenFramebuffer();
    GL.BindFramebuffer(FramebufferTarget.FramebufferExt, fboHandle);
    GL.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0Ext, target, textureHandle, 0);

    if(format.DepthBuffer)
        GL.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, FramebufferAttachment.DepthAttachmentExt, RenderbufferTarget.RenderbufferExt, dbHandle);
    Log.Debug("Framebuffer status: " + GL.CheckFramebufferStatus(FramebufferTarget.FramebufferExt));
    Log.Debug("Created Framebuffer: " + GL.GetError());
    GL.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);

}

Now whenever I use multisampling greater than 1, I will get an error:

[LOG]: Created Texture Parameters: NoError
[LOG]: Created Image: NoError
[LOG]: Framebuffer status: FramebufferIncompleteAttachment

When ms is less than 2, everything works fine...


Solution

  • You're using an invalid format for your renderbuffer here:

    GL.RenderbufferStorageMultisample(RenderbufferTarget.RenderbufferExt, samples,
           RenderbufferStorage.Rgba8, Width, Height);
    

    You later try to use this buffer as a depth attachment. GL_RGBA8 is not a valid format for a depth attachment. Commonly used formats for depth attachments are GL_DEPTH_COMPONENT16 and GL_DEPTH_COMPONENT24. So the call should be changed to:

    GL.RenderbufferStorageMultisample(RenderbufferTarget.RenderbufferExt, samples,
           RenderbufferStorage.DepthComponent24, Width, Height);