OpenGL doesn't render to Framebuffer but to Window

167 views Asked by At

My problem is that OpenGL renders to the Main-Window, although I bound the Framebuffer I want to use.

This is my Main Rendering-Method

protected override void OnRenderFrame(FrameEventArgs e)
{
    base.OnRenderFrame(e);

    renderer.BeginFrame();
    renderer.RenderEntity(testEntity);
    renderer.EndFrame();

    SwapBuffers();
}

This is my Renderer

class Renderer
{
    List<Vertex> screenQuadVertecies = new List<Vertex>
    {
        new Vertex(new Vector3(-1, 1, 0), new Vector3()),
        new Vertex(new Vector3(1, 1, 0), new Vector3()),
        new Vertex(new Vector3(-1, -1, 0), new Vector3()),
        new Vertex(new Vector3(1, -1, 0), new Vector3())
    };

    List<int> screenQuadIndices = new List<int>
    {
        0, 1, 2,
        1, 2, 3
    };

    List<Vector2> screenQuadUVs = new List<Vector2>
    {
        new Vector2(0, 0),
        new Vector2(1, 0),
        new Vector2(0, 1),
        new Vector2(1, 1)
    };

    TexturedMesh screenQuad;

    Framebuffer mainPassFramebuffer;

    Camera activeCamera;
    Shader ModelShader;
    Shader PostProcessingShader;

    int width, height;

    public Renderer(int width, int height)
    {
        this.width = width;
        this.height = height;

        ModelShader = new MainShader();
        PostProcessingShader = new PostProcessingShader();
        mainPassFramebuffer = new Framebuffer(width, height);
        screenQuad = new TexturedMesh(screenQuadVertecies, screenQuadIndices, screenQuadUVs);
    }

    public void BeginFrame()
    {
        mainPassFramebuffer.EndRendering();
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
        mainPassFramebuffer.ClearBuffer();
        mainPassFramebuffer.BeginRendering();
    }

    public void EndFrame()
    {
        mainPassFramebuffer.EndRendering();
        mainPassFramebuffer.BindTexture();
        PostProcessingShader.UseShader();
        screenQuad.PrepareRendering();
        GL.DrawElements(PrimitiveType.Triangles, 6, DrawElementsType.UnsignedInt, 0);
        screenQuad.EndRendering();
        PostProcessingShader.UnuseShader();
    }

    public void RenderEntity(Entity e)
    {
        e.Mesh.PrepareRendering();
        ModelShader.UseShader();
        ModelShader.LoadCamera(activeCamera);
        ModelShader.LoadModel(e.GetModelMatrix());
        GL.DrawElements(PrimitiveType.Triangles, e.Mesh.GetSize(), DrawElementsType.UnsignedInt, 0);
        ModelShader.UnuseShader();
    }

    public void RenderTerrain(Terrain t)
    {
        foreach (var chunk in t.chunks)
        {
            RenderEntity(chunk.GetEntity());
        }
    }

    public void SetActiveCamera(Camera camera)
    {
        activeCamera = camera;
    }

}

And this is my Framebuffer Class

class Framebuffer
{
    int frameBufferID;
    int textureID;

    int width, height;

    public Framebuffer(int width, int height)
    {
        this.width = width;
        this.height = height;

        frameBufferID = GL.GenRenderbuffer();
        GL.BindFramebuffer(FramebufferTarget.Framebuffer, frameBufferID);
        textureID = CreateTexture();
        GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, textureID, 0);
        GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
    }

    protected int CreateTexture()
    {
        int returnID;

        returnID = GL.GenTexture();
        GL.BindTexture(TextureTarget.Texture2D, returnID);

        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, width, height, 0, PixelFormat.Rgb, PixelType.UnsignedByte, (IntPtr)0);

        int nearest = (int)TextureMagFilter.Nearest;
        GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, ref nearest);
        GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, ref nearest);

        return returnID;
    }

    public void BeginRendering()
    {
        GL.BindFramebuffer(FramebufferTarget.Framebuffer, frameBufferID);
        GL.Viewport(new System.Drawing.Point(0, 0), new System.Drawing.Size(width, height));
    }

    public void EndRendering()
    {
        GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
    }

    public void BindTexture()
    {
        GL.BindTexture(TextureTarget.Texture2D, textureID);
    }

    public void ClearBuffer()
    {
        GL.BindFramebuffer(FramebufferTarget.Framebuffer, frameBufferID);
        GL.Viewport(new System.Drawing.Point(0, 0), new System.Drawing.Size(width, height));
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
        GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
    }
}

The expected result is a black quad because I have been implementing Texturing when I discovered that my Model still renders to the screen. I found that out when I commentend out the GL.DrawElements call in EndRendering() which should render the quad to the screen. When I now don't draw that quad the image still appears.

What am I doing wrong?

1

There are 1 answers

1
derhass On BEST ANSWER

A render buffer is not a framebuffer object:

frameBufferID = GL.GenRenderbuffer();

When you try to bind an ID you got from glGenRenderbuffers as a framebuffer, you will get an GL_INVALID_OPERATION error from glBindFramebuffer(), and the command will have no further effect (leaving the default framebuffer bound).

New FBO names are generated via glGenFramebuffers, so you should use that.