OpenGL - 渲染到纹理 - 总是黑屏

OpenGL - Render to texture - always blackscreen

我是 OpenGL 的新手,我正在研究 Voxelengine。我想将当前场景渲染为纹理,然后在四边形上渲染该纹理。问题是我总是黑屏。当我将碎片颜色输出乘以 5 时,我的屏幕变成灰色。因此我认为问题是,纹理没有得到我的渲染器的输出。直接渲染到默认渲染器工作正常,所以我认为这是我的 fbo 的问题。

Renderer.h:

public ref class DefaultRenderer : RendererBase, IRenderer
    {
    public:

    internal:

    protected:

    private:
        EngineCore::Graphics::GraphicController* GraphicControl_;
        Controllers::CameraControl^ CameraControl_;
        Controllers::ColorPaletteControl^ ColorPaletteControl_;
        Controllers::LightControl^ LightControl_;

        unsigned int texture_;
        unsigned int FBO_;
        unsigned int RBO_;
        unsigned int quadVAO_;
        unsigned int quadVBO_;

        array<float>^ quadVertices_;

        EngineCore::Graphics::Shaders::ShaderProgram* screenShader_;


        bool IsShadowsEnabled_ = false;         // At the moment not used / not implemented
        bool IsSkyBoxEnabled_ = true;           // At the moment not used / not implemented
        bool IsBloomEnabled_ = false;           // At the moment not used / not implemented
        bool IsToneMappingEnabled_ = false;     // At the moment not used / not implemented
        bool IsFxaaEnabled_ = false;            // At the moment not used / not implemented

    public:
        DefaultRenderer() {};
        ~DefaultRenderer() {
            this->!DefaultRenderer();
        };
        !DefaultRenderer() {};

    internal:

    protected:

    private:


    public:
        /// <summary>
        /// Enables Shadows
        /// </summary>
        virtual void EnableShadows();
        /// <summary>
        /// Disables Shadows
        /// </summary>
        virtual void DisableShadows();
        /// <summary>
        /// Enables Skybox
        /// </summary>
        virtual void EnableSkyBox();
        /// <summary>
        /// Disables Skyboy
        /// </summary>
        virtual void DisableSkyBox();
        /// <summary>
        /// Enables Bloom
        /// </summary>
        virtual void EnableBloom();
        /// <summary>
        /// Disables Bloom
        /// </summary>
        virtual void DisableBloom();
        /// <summary>
        /// Enables ToneMapping
        /// </summary>
        virtual void EnableToneMapping();
        /// <summary>
        /// Disables ToneMapping
        /// </summary>
        virtual void DisableToneMapping();
        /// <summary>
        /// Enables Fxaa
        /// </summary>
        virtual void EnableIsFxaa();
        /// <summary>
        /// Disables Fxaa
        /// </summary>
        virtual void DisableIsFxaa();
        /// <summary>
        /// This function enable the use of ColorPalette in the PBR-Rendering
        /// and disables the use of Texturing for World-Elements.
        /// World-Elements are the Voxels.
        /// </summary>
        virtual void EnableRenderingWithColorPalette();
        /// <summary>
        /// This function disable the use of ColorPalette in the PBR-Rendering
        /// and enables the use of Texturing for World-Elements.
        /// World-Elements are the Voxels.
        /// </summary>
        virtual void DisableRenderingWithColorPalette();
        /// <summary>
        /// Enables color palette transparency
        /// </summary>
        virtual void EnableColorTransparency();
        /// <summary>
        /// Disables color palette transparency
        /// </summary>
        virtual void DisableColorTransparency();

    internal:
        void Init(VoxelEngine::IEngine^ engine, EngineCore::Graphics::GraphicController* graphicControl, Controllers::CameraControl^ cameraControl, Controllers::ColorPaletteControl^ colorPalette, EngineCore::Input::InputSystem* input) override;
        void Render(std::vector<std::shared_ptr<EngineCore::Culling::Data::ChunkData>> chunksForRendering, frameTimeOffset offsetTime) override;

    protected:

    private:
        /// <summary>
        /// This function adds all of our shaders and create an Open GL shader
        /// program from them.
        /// </summary>
        void AddShadersAndCreateGLProgram(VoxelEngine::IEngine^ engine);
        /// <summary>
        /// In this function all needed uniform buffers are created.
        /// </summary>
        void CreateUniformBuffers();
        /// <summary>
        /// In this function all needed voxel buffers are created.
        /// </summary>
        void CreateVoxelBuffers();
        /// <summary>
        /// In this function the uniform gets their values.
        /// </summary>
        void AddUniforms();
        /// <summary>
        /// In this function the buffers got rendered.
        /// </summary>
        void RenderVoxelBuffer(EngineCore::Graphics::Buffer::VoxelBuffer tmp, const EngineCore::Graphics::Shaders::ShaderProgram& shaderProgram);
        /// <summary>
        /// This function creates the framebuffer.
        /// </summary>
        void CreateFrameBuffer();


    };

Renderer.cpp CreateFrameBuffer:

