AlgebraMaster

Modern C++ 创造非凡 . 改变世界

导航

- OPENGL8 - 抗锯齿 MSAA & Default Framebuffer & Postframebuffer

CP27抗锯齿:

 

 

 

 

方法1:最简单得就用GLFW: MSAA

glfwWindowHint(GLFW_SAMPLES, 4);
glEnable(GL_MULTISAMPLE);

 

方法2:离屏MSAA

第一种是直接生成MultiSampled Framebuffer 直接拷贝到 default Framebuffer.

//
// Created by admin on 2020/2/27.
//

#ifndef TRIANGLE_ALG_OGLHELPER_H
#define TRIANGLE_ALG_OGLHELPER_H
#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>


namespace AlgebraMaster{
    // --------------------- function declaration ----------------------------------------
    // * create VAO and VBO, but not contain any data /
    void CreateGeometryBuffer(GLuint &VAO, GLuint &VBO);

    // * Create framebuffer that can attach a texture/
    void CreateFrameBufferTextured(int width, int height, GLuint &framebufferID, GLuint &attachTextureID);
    // * create RenderBuffer object that can render depth, stent
    void CreateRenderBufferObject(int width, int height, GLuint &renderBufferID);

    // * Create multiSampled frame buffer that attached a texture /
    void CreateMultiSampledFrameBufferTextured(int width, int height, GLuint &framebufferID, GLuint &attachTextureID, int samples=4);
    // * Create multiSampled RenderBuffer /
    void CreateMultiSampledRenderBufferObject(int width, int height, GLuint &renderBufferID,int samples = 4);

    //* from src buffer to des buffer , if des buffer=0 , that copy to screen
    void CopyFrameBuffer(const GLuint &srcBufferID, const GLuint &desBufferID, int width, int height, bool copyDepth=false, bool copyStencil= false );

    // --------------------- function declaration ----------------------------------------



    // --------------------- function definition ----------------------------------------
    void CreateGeometryBuffer(GLuint &VAO, GLuint &VBO){
        glCreateVertexArrays(1, &VAO);
        glCreateBuffers(1,&VBO);
        glBindVertexArray(VAO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);

    }

    // create frame buffer that attached a texture
    void CreateFrameBufferTextured(int width, int height ,GLuint &framebufferID,
                                   GLuint &attachTextureID){

        glGenFramebuffers(1, &framebufferID);
        glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);

        glGenTextures(1, &attachTextureID);
        glBindTexture(GL_TEXTURE_2D, attachTextureID);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 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);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, attachTextureID, 0);
    }

    // create render buffer that can render DEPTH/STENCIL
    void CreateRenderBufferObject(int width, int height, GLuint &renderBufferID)
    {
        glGenRenderbuffers(1, &renderBufferID);
        glBindRenderbuffer(GL_RENDERBUFFER, renderBufferID);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); // use a single renderbuffer object for both a depth AND stencil buffer.
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBufferID); // now actually attach it
        // now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now
        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
            cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl;
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

    // a multi sampled frame buffer with a multi sampled texture
    void CreateMultiSampledFrameBufferTextured(int width, int height, GLuint &framebufferID, GLuint &attachTextureID, int samples){
        glCreateFramebuffers(1,&framebufferID);
        glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
        glGenTextures(1,&attachTextureID);
        glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,attachTextureID);
        glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,samples,GL_RGB,width,height,GL_TRUE);
        glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
        glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D_MULTISAMPLE,attachTextureID,0);

    }
    // Multi sampled render buffer
    void CreateMultiSampledRenderBufferObject(int width, int height, GLuint &renderBufferID,int samples ){
        glGenRenderbuffers(1, &renderBufferID);
        glBindRenderbuffer(GL_RENDERBUFFER, renderBufferID);
        glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH24_STENCIL8, width,height);
        glBindRenderbuffer(GL_RENDERBUFFER, 0);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBufferID); // now actually attach it
        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
            cout << "ERROR::MULTI_FRAMEBUFFER:: Framebuffer is not complete!" << endl;
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

    //* from src buffer to des buffer , if des buffer=0 , that copy to screen
    void CopyFrameBuffer(const GLuint &srcBufferID, const GLuint &desBufferID, int width, int height, bool copyDepth, bool copyStencil )
    {
        glBindFramebuffer(GL_READ_FRAMEBUFFER, srcBufferID);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, desBufferID);
        glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
        if (copyDepth)
            glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
        if (copyStencil)
            glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_STENCIL_BUFFER_BIT, GL_NEAREST);
    }


    // --------------------- function definition ----------------------------------------
} // end of namespace









