【问题标题】:OpenGL doesn't render to Framebuffer but to WindowOpenGL 不渲染到 Framebuffer 而是渲染到 Window
【发布时间】:2016-12-26 23:03:18
【问题描述】:

我的问题是 OpenGL 渲染到主窗口,尽管我绑定了我想使用的帧缓冲区。

这是我的主要渲染方法

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

}

这是我的帧缓冲类

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

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

我做错了什么?

【问题讨论】:

    标签: c# opengl framebuffer


    【解决方案1】:

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

    frameBufferID = GL.GenRenderbuffer();

    当您尝试将您从 glGenRenderbuffers 获得的 ID 绑定为帧缓冲区时,您将从 glBindFramebuffer() 收到 GL_INVALID_OPERATION 错误,并且该命令将没有进一步的效果(保留默认的帧缓冲区绑定)。

    新的 FBO 名称是通过 glGenFramebuffers 生成的,所以你应该使用它。

    【讨论】:

    • 哦,天哪,愚蠢的错误......我刚刚关闭了我的电脑,所以明天我会试试。感谢您阅读这些乱七八糟的代码!
    猜你喜欢
    • 2014-07-22
    • 2015-04-08
    • 1970-01-01
    • 1970-01-01
    • 2013-11-25
    • 2015-10-25
    • 1970-01-01
    • 2023-03-30
    • 2020-11-14
    相关资源
    最近更新 更多