Program Listing for File CascadedShadowMap.cpp

Return to documentation for file (Src/GraphicsEngineOpenGL/scene/light/directional_light/CascadedShadowMap.cpp)

#include "scene/light/directional_light/CascadedShadowMap.hpp"

#include <iostream>

#include "hostDevice/bindings.hpp"
#include "spdlog/spdlog.h"

CascadedShadowMap::CascadedShadowMap()
  :

    FBO(0), shadow_maps(0), shadow_width(0), shadow_height(0), matrices_UBO(0), num_active_cascades(0), pcf_radius(1),
    intensity(1)

{}

bool CascadedShadowMap::init(GLuint width, GLuint height, GLuint num_cascades)
{
    shadow_width = width;
    shadow_height = height;

    num_active_cascades = num_cascades;

    glGenFramebuffers(1, &FBO);
    glGenTextures(1, &shadow_maps);
    glBindTexture(GL_TEXTURE_2D_ARRAY, shadow_maps);
    glTexImage3D(GL_TEXTURE_2D_ARRAY,
      0,
      GL_DEPTH_COMPONENT32F,
      shadow_width,
      shadow_height,
      NUM_CASCADES,
      0,
      GL_DEPTH_COMPONENT,
      GL_FLOAT,
      nullptr);

    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

    constexpr float bordercolor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    glTexParameterfv(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, bordercolor);

    glBindFramebuffer(GL_FRAMEBUFFER, FBO);
    glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadow_maps, 0);
    glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);

    int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE) { spdlog::error("ERROR::FRAMEBUFFER:: Framebuffer is not complete!"); }

    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    // setting up our buffer for the light matrics
    // for every cascade we will have 1 matrix in the geometry shader
    glGenBuffers(1, &matrices_UBO);
    glBindBuffer(GL_UNIFORM_BUFFER, matrices_UBO);
    glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) * NUM_CASCADES, nullptr, GL_DYNAMIC_DRAW);
    glBindBufferBase(GL_UNIFORM_BUFFER, UNIFORM_LIGHT_MATRICES_BINDING, matrices_UBO);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

    return true;
}

void CascadedShadowMap::write_light_matrices(std::vector<glm::mat4x4> &lightMatrices)
{
    glBindBuffer(GL_UNIFORM_BUFFER, matrices_UBO);
    for (size_t i = 0; i < lightMatrices.size(); ++i) {
        glBufferSubData(GL_UNIFORM_BUFFER, i * sizeof(glm::mat4x4), sizeof(glm::mat4x4), &lightMatrices[i]);
    }
    glBindBuffer(GL_UNIFORM_BUFFER, 0);
}

void CascadedShadowMap::write() { glBindFramebuffer(GL_FRAMEBUFFER, FBO); }

void CascadedShadowMap::read(GLenum texture_unit)
{
    glActiveTexture(GL_TEXTURE0 + texture_unit);
    glBindTexture(GL_TEXTURE_2D_ARRAY, shadow_maps);
}

void CascadedShadowMap::set_pcf_radius(GLuint radius) { pcf_radius = radius; }

void CascadedShadowMap::set_intensity(GLfloat intensity) { this->intensity = intensity; }

CascadedShadowMap::~CascadedShadowMap()
{
    if (FBO) { glDeleteFramebuffers(1, &FBO); }

    if (shadow_maps) { glDeleteTextures(1, &shadow_maps); }
}