#endif //TRIANGLE_ALG_OGLHELPER_H
ALG_OGLHelper.h
#define GLEW_STATIC
// GLEW
#include <GL/glew.h>
#include <cstdlib>
#undef GLFW_DLL
// GLFW
#include <GLFW/glfw3.h>
#include <iostream>
#include "ALG_LoadShader.h"
#include "ALG_LoadTexture.h"
#include "ALG_GLFWCamera.h"
#include "ALG_FrameWindow.h"
#include "ALG_ModelDelegate.h"
#include "ALG_SceneDelegate.h"
#include "ALG_DrawGrid.h"
#include "ALG_DrawOriginGnomon.h"
#include "ALG_DrawCube.h"
#include <cmath>

#include "ALG_Random.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace AlgebraMaster;


const unsigned int SRC_WIDTH = 1400;
const unsigned int SRC_HEIGHT = 720;


static GLuint cubeVAO,VBO;
static GLuint lightVAO;  //VBO stays the same; the vertices are the same for the light object which is also a 3D cube


static LoadShader SurfaceShader;

void init();
void display();


void processInput(GLFWwindow *window);
void framebuffer_size_callback(GLFWwindow* window, int width, int height); // framezize
void mouse_callback(GLFWwindow* window, double xpos, double ypos); // Maya Alt+LeftMouse
void scroll_callback(GLFWwindow *window, double xoffset, double yoffset);


// camera
static GLFWCamera *camera;
static float lastX =  float(SRC_WIDTH) / 2.0f;
static float lastY =  float(SRC_HEIGHT) / 2.0f;
static bool firstMouse = true;
static bool firstMiddowMouse = true;
// timing
static float deltaTime = 0.0f;    // time between current frame and last frame
static float lastFrame = 0.0f;

// light define
static glm::vec3 lightPos(0.0f, 4.0f,-2.0f);

static Scene scene;
static DrawGrid grid;
static DrawOriginGnomon gnomon;
const int amount = 100;

// framebuffer
static GLuint multiFBO;
static GLuint multiFBOTexture;
static GLuint multiRBO;
// PostProcessing Buffer
static GLuint  postFrameBufferID;



void init(){



    camera = new GLFWCamera;
    camera->pos.y = 0.5f;
    camera->pos.z = 2.0f;
    // GL depth zbuffer
    glEnable(GL_DEPTH_TEST);



    SurfaceShader.load("shaders/standard_surface/SurfaceShader.vert","shaders/standard_surface/SurfaceShader.frag");


    scene.read("scene/scene.json");
    scene.parseInitialize();
    scene.parseModel();
    scene.parseMats();
    scene.parseAssignMats();

    grid.initialize();
    gnomon.initialize();


    // Instance Array building:

    auto *modelMatrices = new glm::mat4[amount];

    RandomN1P1 xPosSet(amount, 1);
    RandomN1P1 zPosSet(amount, 2);
    RandomN1P1 rotAmount(amount,3);
    Random01 scaleAmount(amount,4);
    //cout << scaleAmount <<endl;

    for(int i=0;i<amount;i++)
    {
        // new translate
        glm::mat4 model(1.0f);
        model = glm::translate(model,glm::vec3(xPosSet[i]*20, 0.0, zPosSet[i]*20  )  );
        // new rot
        glm::mat4 rot(1.0f);
        rot = glm::rotate(rot,glm::radians(rotAmount[i]*360) , glm::vec3(0.0,1.0,0.0));
        // R S T order
        glm::mat4 scale(1.0f);
        scale = glm::scale(  scale,glm::vec3(scaleAmount[i])  );

        modelMatrices[i] = model * scale * rot  ;
    }
    //object share one mem buffer of instance
    unsigned int buffer;
    glCreateBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, amount * sizeof(glm::mat4), &modelMatrices[0], GL_STATIC_DRAW);

    for(auto &model: scene.allModels){
        for(auto &loc: model->locations)
        {
            glBindVertexArray(loc->mesh->VAO);

            glEnableVertexAttribArray(10);
            glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)0);

            glEnableVertexAttribArray(11);
            glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4)));

            glEnableVertexAttribArray(12);
            glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(2 * sizeof(glm::vec4)));

            glEnableVertexAttribArray(13);
            glVertexAttribPointer(13, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(3 * sizeof(glm::vec4)));

            glVertexAttribDivisor(10, 1);
            glVertexAttribDivisor(11, 1);
            glVertexAttribDivisor(12, 1);
            glVertexAttribDivisor(13, 1);
            glBindVertexArray(0);
        }
    }
    delete [] modelMatrices;
    const int samplers = 32;
    // Create MultiSampler Framebuffer with attached texture
    CreateMultiSampledFrameBufferTextured(SRC_WIDTH, SRC_HEIGHT, multiFBO, multiFBOTexture, samplers);
    // Create MultiSampler render buffer
    CreateMultiSampledRenderBufferObject(SRC_WIDTH, SRC_HEIGHT, multiRBO, samplers);

}

