<-OPENGL 9-> 阴影篇

<1> 生成深度贴图到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 );



    //* create depth buffer for shadow /
    void CreateDepthFrameBufferTextured(int width, int height, GLuint &frameBufferID, GLuint &attachTextureID);





    //
    void ClearAllBufferColor(glm::vec4 bgColor= {0.4f, 0.4f, 0.6f, 1.0f});


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

        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
            cout << "ERROR::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);
    }

    void CreateDepthFrameBufferTextured(int width, int height, GLuint &frameBufferID, GLuint &attachTextureID){
        glCreateFramebuffers(1,&frameBufferID);
        glGenTextures(1, &attachTextureID);
        glBindTexture(GL_TEXTURE_2D, attachTextureID);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        // attach depth texture as FBO's depth buffer
        glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, attachTextureID, 0);
        glDrawBuffer(GL_NONE);
        glReadBuffer(GL_NONE);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }



    void ClearAllBufferColor(glm::vec4 bgColor){
        glClearColor(bgColor.x,bgColor.y,bgColor.z,bgColor.w);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }




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









#endif //TRIANGLE_ALG_OGLHELPER_H
ALG_OGLHelper.h
//
// Created by admin on 2020/3/12.
//

#ifndef TRIANGLE_ALG_DEPTHSHADOW_H
#define TRIANGLE_ALG_DEPTHSHADOW_H

#include "ALG_OGLHelper.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "ALG_OGLHelper.h"
#include "ALG_TextureDelegate.h"
namespace AlgebraMaster{

    struct DistanceDepthShadow{
        DistanceDepthShadow(){
            texture = new Texture;
        }

        ~DistanceDepthShadow(){
            delete texture;
        }

        // because we have Scene class,that have huge amount of texture units
        void setUpTexture(const string &texName,int texChannel, unsigned texUnitID){
            texture->texType = Texture::DEPTH_SHADOW_MAP;
            texture->path = texName;
            texture->texChannel = texChannel;
            texture->textureUnitID = texUnitID;   //current unique texture unit
        }

        void buildMap(int w, int h,
                const string &texName,unsigned int texChannel, unsigned texUnitID){

            // the shader will transform rendering objs to our light space
            shader.load("shaders/depth_shadow/simpleDepth.vert","shaders/depth_shadow/simpleDepth.frag");
            CreateDepthFrameBufferTextured(w,h,fbo,texture->id);
            setUpTexture(texName,texChannel,texUnitID);
            width = w;
            height = h;
        }

        void buildLightSpaceMatrix(){

            lightProjection = glm::ortho(-15.0f, 15.0f, -15.0f, 15.0f, near_plane, far_plane);
            lightView = glm::lookAt(lightPos, lightDir, glm::vec3(0.0, 1.0, 0.0));
            lightSpaceMatrix = lightProjection * lightView;
        }

        // members
        int width{0},height{0};
        glm::mat4 lightProjection{}, lightView{};
        float near_plane = 1.0f, far_plane = 50.0f;
        glm::vec3 lightPos{0.0};
        glm::vec3 lightDir{0.0};
        glm::mat4 lightSpaceMatrix{0.0};
        unsigned int fbo{0};  // Framebuffer of depth
        Texture * texture;
        LoadShader shader;
    };

}












#endif //TRIANGLE_ALG_DEPTHSHADOW_H
ALG_DepthShadow.h
//
// 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 initialize(const string &vertPath, const string &fragPath){
            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.load(vertPath.c_str(),fragPath.c_str());
            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
"
                                           "out vec4 FragColor;
"
                                           "in vec2 TexCoords;
"
                                           "uniform sampler2D screenTexture;
"
                                           "void main()
"
                                           "{
"
                                           "vec3 col = texture(screenTexture, TexCoords).rgb;
"
                                           "FragColor = vec4(col, 1.0);
"
                                           "}
";

        const char* vertexShaderSource = "#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);
"
                                         "}
";

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

    };


}





#endif //TRIANGLE_ALG_DRAWPOSTPOCESSINGQUAD_H
ALG_DrawPostProcessingQuad.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 "ALG_DrawPlane.h"
#include "ALG_DepthShadow.h"
#include "ALG_OGLHelper.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(-2.0f, 4.0f, -1.0f);

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

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

//
static DistanceDepthShadow *shadow;
float near_plane = 0.5f, far_plane = 17.5f;




void RenderScene(glm::mat4 &model, glm::mat4 &view , glm::mat4 &projection, LoadShader *shader = 0)
        {
            for(auto &m: scene.allModels){
                for(auto &loc: m->locations){
                    glBindVertexArray(loc->mesh->VAO);
                    if (shader){
                        shader->use();
                        shader->setInt("useInstance", 1);
                        shader->setMatrix(model,view,projection);
                    }
                    else{
                        loc->mesh->shader.use();
                        loc->mesh->shader.setInt("useInstance", 1);
                        loc->mesh->shader.setMatrix(model,view,projection);
                        loc->mesh->shader.setVec3("dirLight.P",lightPos);
                        loc->mesh->shader.setMat4("lightSpaceMatrix", shadow->lightSpaceMatrix);
                        loc->mesh->shader.setInt("shadowMap", shadow->texture->id );
                        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);
        }
    }
    plane.draw(projection,view);
    grid.draw(projection,view);
    gnomon.draw(projection,view);
}

