OpenGL不会渲染到Framebuffer而是渲染到Window

时间:2016-12-26 23:03:18

标签: c# opengl framebuffer

我的问题是OpenGL渲染到主窗口,虽然我绑定了我想要使用的Framebuffer。

这是我的主渲染方法

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

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

    SwapBuffers();
}

这是我的渲染器

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;
    }

}

这是我的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);
    }
}

预期的结果是黑色四边形,因为当我发现我的模型仍然呈现在屏幕上时,我一直在实现Texturing。当我在EndRendering()中调出GL.DrawElements调用时,我发现了这一点,它应该将四边形渲染到屏幕上。当我现在不画那个四边形时,图像仍然出现。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

渲染缓冲区不是帧缓冲对象:

  

frameBufferID = GL.GenRenderbuffer();

当您尝试绑定从glGenRenderbuffers作为帧缓冲区获取的ID时,您将从GL_INVALID_OPERATION收到glBindFramebuffer()错误,该命令将不会产生进一步的影响(离开默认帧缓冲区绑定)。

新的FBO名称是通过glGenFramebuffers生成的,因此您应该使用它。