// object .vert settings

// ----------- Render Loop ----------
void display(){

    // per-frame time logic
            // --------------------
    float currentFrame = glfwGetTime();
    deltaTime = currentFrame - lastFrame;
    lastFrame = currentFrame;


    glm::mat4 view = camera->GetViewMatrix();
    glm::mat4 projection = glm::perspective(glm::radians(camera->fov),float(SRC_WIDTH) / float(SRC_HEIGHT),0.1f,  1000.0f);
    // object world transformation
    glm::mat4 model = glm::mat4(1.0f);
    scene.setMatrix(projection,view,model);

    // 1. draw scene as normal in multisampled buffers
    glBindFramebuffer(GL_FRAMEBUFFER, multiFBO);
    glClearColor(0.1f, 0.2f, 0.4f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);


    for(auto &m: scene.allModels){
        for(auto &loc: m->locations){
            glBindVertexArray(loc->mesh->VAO);

            loc->mesh->shader.use();
            loc->mesh->shader.setInt("useInstance", 1);
            loc->mesh->shader.setMatrix(model,view,projection);
            loc->mesh->allocateTextureChannelFromShader(loc->mesh->shader);
            //glDrawElements(GL_TRIANGLES, loc->mesh->indices.size(), GL_UNSIGNED_INT, 0);
            glDrawElementsInstanced(GL_TRIANGLES, loc->mesh->indices.size(), GL_UNSIGNED_INT, 0, amount);
            glBindVertexArray(0);
        }
    }




    grid.draw(projection,view);
    gnomon.draw(projection,view);






    // copy multi buffer to our default screen buffer
    CopyFrameBuffer(multiFBO,0,SRC_WIDTH,SRC_HEIGHT,true);




}


int main()
{
    glfwInit();
    FrameWindow FrameWindow(SRC_WIDTH,SRC_HEIGHT);
    glfwSetFramebufferSizeCallback(FrameWindow.getWindow(), framebuffer_size_callback);
    glfwSetCursorPosCallback(FrameWindow.getWindow(),mouse_callback);
    glfwSetScrollCallback(FrameWindow.getWindow(), scroll_callback);
    init();
    // RENDER--------------
    while(!glfwWindowShouldClose(FrameWindow.getWindow())){
        processInput(FrameWindow.getWindow());
        display();
        glfwSwapBuffers(FrameWindow.getWindow());
        glfwPollEvents();
    }
    delete camera;
    return 0;
}

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // make sure the viewport matches the new window dimensions; note that width and
    // height will be significantly larger than specified on retina displays.
    glViewport(0, 0, width, height);
}

void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        camera->processKeyboardMove(deltaTime,GLFWCamera::FORWARD);
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        camera->processKeyboardMove(deltaTime,GLFWCamera::BACKWARD);
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
        camera->processKeyboardMove(deltaTime,GLFWCamera::LEFT);
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
        camera->processKeyboardMove(deltaTime,GLFWCamera::RIGHT);
}