void init(){


    // Define the viewport dimensions
    glViewport(0, 0, SRC_WIDTH, SRC_HEIGHT);
    camera = new GLFWCamera;
    camera->pos.y = 0.5f;
    camera->pos.z = 2.0f;
    // GL depth zbuffer
    glEnable(GL_DEPTH_TEST);



    // initialize shadow map
    shadow = new DistanceDepthShadow;
    unsigned int texChannel = Scene::currentActiveTextureChannel;
    unsigned int texUnit = Scene::currentTextureLoaderIndex;
    shadow->buildMap(4086,4086,"dirLightShadow",texChannel,texUnit);
    shadow->lightDir = glm::vec3(0,0,0);
    shadow->lightPos = lightPos * 6.0f;
    shadow->near_plane = near_plane;
    shadow->far_plane = far_plane;
    Scene::currentActiveTextureChannel++;
    Scene::currentTextureLoaderIndex++;
    //




    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("shaders/depth_shadow/debugQuad.vert","shaders/depth_shadow/debugQuad.frag");
    plane.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]*10, 0.0, zPosSet[i]*10  )  );
        // 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);

    // FBO
}

// object .vert settings

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


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

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

    // ----------------------------------- RENDER SHADOW MAP -----------------------------------
    // 1. render depth of scene to texture (from light's perspective)
    shadow->buildLightSpaceMatrix();
    shadow->shader.use();
    shadow->shader.setMat4("lightSpaceMatrix",shadow->lightSpaceMatrix);
    glViewport(0, 0, shadow->width, shadow->height);
    glBindFramebuffer(GL_FRAMEBUFFER, shadow->fbo);
    glClear(GL_DEPTH_BUFFER_BIT);

    // Render Scene in depth shadow shader
    RenderScene(model,shadow->lightView,shadow->lightProjection,&shadow->shader);
    // ----------------------------------- RENDER SHADOW MAP -----------------------------------

    /*
    // 2. draw scene as normal in multisampled buffers
    glViewport(0, 0, SRC_WIDTH, SRC_HEIGHT);
    glBindFramebuffer(GL_FRAMEBUFFER, multiFBO);
    ClearAllBufferColor();
    glEnable(GL_DEPTH_TEST);
    //scene.setMatrix(projection,view,model);
    // render scene as normal
    RenderScene(model,view,projection);

    // copy multi buffer to our default screen buffer
    CopyFrameBuffer(multiFBO,quad.FBO,SRC_WIDTH,SRC_HEIGHT);
    */
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    // reset viewport

    glViewport(0, 0, SRC_WIDTH, SRC_HEIGHT);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    ClearAllBufferColor();
    quad.shader.use();
    quad.shader.setFloat("near_plane", near_plane);
    quad.shader.setFloat("far_plane", far_plane);
    glActiveTexture(shadow->texture->texChannel);
    glBindTexture(GL_TEXTURE_2D, shadow->texture->id);
    glBindVertexArray(quad.VAO);
    glDrawArrays(GL_TRIANGLES, 0, 6);
}


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


    double lastTime  = glfwGetTime();
    double targetFps = 50.0f;


    double previousTime = glfwGetTime();
    double frameCount = 0;

    // RENDER--------------
    while(!glfwWindowShouldClose(FrameWindow.getWindow())){



        // Game Loop
        processInput(FrameWindow.getWindow());
        display();
        glfwSwapBuffers(FrameWindow.getWindow());
        glfwPollEvents();
        // Game Loop


        // Limit fps
        while (glfwGetTime() < lastTime  + 1.0/targetFps) {
                // TODO: Put the thread to sleep, yield, or simply do nothing
         }
        lastTime  += (1.0 / targetFps);
        // Limit fps


        // If a second has passed.
        double currentTime = glfwGetTime();
        frameCount++;
        if ( currentTime - previousTime >= 1.0 )
        {
            // Display the frame count here any way you want.

            stringstream ss;
            ss << "日个朗拉fps:" << frameCount;
            string fpsStr;
            ss >> fpsStr;


            glfwSetWindowTitle(FrameWindow.getWindow(), fpsStr.c_str());
            frameCount = 0.0000;
            previousTime = currentTime;
        }




    }
    delete camera;
    delete shadow;
    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

源码里因为渲染有instance,所以depthShader里面有相关instance矩阵 ,最后把灯光作为摄像机渲染:

所以场景渲染也加入了一个使用自定义shader渲染。

void RenderScene(glm::mat4 &model, glm::mat4 &view , glm::mat4 &projection, LoadShader *shader = 0)
        {
            for(auto &m: scene.allModels){
                for(auto &loc: m->locations){
                    glBindVertexArray(loc->mesh->VAO);
                    if (shader){
                        shader->use();
                        shader->setInt("useInstance", 1);
                        shader->setMatrix(model,view,projection);
                    }
                    else{
                        loc->mesh->shader.use();
                        loc->mesh->shader.setInt("useInstance", 1);
                        loc->mesh->shader.setMatrix(model,view,projection);
                        loc->mesh->shader.setVec3("dirLight.P",lightPos);
                        loc->mesh->shader.setMat4("lightSpaceMatrix", shadow->lightSpaceMatrix);
                        loc->mesh->shader.setInt("shadowMap", shadow->texture->id );
                        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);
        }
    }
    plane.draw(projection,view);
    grid.draw(projection,view);
    gnomon.draw(projection,view);
}

加入阴影渲染:重构了大量的代码

 OPENGL渲染巨量粒子,此案例有4600万粒子,还能以FPS:7的帧率运行。

原文地址:https://www.cnblogs.com/gearslogy/p/12495026.html