将帧缓冲区对象模糊到屏幕上

时间:2017-12-16 07:10:09

标签: c++ opengl fbo

所以我试图用C ++和GLFW / GLEW在OpenGL中创建一个帧缓冲对象。我已成功使用VAO和VBO来简单地使用OpenGL的glDrawArrays方法渲染顶点数组,以在屏幕上制作四边形。然后,我创建了一个多重采样的帧缓冲区对象,并创建了相应的颜色缓冲区和深度缓冲区,然后绑定它,然后渲染四边形,然后解除对帧缓冲区对象,然后尝试将FBO blit到屏幕。它没有那么好或根本没有效果。此外,如果它引起混淆,如果项目在visual studio中以发布模式运行,我做了一个名为“INRELEASE”的预处理器定义,这样在程序启动时就不会弹出控制台。 这是我的代码。

Fbo.h:

#pragma once

#include "Window.h"

class Fbo
{
public:
    static const int NONE = 0;
    static const int DEPTH_TEXTURE = 1;
    static const int DEPTH_RENDER_BUFFER = 2;

private:
    Window *window;

    const int width;
    const int height;

    GLuint frameBuffer;

    bool multisample;

    GLuint colorTexture;
    GLuint depthTexture;

    GLuint depthBuffer;
    GLuint colorBuffer;

    void initializeFrameBuffer(int type);
    void createFrameBuffer();
    void createTextureAttachment();
    void createDepthTextureAttachment();
    void createMultisampledColorAttachment();
    void createDepthBufferAttachment();

public:
    Fbo(Window *window, int width, int height, int depthBufferType);
    Fbo(Window *window, int width, int height);

    void cleanUp() const;
    void bindFrameBuffer() const;
    void unbindFrameBuffer() const;
    void bindToRead() const;
    void resolveToFbo(Fbo *outputFbo) const;
    void resolveToScreen() const;

    inline int getColorTexture() const { return colorTexture; }
    inline int getDepthTexture() const { return depthTexture; }
};

Fbo.cpp:

#include "Fbo.h"

#include <GLFW\glfw3.h>
#include <GL\glew.h>

#include <iostream>

Fbo::Fbo(Window *window, int width, int height, int depthBufferType) : width(width), height(height)
{
    this->window = window;

    multisample = false;
    initializeFrameBuffer(depthBufferType);
}

Fbo::Fbo(Window *window, int width, int height) : width(width), height(height)
{
    this->window = window;

    multisample = true;
    initializeFrameBuffer(DEPTH_RENDER_BUFFER);
}

void Fbo::cleanUp() const
{
    glDeleteFramebuffers(1, &frameBuffer);
    glDeleteTextures(1, &colorTexture);
    glDeleteTextures(1, &depthTexture);
    glDeleteRenderbuffers(1, &depthBuffer);
    glDeleteRenderbuffers(1, &colorBuffer);
}

void Fbo::bindFrameBuffer() const
{
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer);
    glViewport(0, 0, width, height);
}

void Fbo::unbindFrameBuffer() const
{
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glViewport(0, 0, window->getWidth(), window->getHeight());
}

void Fbo::bindToRead() const
{
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBuffer);
    glReadBuffer(GL_COLOR_ATTACHMENT0);
}

void Fbo::resolveToFbo(Fbo *outputFbo) const
{
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, outputFbo->frameBuffer);
    glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBuffer);
    glBlitFramebuffer(0, 0, width, height, 0, 0, outputFbo->width, outputFbo->height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
    unbindFrameBuffer();
}

void Fbo::resolveToScreen() const
{
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    glBindFramebuffer(GL_READ_FRAMEBUFFER, frameBuffer);
    glDrawBuffer(GL_BACK);
    glBlitFramebuffer(0, 0, width, height, 0, 0, window->getWidth(), window->getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
    unbindFrameBuffer();
}

void Fbo::initializeFrameBuffer(int type)
{
    createFrameBuffer();

    if (multisample)
        createMultisampledColorAttachment();
    else
        createTextureAttachment();

    if (type == DEPTH_RENDER_BUFFER)
    {
        createDepthBufferAttachment();
    }
    else if (type == DEPTH_TEXTURE)
    {
        createDepthTextureAttachment();
    }

    unbindFrameBuffer();
}

void Fbo::createFrameBuffer()
{
    glGenFramebuffers(1, &frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
    glDrawBuffer(GL_COLOR_ATTACHMENT0);
}

void Fbo::createTextureAttachment()
{
    glGenTextures(1, &colorTexture);
    glBindTexture(GL_TEXTURE_2D, colorTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
}

void Fbo::createDepthTextureAttachment()
{
    glGenTextures(1, &depthTexture);
    glBindTexture(GL_TEXTURE_2D, depthTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
}

void Fbo::createMultisampledColorAttachment()
{
    glGenRenderbuffers(1, &colorBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
    glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, width, height);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer);
}

void Fbo::createDepthBufferAttachment()
{
    glGenRenderbuffers(1, &depthBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);

    if (!multisample)
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
    else
        glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT24, width, height);

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
}

Main.cpp的:

#include <iostream>

#include <GL\glew.h>
#include <GLFW\glfw3.h>

#include "Window.h"
#include "Fbo.h"
#include "Loader.h"
#include "Renderer.h"

#ifdef INRELEASE
int WinMain()
#else
int main()
#endif
{
    Window window("3D Engine", 800, 600, true);
    Loader loader;
    Renderer renderer;

    float vertices[] = 
    {
        -0.5f,  0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.5f,  0.5f, 0.0f,
        -0.5f,  0.5f, 0.0f
    };

    RawModel model = loader.loadToVao(vertices, sizeof(vertices));
    Fbo fbo(&window, window.getWidth(), window.getHeight());

    while (!window.isClosed())
    {
        window.clear();

        fbo.bindFrameBuffer();
        renderer.render(model);
        fbo.unbindFrameBuffer();
        fbo.resolveToScreen();

        window.update();
    }

    fbo.cleanUp();
    loader.cleanUp();
    return 0;
}

0 个答案:

没有答案