// ROTATE VIEW DIR
void mouse_callback(GLFWwindow* window, double xpos, double ypos){

    int middow_mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_MIDDLE);
    int mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT);
    int key_state = glfwGetKey(window,GLFW_KEY_LEFT_ALT);
    // set up the camera view
    if( mouse_state == GLFW_PRESS && key_state== GLFW_PRESS)
    {
        if (firstMouse){
            lastX = xpos;
            lastY = ypos;
            firstMouse = false;
        }
        float xoffset = xpos - lastX;
        float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
        lastX = xpos;
        lastY = ypos;
        camera->processMouseMove(xoffset,yoffset);
    }
    if (key_state == GLFW_RELEASE || mouse_state == GLFW_RELEASE){
        firstMouse = true;
    }


    // Move Camera Position
    if( middow_mouse_state == GLFW_PRESS) {

        if (firstMiddowMouse){
            lastX = xpos;
            lastY = ypos;
            firstMiddowMouse = false;
        }
        float xoffset = xpos - lastX;
        float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
        lastX = xpos;
        lastY = ypos;
        camera->pos.x += xoffset*0.01f;
        camera->pos.y += yoffset*0.01f;

    }
    if ( middow_mouse_state == GLFW_RELEASE){
        firstMiddowMouse = true;
    }

}

void scroll_callback(GLFWwindow *window, double xoffset, double yoffset){
    camera->processFov(yoffset);
}
main.cpp

上面OGLHelper.h里有3个函数:

 // a multi sampled frame buffer with a multi sampled texture
    void CreateMultiSampledFrameBufferTextured(int width, int height, GLuint &framebufferID, GLuint &attachTextureID, int samples){
        glCreateFramebuffers(1,&framebufferID);
        glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
        glGenTextures(1,&attachTextureID);
        glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,attachTextureID);
        glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,samples,GL_RGB,width,height,GL_TRUE);
        glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
        glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D_MULTISAMPLE,attachTextureID,0);

    }
    // Multi sampled render buffer
    void CreateMultiSampledRenderBufferObject(int width, int height, GLuint &renderBufferID,int samples ){
        glGenRenderbuffers(1, &renderBufferID);
        glBindRenderbuffer(GL_RENDERBUFFER, renderBufferID);
        glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH24_STENCIL8, width,height);
        glBindRenderbuffer(GL_RENDERBUFFER, 0);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderBufferID); // now actually attach it
        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
            cout << "ERROR::MULTI_FRAMEBUFFER:: Framebuffer is not complete!" << endl;
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

    //* from src buffer to des buffer , if des buffer=0 , that copy to screen
    void CopyFrameBuffer(const GLuint &srcBufferID, const GLuint &desBufferID, int width, int height, bool copyDepth, bool copyStencil )
    {
        glBindFramebuffer(GL_READ_FRAMEBUFFER, srcBufferID);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, desBufferID);
        glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
        if (copyDepth)
            glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
        if (copyStencil)
            glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_STENCIL_BUFFER_BIT, GL_NEAREST);
    }

所以main中逻辑就是:

void init()
{
...
// Create MultiSampler Framebuffer with attached texture
    CreateMultiSampledFrameBufferTextured(SRC_WIDTH, SRC_HEIGHT, multiFBO, multiFBOTexture, samplers);
    // Create MultiSampler render buffer
    CreateMultiSampledRenderBufferObject(SRC_WIDTH, SRC_HEIGHT, multiRBO, samplers);
}