void DefaultRenderer::CreateFrameBuffer()
    {
        quadVertices_ = gcnew array<float>
        {       // positions   // texCoords
                -1.0f, 1.0f, 0.0f, 1.0f,
                -1.0f, -1.0f, 0.0f, 0.0f,
                 1.0f, -1.0f, 1.0f, 0.0f,

                -1.0f, 1.0f, 0.0f, 1.0f,
                 1.0f, -1.0f, 1.0f, 0.0f,
                 1.0f, 1.0f, 1.0f, 1.0f
        };

        float quadVertices[24];
        for (size_t i = 0; i < 24; i++)
        {
            quadVertices[i] = quadVertices_[i];
        }


        // screen quad VAO
        unsigned int quadVAO;
        unsigned int quadVBO;

        glGenVertexArrays(1, &quadVAO);
        glGenBuffers(1, &quadVBO);
        quadVAO_ = quadVAO;
        quadVBO_ = quadVBO;
        glBindVertexArray(quadVAO_);
        glBindBuffer(GL_ARRAY_BUFFER, quadVBO_);
        glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));



        screenShader_ = &GraphicControl_->GetShaderProgram("framebuffer_screen_Program");


        screenShader_->Use();
        glUniform1i(screenShader_->GetUniform("screenTexture"), 0);

        unsigned int framebuffer;
        glGenFramebuffers(1,&framebuffer);
        FBO_ = framebuffer;
        glBindFramebuffer(GL_FRAMEBUFFER, FBO_);


        // generate texture
        unsigned int texColorBuffer;
        glGenTextures(1, &texColorBuffer);
        texture_ = texColorBuffer;
        glBindTexture(GL_TEXTURE_2D, texture_); 
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1920, 1080, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glBindTexture(GL_TEXTURE_2D, 0);

        // attach it to currently bound framebuffer object
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_, 0);


        unsigned int rbo;
        glGenRenderbuffers(1, &rbo);
        RBO_ = rbo;
        glBindRenderbuffer(GL_RENDERBUFFER, RBO_);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1920, 1080);
        glBindRenderbuffer(GL_RENDERBUFFER, 0);

        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO_);


        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        {
            std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
        }


        FBO_ = framebuffer;
        texture_ = texColorBuffer;
        RBO_ = rbo;
        quadVBO_ = quadVBO;
        quadVAO_ = quadVAO;

        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

Renderer.cpp 渲染循环:

void DefaultRenderer::Render(std::vector<std::shared_ptr<EngineCore::Culling::Data::ChunkData>> chunksForRendering, frameTimeOffset offsetTime)
    {
        //bind to framebuffer and draw scene to color texture
        glBindFramebuffer(GL_FRAMEBUFFER, FBO_ );

        //clear framebuffer
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        glEnable(GL_DEPTH_TEST);

        auto tmp = GraphicControl_->GetVoxelBuffer("test");
        tmp.ClearVoxelRenderList();
        tmp.VoxelBufferData(chunksForRendering);


        AddUniforms();

        RenderVoxelBuffer(tmp, GraphicControl_->GetShaderProgram("testProgram"));



        // bind back to default framebuffer and draw a quad plane with the attached framebuffer color texture
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        //// clear all relevant buffers
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);  
        glClear(GL_COLOR_BUFFER_BIT);



        GraphicControl_->GetShaderProgram("framebuffer_screen_Program").Use();
        glBindVertexArray(quadVAO_);
        glDisable(GL_DEPTH_TEST); // disable depth test 
        glBindTexture(GL_TEXTURE_2D, texture_); // use the color attachment texture as the texture of the quad plane
        glDrawArrays(GL_TRIANGLES, 0, 6);

    }

Renderer.cpp渲染体素缓冲区:

void DefaultRenderer::RenderVoxelBuffer(EngineCore::Graphics::Buffer::VoxelBuffer tmp, const EngineCore::Graphics::Shaders::ShaderProgram& shaderProgram)
    {
        shaderProgram.Use();
        for (auto const& singleChunk : tmp.List_)
        {
            glBindVertexArray(singleChunk->Id);

            glBindBuffer(GL_ARRAY_BUFFER, singleChunk->VoxelBuffer);
            glBufferData(GL_ARRAY_BUFFER, singleChunk->VoxelCount * sizeof(EngineCore::Graphics::Data::VoxelData), singleChunk->List.data(), GL_DYNAMIC_DRAW);

            glEnableVertexAttribArray(0);
            glVertexAttribIPointer(0, 1, GL_UNSIGNED_INT, sizeof(EngineCore::Graphics::Data::VoxelData), 0);

            glUniform3f(shaderProgram.GetUniform("u_chunk_location"), (float)singleChunk->OffsetX, (float)singleChunk->OffsetY, (float)singleChunk->OffsetZ);
            glDrawArrays(GL_POINTS, 0, singleChunk->VoxelCount);
        }
        glBindVertexArray(0);
    }

framebuffer_screen.fs:

#version 450 core

out vec4 FragColor;

in vec2 TexCoords;

uniform sampler2D screenTexture;

void main()
{
    vec3 col = texture(screenTexture, TexCoords).rgb;
    FragColor = vec4(col, 1.0);
} 

framebuffer_screen.vs:

#version 450 core

layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;

out vec2 TexCoords;

void main()
{
    TexCoords = aTexCoords;
    gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); 
}  

我忘记在设置我的着色器属性之前激活我的着色器。现在一切正常