<-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
// // 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
// // 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\n" "out vec4 FragColor;\n" "in vec2 TexCoords;\n" "uniform sampler2D screenTexture;\n" "void main()\n" "{\n" "vec3 col = texture(screenTexture, TexCoords).rgb;\n" "FragColor = vec4(col, 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
#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); }
源码里因为渲染有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的帧率运行。