void display(){

 // 1. draw scene as normal in multisampled buffers
    glBindFramebuffer(GL_FRAMEBUFFER, multiFBO);
    glClearColor(0.1f, 0.2f, 0.4f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    // RenderYour Objs.........


    // copy multi buffer to our default screen buffer
    CopyFrameBuffer(multiFBO,0,SRC_WIDTH,SRC_HEIGHT,true);
}

这种情况下的材质是没改变的。

如果要改变成 自定义多采样材质算法,参考https://www.cnblogs.com/chandler00x/p/3888139.html

注意这样对拷有个问题,是因为直接从MultiSampledBuffer->DefaultSampledBuffer.会导致屏幕放大,并没有适配。

但是下面的带有PostProcessingBuffer不会。

 

第二种带有Post processing的framebuffer

两幅图来展示:

 

注意第二幅图中间copy的过程,glBlitFrameBuffer()我没有copy depth, copy stencil, 因为这个imtermediateFBO 是一个only color attached texture buffer.

 

 

//
// Created by admin on 2020/3/9.
//

#ifndef TRIANGLE_ALG_DRAWPOSTPOCESSINGQUAD_H
#define TRIANGLE_ALG_DRAWPOSTPOCESSINGQUAD_H

#include "ALG_LoadShader.h"
#include "ALG_OGLHelper.h"
namespace AlgebraMaster{

    static float __postQuadVertices__[] = {
            // 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
    };


    class DrawPostProcessingQuad{
    public:
        void initialize(){
            glGenVertexArrays(1, &VAO);
            glGenBuffers(1, &VBO);
            glBindVertexArray(VAO);
            glBindBuffer(GL_ARRAY_BUFFER, VBO);
            glBufferData(GL_ARRAY_BUFFER, sizeof(__postQuadVertices__), &__postQuadVertices__, GL_STATIC_DRAW);
            // pos
            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)));

            shader.fromSrc(vertexShaderSource,fragmentShaderSource);
            CreateFrameBufferTextured(mWidth,mHeight,FBO,FBOTexture);

        }

        void setupWidthHeight(int width,int height){
            mWidth = width;
            mHeight = height;
        }
        void draw(){
            shader.use();
            glBindVertexArray(VAO);
            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D,FBOTexture ); // use the now resolved color attachment as the quad's texture
            glDrawArrays(GL_TRIANGLES, 0, 6);
        }


        const char* fragmentShaderSource = "#version 450 core\n"
                                           "out vec4 FragColor;\n"
                                           "in vec2 TexCoords;\n"
                                           "uniform sampler2D screenTexture;\n"
                                           "void main()\n"
                                           "{\n"
                                           "vec3 col = texture(screenTexture, TexCoords).rgb;\n"
                                           "float grayscale = 0.2126 * col.r + 0.7152 * col.g + 0.0722 * col.b;\n"
                                           "FragColor = vec4(vec3(grayscale), 1.0);\n"
                                           "}\n\0";

        const char* vertexShaderSource = "#version 450 core\n"
                                         "layout (location = 0) in vec2 aPos;\n"
                                         "layout (location = 1) in vec2 aTexCoords;\n"
                                         "out vec2 TexCoords;\n"
                                         "void main()\n"
                                         "{\n"
                                         "TexCoords = aTexCoords;\n"
                                         "gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);\n"
                                         "}\n\0";

        unsigned int VAO,VBO,FBO,FBOTexture;
        LoadShader shader;
        int mWidth;
        int mHeight;

    };


}





#endif //TRIANGLE_ALG_DRAWPOSTPOCESSINGQUAD_H
ALG_DrawPostPocessingQuad.h
#define GLEW_STATIC
// GLEW
#include <GL/glew.h>
#include <cstdlib>
#undef GLFW_DLL
// GLFW
#include <GLFW/glfw3.h>
#include <iostream>
#include "ALG_LoadShader.h"
#include "ALG_LoadTexture.h"
#include "ALG_GLFWCamera.h"
#include "ALG_FrameWindow.h"
#include "ALG_ModelDelegate.h"
#include "ALG_SceneDelegate.h"
#include "ALG_DrawGrid.h"
#include "ALG_DrawOriginGnomon.h"
#include "ALG_DrawCube.h"
#include "ALG_DrawPostPocessingQuad.h"
#include <cmath>

#include "ALG_Random.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace AlgebraMaster;


const unsigned int SRC_WIDTH = 1400;
const unsigned int SRC_HEIGHT = 720;


static GLuint cubeVAO,VBO;
static GLuint lightVAO;  //VBO stays the same; the vertices are the same for the light object which is also a 3D cube


static LoadShader SurfaceShader;

void init();
void display();


void processInput(GLFWwindow *window);
void framebuffer_size_callback(GLFWwindow* window, int width, int height); // framezize
void mouse_callback(GLFWwindow* window, double xpos, double ypos); // Maya Alt+LeftMouse
void scroll_callback(GLFWwindow *window, double xoffset, double yoffset);


