static void computeLightSpace(glm::mat4 view, glm::mat4 proj, glm::vec3 lightDir, glm::mat4 out[3]){ glm::mat4 inv = glm::inverse(proj*view); glm::vec4 corners[8] = { {-1,-1,-1,1},{1,-1,-1,1},{1,1,-1,1},{-1,1,-1,1}, {-1,-1, 1,1},{1,-1, 1,1},{1,1, 1,1},{-1,1, 1,1} }; for(int i=0;i<3;i++){ glm::mat4 lightView = glm::lookAt(-lightDir*100.0f,glm::vec3(0),glm::vec3(0,1,0)); glm::vec3 mn(FLT_MAX), mx(-FLT_MAX); for(auto &c: corners){ glm::vec4 wc = inv * c; wc/=wc.w; glm::vec4 lc = lightView * wc; mn = glm::min(mn,glm::vec3(lc)); mx = glm::max(mx,glm::vec3(lc)); } out[i] = glm::ortho(mn.x,mx.x,mn.y,mx.y,-mx.z-50.0f,-mn.z+50.0f) * lightView; } } void VoxelGame::render(glm::mat4 const& view, glm::mat4 const& proj){ computeLightSpace(view,proj,lightDir,lightSpaceMat); // 1) depth passes for(int i=0;i<NUM_CASCADES;i++){ glViewport(0,0,SHADOW_MAP_SIZE,SHADOW_MAP_SIZE); glBindFramebuffer(GL_FRAMEBUFFER,depthFBO[i]); glClear(GL_DEPTH_BUFFER_BIT); glUseProgram(depthProg); glUniformMatrix4fv(glGetUniformLocation(depthProg,"uLightSpace"), 1,GL_FALSE,glm::value_ptr(lightSpaceMat[i])); renderScene(depthProg); } glBindFramebuffer(GL_FRAMEBUFFER,0); // 2) main pass glViewport(0,0,screenW,screenH); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glUseProgram(mainProg); glUniformMatrix4fv(glGetUniformLocation(mainProg,"uView"), 1,GL_FALSE,glm::value_ptr(view)); glUniformMatrix4fv(glGetUniformLocation(mainProg,"uProj"), 1,GL_FALSE,glm::value_ptr(proj)); for(int i=0;i<NUM_CASCADES;i++){ char buf[32]; sprintf(buf,"uLightSpace[%d]",i); glUniformMatrix4fv(glGetUniformLocation(mainProg,buf), 1,GL_FALSE,glm::value_ptr(lightSpaceMat[i])); } glUniform1fv(glGetUniformLocation(mainProg,"cascadeSplit"), NUM_CASCADES,cascadeSplits); glUniform3fv(glGetUniformLocation(mainProg,"lightDir"), 1,glm::value_ptr(lightDir)); glUniform3fv(glGetUniformLocation(mainProg,"viewPos"), 1,glm::value_ptr(cameraPos)); // bind textures glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,textureDirt); glUniform1i(glGetUniformLocation(mainProg,"uTexDirt"),0); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,textureGrass); glUniform1i(glGetUniformLocation(mainProg,"uTexGrass"),1); for(int i=0;i<NUM_CASCADES;i++){ glActiveTexture(GL_TEXTURE2+i); glBindTexture(GL_TEXTURE_2D,depthTex[i]); char buf[32]; sprintf(buf,"uShadowMap[%d]",i); glUniform1i(glGetUniformLocation(mainProg,buf),2+i); } renderScene(mainProg); }