File ShadowSystem.h
File List > render > ShadowSystem.h
Go to the documentation of this file
#pragma once
#include "Light.h"
#include "RenderConfigs.h"
#include "Texture.h"
#include "buffers/StorageBuffer.h"
#include "buffers/UniformBuffer.h"
#include "buffers/FrameBuffer.h"
#include "PolygonLight.h"
#include "shaders/RenderShader.h"
#include <unordered_map>
#include <vector>
#include <memory>
#include <array>
struct ShadowSystem {
public:
// In GLSL (shader), the size of vec3 equals to vec4 due to std140 alignment
// See: https://registry.khronos.org/OpenGL/specs/gl/glspec45.core.pdf#page=159
struct PointStruct
{
PointStruct(const Light& light);
alignas(16) glm::vec3 color{ 1 };
alignas(16) glm::vec3 pos{ 0 };
alignas(4) float power{ 1.0f };
alignas(4) int use_shadow{ 1 };
alignas(4) float radius{ 0.05f };
};
struct SunStruct
{
SunStruct(const Light& light, const glm::mat4& proj);
alignas(16) glm::vec3 color{ 1 };
alignas(16) glm::vec3 pos{ 0 };
alignas(16) glm::vec3 dir{ 1, 0, 0 };
alignas(4) float power{ 1.0f };
alignas(4) int use_shadow{ 1 };
alignas(16) glm::mat4 proj_trans;
};
struct SpotStruct
{
SpotStruct(const Light& light);
alignas(16) glm::vec3 color{ 1 };
alignas(16) glm::vec3 pos{ 0 };
alignas(16) glm::vec3 dir{ 1, 0, 0 };
alignas(4) float power{ 1.0f };
alignas(4) int use_shadow{ 1 };
alignas(4) float cutoff{ 0.9f };
alignas(4) float outer_cutoff{ 0.8f };
};
struct AreaStruct
{
AreaStruct(const Light& light);
alignas(16) glm::vec3 color{ 1 };
alignas(16) glm::mat4 trans{ 1 };
alignas(4) float power{ 1.0f };
alignas(4) int use_shadow{ 1 };
alignas(4) float ratio{ 1.0f };
};
struct PolyStruct
{
alignas(16) glm::vec3 color{ 1 };
alignas(4) float power{ 1.0f };
alignas(4) int use_shadow{ 1 };
alignas(4) int n{ 3 };
};
struct PolyVertStruct
{
alignas(16) glm::vec3 v{ 0, 0, 0 };
};
static const GLuint Sizeof_Point = sizeof(PointStruct);
static const GLuint Sizeof_Sun = sizeof(SunStruct);
static const GLuint Sizeof_Spot = sizeof(SpotStruct);
static const GLuint Sizeof_Area = sizeof(AreaStruct);
static const GLuint Sizeof_Poly = sizeof(PolyStruct);
static const GLuint Sizeof_PolyVert = sizeof(PolyVertStruct);
struct SceneInfo {
int point_count{ 0 };
int sun_count{ 0 };
int spot_count{ 0 };
int area_count{ 0 };
int poly_count{ 0 };
int poly_verts_count{ 0 };
};
public:
std::vector<PointStruct> point_list;
std::vector<SunStruct> sun_list;
std::vector<SpotStruct> spot_list;
std::vector<AreaStruct> area_list;
std::vector<PolyStruct> poly_list;
std::vector<PolyVertStruct> poly_verts;
mutable std::unordered_map<int, Texture> shadow_cache;
std::unordered_map<int, Texture> shadow_maps;
std::unordered_map<int, glm::mat4> proj_matrices;
StorageBuffer point_buffer;
StorageBuffer sun_buffer;
StorageBuffer spot_buffer;
StorageBuffer area_buffer;
StorageBuffer poly_buffer;
StorageBuffer poly_verts_buffer;
UniformBuffer info;
private:
using _LightInfo = std::tuple<int, Light*>;
std::unordered_map<int, _LightInfo> light_info_cache;
GLuint cache_w{};
GLuint cache_h{};
bool prev_moment_shadow{ false };
static std::array<FrameBuffer, 4> _shadowmap_buffer;
static std::array<ChainedShader, 4> _shadowmap_shader;
static std::array<glm::mat4, 6> _point_6side;
public:
ShadowSystem();
~ShadowSystem();
void Init();
void Bind() const;
public:
static constexpr int shadow_slot[16]{31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16};
public:
void ParseLightData(const std::unordered_map<int, std::shared_ptr<Light>>& light_list, bool using_moment_shadow = false);
void ParsePolygonLightData(const std::unordered_map<int, std::shared_ptr<PolygonLight>>& poly_light_list);
public:
SceneInfo GetSceneInfo() const;
GLsizei GetTotalCount() const;
GLuint GetSlotOffset(LightType _type) const;
void Resize(GLuint _w, GLuint _h);
public:
void UpdateLight(Light* light);
void Update(int frame, RenderConfigs* config);
void BindShadowMap() const;
public:
void InitShadowMap(Light* light, bool using_moment_shadow);
void UpdateProjMatrix(Light* light);
void ConstructSAT(Light* light, const RenderConfigs* config);
public:
static void EnableShadowMap();
void BindShadowMapBuffer(Light* light, Texture& shadow_map);
void BindShadowMapShader(Light* light, const glm::mat4& proj);
void BindTargetTrans(Light* light, const glm::mat4& _trans);
};