105 lines
3.7 KiB
C++
105 lines
3.7 KiB
C++
#pragma once
|
|
|
|
#include "Gedeng/Mesh.h"
|
|
#include "Gedeng/Shader.h"
|
|
#include <glm/glm.hpp>
|
|
|
|
namespace Gedeng {
|
|
|
|
class DirectionalLight {
|
|
public:
|
|
glm::vec3 direction;
|
|
|
|
DirectionalLight() : 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_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
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);
|
|
}
|
|
|
|
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_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
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(-40.0f, 40.0f, -40.0f, 40.0f, near_plane, far_plane);
|
|
glm::mat4 lightView = glm::lookAt(-direction * 40.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 = 1024;
|
|
const unsigned int SHADOW_HEIGHT = 1024;
|
|
|
|
Gedeng::Shader shadow_shader;
|
|
};
|
|
|
|
} // namespace Gedeng
|