// camera
static GLFWCamera *camera;
static float lastX =  float(SRC_WIDTH) / 2.0f;
static float lastY =  float(SRC_HEIGHT) / 2.0f;
static bool firstMouse = true;
static bool firstMiddowMouse = true;
// timing
static float deltaTime = 0.0f;    // time between current frame and last frame
static float lastFrame = 0.0f;

// light define
static glm::vec3 lightPos(0.0f, 4.0f,-2.0f);

static Scene scene;
static DrawGrid grid;
static DrawOriginGnomon gnomon;
static DrawPostProcessingQuad quad;
const int amount = 100;

// framebuffer
static GLuint multiFBO;
static GLuint multiFBOTexture;
static GLuint multiRBO;
// PostProcessing Buffer




void init(){



    camera = new GLFWCamera;
    camera->pos.y = 0.5f;
    camera->pos.z = 2.0f;
    // GL depth zbuffer
    glEnable(GL_DEPTH_TEST);



    SurfaceShader.load("shaders/standard_surface/SurfaceShader.vert","shaders/standard_surface/SurfaceShader.frag");


    scene.read("scene/scene.json");
    scene.parseInitialize();
    scene.parseModel();
    scene.parseMats();
    scene.parseAssignMats();

    grid.initialize();
    gnomon.initialize();
    quad.setupWidthHeight(SRC_WIDTH,SRC_HEIGHT);
    quad.initialize();

    // Instance Array building:

    auto *modelMatrices = new glm::mat4[amount];

    RandomN1P1 xPosSet(amount, 1);
    RandomN1P1 zPosSet(amount, 2);
    RandomN1P1 rotAmount(amount,3);
    Random01 scaleAmount(amount,4);
    //cout << scaleAmount <<endl;

    for(int i=0;i<amount;i++)
    {
        // new translate
        glm::mat4 model(1.0f);
        model = glm::translate(model,glm::vec3(xPosSet[i]*20, 0.0, zPosSet[i]*20  )  );
        // new rot
        glm::mat4 rot(1.0f);
        rot = glm::rotate(rot,glm::radians(rotAmount[i]*360) , glm::vec3(0.0,1.0,0.0));
        // R S T order
        glm::mat4 scale(1.0f);
        scale = glm::scale(  scale,glm::vec3(scaleAmount[i])  );

        modelMatrices[i] = model * scale * rot  ;
    }
    //object share one mem buffer of instance
    unsigned int buffer;
    glCreateBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, amount * sizeof(glm::mat4), &modelMatrices[0], GL_STATIC_DRAW);

    for(auto &model: scene.allModels){
        for(auto &loc: model->locations)
        {
            glBindVertexArray(loc->mesh->VAO);

            glEnableVertexAttribArray(10);
            glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)0);

            glEnableVertexAttribArray(11);
            glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4)));

            glEnableVertexAttribArray(12);
            glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(2 * sizeof(glm::vec4)));

            glEnableVertexAttribArray(13);
            glVertexAttribPointer(13, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(3 * sizeof(glm::vec4)));

            glVertexAttribDivisor(10, 1);
            glVertexAttribDivisor(11, 1);
            glVertexAttribDivisor(12, 1);
            glVertexAttribDivisor(13, 1);
            glBindVertexArray(0);
        }
    }
    delete [] modelMatrices;
    const int samplers = 1;
    // Create MultiSampler Framebuffer with attached texture
    CreateMultiSampledFrameBufferTextured(SRC_WIDTH, SRC_HEIGHT, multiFBO, multiFBOTexture, samplers);
    // Create MultiSampler render buffer
    CreateMultiSampledRenderBufferObject(SRC_WIDTH, SRC_HEIGHT, multiRBO, samplers);

    // FBO
}

// object .vert settings

