#pragma once #include "Gedeng/Mesh.h" #include "Gedeng/Shader.h" #include namespace Gedeng { class DirectionalLight { public: glm::vec3 direction; explicit DirectionalLight(glm::vec3 direction) // TODO: Avoid all this duplication : direction(direction), shadow_shader(Gedeng::Shader("Shader/shadow.vs", "Shader/shadow.fs")) { // Configure depth map glGenFramebuffers(1, &depth_map_fbo); // Create depth texture glGenTextures(1, &depth_map); glBindTexture(GL_TEXTURE_2D, depth_map); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Attach depth texture as FBO's depth buffer glBindFramebuffer(GL_FRAMEBUFFER, depth_map_fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_map, 0); glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); glBindFramebuffer(GL_FRAMEBUFFER, 0); } void set_in_shader(Shader &shader) { shader.setVec3("light_direction", direction); shader.setMat4("light_space_matrix", get_light_space_matrix()); } void render_shadow(Mesh &mesh) { shadow_shader.use(); shadow_shader.setMat4("lightSpaceMatrix", get_light_space_matrix()); glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); glBindFramebuffer(GL_FRAMEBUFFER, depth_map_fbo); mesh.render(shadow_shader); glBindFramebuffer(GL_FRAMEBUFFER, 0); } glm::mat4 get_light_space_matrix() { // TODO: Make the values here configurable float near_plane = 1.0f, far_plane = 100.0f; glm::mat4 lightProjection = glm::ortho(-20.0f, 20.0f, -20.0f, 20.0f, near_plane, far_plane); glm::mat4 lightView = glm::lookAt(-direction * 10.0f, direction, glm::vec3(0.0, 1.0, 0.0)); return lightProjection * lightView; } void clear_shadows() { shadow_shader.use(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void bind_depth_map_to(int unit) { glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(GL_TEXTURE_2D, depth_map); } private: unsigned int depth_map; unsigned int depth_map_fbo; const unsigned int SHADOW_WIDTH = 2048; const unsigned int SHADOW_HEIGHT = 2048; Gedeng::Shader shadow_shader; }; } // namespace Gedeng