• <-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的帧率运行。

  • 相关阅读:
    android.os.NetworkOnMainThreadException 异常处理
    java.lang.SecurityException: Permission denied (missing INTERNET permission?) 解决
    javah 生成header file 报错 问题解决
    AAPT: libpng error: Not a PNG file 问题解决
    Tomcat启动报错 Failed to start component [StandardServer[8005]]解决
    Hibernate
    Linux常用命令总结
    模拟奇数乱码请求问题
    http国际化模拟请求
    db2数据库安装注意几个问题
  • 原文地址:https://www.cnblogs.com/gearslogy/p/12495026.html
Copyright © 2020-2023  润新知