// ----------- Render Loop ----------
void display(){

    // per-frame time logic
            // --------------------
    float currentFrame = glfwGetTime();
    deltaTime = currentFrame - lastFrame;
    lastFrame = currentFrame;




    // render
    // ------
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 1. draw scene as normal in multisampled buffers
    glBindFramebuffer(GL_FRAMEBUFFER, multiFBO);
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);


    glm::mat4 view = camera->GetViewMatrix();
    glm::mat4 projection = glm::perspective(glm::radians(camera->fov),float(SRC_WIDTH) / float(SRC_HEIGHT),0.1f,  1000.0f);
    // object world transformation
    glm::mat4 model = glm::mat4(1.0f);
    scene.setMatrix(projection,view,model);




    for(auto &m: scene.allModels){
        for(auto &loc: m->locations){
            glBindVertexArray(loc->mesh->VAO);

            loc->mesh->shader.use();
            loc->mesh->shader.setInt("useInstance", 1);
            loc->mesh->shader.setMatrix(model,view,projection);
            loc->mesh->allocateTextureChannelFromShader(loc->mesh->shader);
            //glDrawElements(GL_TRIANGLES, loc->mesh->indices.size(), GL_UNSIGNED_INT, 0);
            glDrawElementsInstanced(GL_TRIANGLES, loc->mesh->indices.size(), GL_UNSIGNED_INT, 0, amount);
            glBindVertexArray(0);
        }
    }

    grid.draw(projection,view);
    gnomon.draw(projection,view);

    // copy multi buffer to our default screen buffer

    CopyFrameBuffer(multiFBO,quad.FBO,SRC_WIDTH,SRC_HEIGHT);


    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    quad.draw();


}


int main()
{
    glfwInit();
    FrameWindow FrameWindow(SRC_WIDTH,SRC_HEIGHT);
    glfwSetFramebufferSizeCallback(FrameWindow.getWindow(), framebuffer_size_callback);
    glfwSetCursorPosCallback(FrameWindow.getWindow(),mouse_callback);
    glfwSetScrollCallback(FrameWindow.getWindow(), scroll_callback);

    init();
    // RENDER--------------
    while(!glfwWindowShouldClose(FrameWindow.getWindow())){
        processInput(FrameWindow.getWindow());
        display();
        glfwSwapBuffers(FrameWindow.getWindow());
        glfwPollEvents();
    }
    delete camera;
    return 0;
}

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    // make sure the viewport matches the new window dimensions; note that width and
    // height will be significantly larger than specified on retina displays.
    glViewport(0, 0, width, height);
}

void processInput(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        camera->processKeyboardMove(deltaTime,GLFWCamera::FORWARD);
    if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
        camera->processKeyboardMove(deltaTime,GLFWCamera::BACKWARD);
    if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
        camera->processKeyboardMove(deltaTime,GLFWCamera::LEFT);
    if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
        camera->processKeyboardMove(deltaTime,GLFWCamera::RIGHT);
}

// ROTATE VIEW DIR
void mouse_callback(GLFWwindow* window, double xpos, double ypos){

    int middow_mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_MIDDLE);
    int mouse_state = glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT);
    int key_state = glfwGetKey(window,GLFW_KEY_LEFT_ALT);
    // set up the camera view
    if( mouse_state == GLFW_PRESS && key_state== GLFW_PRESS)
    {
        if (firstMouse){
            lastX = xpos;
            lastY = ypos;
            firstMouse = false;
        }
        float xoffset = xpos - lastX;
        float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
        lastX = xpos;
        lastY = ypos;
        camera->processMouseMove(xoffset,yoffset);
    }
    if (key_state == GLFW_RELEASE || mouse_state == GLFW_RELEASE){
        firstMouse = true;
    }


    // Move Camera Position
    if( middow_mouse_state == GLFW_PRESS) {

        if (firstMiddowMouse){
            lastX = xpos;
            lastY = ypos;
            firstMiddowMouse = false;
        }
        float xoffset = xpos - lastX;
        float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top
        lastX = xpos;
        lastY = ypos;
        camera->pos.x += xoffset*0.01f;
        camera->pos.y += yoffset*0.01f;

    }
    if ( middow_mouse_state == GLFW_RELEASE){
        firstMiddowMouse = true;
    }

}

void scroll_callback(GLFWwindow *window, double xoffset, double yoffset){
    camera->processFov(yoffset);
}
main.cpp

可以看到main中最后使用了一个Renderbuffer.方法就是从MultiSampledBuffer->PostProcessingBuffer

 // copy multi buffer to our default screen buffer
    ......

    CopyFrameBuffer(multiFBO,quad.FBO,SRC_WIDTH,SRC_HEIGHT);


    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    quad.draw();

 

 

posted on 2020-03-08 14:02  gearslogy  阅读(567)  评论(0编辑  收藏  举报