2026-07-28 00:26:04 +01:00
|
|
|
#include "HydraShadowPipeline.h"
|
|
|
|
|
|
|
|
|
|
#include "HydraRenderStage.h"
|
|
|
|
|
#include "../engine/HydraEngine.h"
|
|
|
|
|
#include "../buffer/HydraBufferManager.h"
|
|
|
|
|
#include "../buffer/HydraTextureBufferManager.h"
|
|
|
|
|
#include "../buffer/HydraLightBufferManager.h"
|
|
|
|
|
#include "PerFrameUBO.hpp"
|
|
|
|
|
|
|
|
|
|
#include "../camera/HydraCamera.h"
|
|
|
|
|
#include "../renderer/HydraRenderer.h"
|
|
|
|
|
#include "../ecs/HydraECS.h"
|
|
|
|
|
#include "../ecs/systems/HydraRenderSystem.h"
|
2026-08-04 18:32:37 +01:00
|
|
|
#include "../ecs/systems/HydraDirectionalShadowSourceSystem.h"
|
2026-08-04 22:40:48 +01:00
|
|
|
#include "../ecs/systems/HydraSpotShadowSourceSystem.h"
|
|
|
|
|
#include "../ecs/components/HydraLightComponent.h"
|
2026-07-28 00:26:04 +01:00
|
|
|
#include "../mesh/StandardVertex.h"
|
|
|
|
|
#include "../actor/HydraActorManager.h"
|
|
|
|
|
#include "../actor/HydraOutputActor.h"
|
|
|
|
|
|
|
|
|
|
void HydraShadowPipeline::Initialise()
|
|
|
|
|
{
|
2026-08-04 22:40:48 +01:00
|
|
|
m_render_stages.resize(2);
|
2026-07-28 00:26:04 +01:00
|
|
|
_CreateUBOs();
|
2026-08-04 22:40:48 +01:00
|
|
|
_CreateDirectionalRenderStage();
|
|
|
|
|
_CreateSpotRenderStage();
|
2026-07-28 00:26:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HydraShadowPipeline::Shutdown()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HydraShadowPipeline::Render()
|
|
|
|
|
{
|
2026-07-28 19:02:45 +01:00
|
|
|
glViewport(0, 0, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE);
|
|
|
|
|
|
|
|
|
|
glEnable(GL_DEPTH_TEST); // Depth testing must be active
|
|
|
|
|
glDepthMask(GL_TRUE); // Depth buffer must be writable
|
|
|
|
|
glDepthFunc(GL_LESS);
|
2026-08-03 22:34:52 +01:00
|
|
|
|
2026-08-04 22:40:48 +01:00
|
|
|
_RenderDirectionalShadowMaps();
|
|
|
|
|
_RenderSpotShadowMaps();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HydraShadowPipeline::_RenderDirectionalShadowMaps()
|
|
|
|
|
{
|
|
|
|
|
HydraECS *ecs = GetEngine()->ECS();
|
|
|
|
|
std::shared_ptr<HydraRenderSystem> render_system = ecs->GetSystem<HydraRenderSystem>();
|
|
|
|
|
std::shared_ptr<HydraDirectionalShadowSourceSystem> shadow_system = ecs->GetSystem<HydraDirectionalShadowSourceSystem>();
|
2026-08-03 22:34:52 +01:00
|
|
|
|
2026-07-28 19:02:45 +01:00
|
|
|
for (HydraID entity_id : shadow_system->Entities)
|
2026-07-28 00:26:04 +01:00
|
|
|
{
|
2026-08-04 18:32:37 +01:00
|
|
|
HydraDirectionalShadowSourceComponent shad_comp = GetEngine()->ECS()->GetComponent<HydraDirectionalShadowSourceComponent>(entity_id);
|
2026-08-04 22:40:48 +01:00
|
|
|
HydraLightComponent light_comp = GetEngine()->ECS()->GetComponent<HydraLightComponent>(entity_id);
|
|
|
|
|
_UpdateUBO(light_comp.shadow_map_id);
|
|
|
|
|
|
2026-07-28 19:02:45 +01:00
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, shad_comp.frame_buffer_id);
|
|
|
|
|
|
|
|
|
|
float depth_value = 1.0f;
|
2026-08-03 22:34:52 +01:00
|
|
|
float clear_colour[] = {0,0,0};
|
2026-07-28 19:02:45 +01:00
|
|
|
glClearNamedFramebufferfv(shad_comp.frame_buffer_id, GL_DEPTH, 0, &depth_value);
|
2026-08-03 22:34:52 +01:00
|
|
|
glClearNamedFramebufferfv(shad_comp.frame_buffer_id, GL_COLOR, 0, clear_colour);
|
2026-08-04 22:40:48 +01:00
|
|
|
m_render_stages[DIRECTIONAL_RENDER_STAGE]->Render(render_system->Entities, INVALID_HYDRA_ID);
|
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
2026-07-28 00:26:04 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-04 22:40:48 +01:00
|
|
|
void HydraShadowPipeline::_RenderSpotShadowMaps()
|
|
|
|
|
{
|
|
|
|
|
HydraECS *ecs = GetEngine()->ECS();
|
|
|
|
|
std::shared_ptr<HydraRenderSystem> render_system = ecs->GetSystem<HydraRenderSystem>();
|
|
|
|
|
std::shared_ptr<HydraSpotShadowSourceSystem> shadow_system = ecs->GetSystem<HydraSpotShadowSourceSystem>();
|
|
|
|
|
|
|
|
|
|
for (HydraID entity_id : shadow_system->Entities)
|
|
|
|
|
{
|
|
|
|
|
HydraSpotShadowSourceComponent shad_comp = GetEngine()->ECS()->GetComponent<HydraSpotShadowSourceComponent>(entity_id);
|
|
|
|
|
HydraLightComponent light_comp = GetEngine()->ECS()->GetComponent<HydraLightComponent>(entity_id);
|
|
|
|
|
_UpdateUBO(light_comp.shadow_map_id);
|
|
|
|
|
|
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, shad_comp.frame_buffer_id);
|
|
|
|
|
|
|
|
|
|
float depth_value = 1.0f;
|
|
|
|
|
float clear_colour[] = {0,0,0};
|
|
|
|
|
glClearNamedFramebufferfv(shad_comp.frame_buffer_id, GL_DEPTH, 0, &depth_value);
|
|
|
|
|
glClearNamedFramebufferfv(shad_comp.frame_buffer_id, GL_COLOR, 0, clear_colour);
|
|
|
|
|
m_render_stages[SPOT_RENDER_STAGE]->Render(render_system->Entities, INVALID_HYDRA_ID);
|
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HydraShadowPipeline::_CreateDirectionalRenderStage()
|
2026-07-28 00:26:04 +01:00
|
|
|
{
|
2026-07-28 19:02:45 +01:00
|
|
|
HydraRenderStage *render_stage = new HydraRenderStage();
|
2026-07-28 00:26:04 +01:00
|
|
|
std::string shader_path = std::string(shader_base);
|
2026-07-28 19:02:45 +01:00
|
|
|
HydraBufferManager *buffer_manager = GetEngine()->BufferManager();
|
2026-07-28 00:26:04 +01:00
|
|
|
|
2026-07-28 19:02:45 +01:00
|
|
|
HydraID pos_buffer_id = buffer_manager->FindBuffer("PositionsBuffer");
|
2026-08-03 22:34:52 +01:00
|
|
|
HydraID mat_buffer_id = buffer_manager->FindBuffer("MaterialBuffer");
|
|
|
|
|
HydraID tex_buffer_id = buffer_manager->FindBuffer("TextureBuffer");
|
2026-07-28 19:02:45 +01:00
|
|
|
HydraID shadow_buffer_id = buffer_manager->FindBuffer("ShadowBuffer");
|
2026-07-28 00:26:04 +01:00
|
|
|
HydraID per_frame_buffer_id = buffer_manager->FindBuffer("ShadowPerFrameUBO");
|
|
|
|
|
|
|
|
|
|
HydraShaderBinding shader_binding = {};
|
2026-07-28 19:02:45 +01:00
|
|
|
|
2026-08-03 22:34:52 +01:00
|
|
|
shader_binding.block_name.push_back("positions_buffer");
|
2026-07-28 00:26:04 +01:00
|
|
|
shader_binding.binding_point.push_back(1);
|
|
|
|
|
shader_binding.buffer_id.push_back(pos_buffer_id);
|
|
|
|
|
shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER);
|
2026-07-28 19:02:45 +01:00
|
|
|
|
2026-08-03 22:34:52 +01:00
|
|
|
shader_binding.block_name.push_back("material_buffer");
|
|
|
|
|
shader_binding.binding_point.push_back(2);
|
|
|
|
|
shader_binding.buffer_id.push_back(mat_buffer_id);
|
|
|
|
|
shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER);
|
|
|
|
|
|
|
|
|
|
shader_binding.block_name.push_back("texture_buffer");
|
|
|
|
|
shader_binding.binding_point.push_back(3);
|
|
|
|
|
shader_binding.buffer_id.push_back(tex_buffer_id);
|
|
|
|
|
shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER);
|
|
|
|
|
|
|
|
|
|
shader_binding.block_name.push_back("shadow_map_sets");
|
2026-07-28 19:02:45 +01:00
|
|
|
shader_binding.binding_point.push_back(5);
|
2026-07-28 00:26:04 +01:00
|
|
|
shader_binding.buffer_id.push_back(shadow_buffer_id);
|
|
|
|
|
shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER);
|
|
|
|
|
|
|
|
|
|
shader_binding.block_name.push_back("shadow_per_frame");
|
2026-07-28 19:02:45 +01:00
|
|
|
shader_binding.binding_point.push_back(1);
|
2026-07-28 00:26:04 +01:00
|
|
|
shader_binding.buffer_id.push_back(per_frame_buffer_id);
|
|
|
|
|
shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_UBO_BUFFER);
|
|
|
|
|
|
|
|
|
|
std::vector<uint32_t> textures;
|
|
|
|
|
|
2026-08-04 17:39:07 +01:00
|
|
|
render_stage->Initialise(shader_path + "shadow_cascade_shader.vert",
|
|
|
|
|
shader_path + "shadow_cascade_shader.frag",
|
|
|
|
|
shader_path + "shadow_cascade_shader.geom",
|
2026-07-28 19:02:45 +01:00
|
|
|
shader_binding,
|
|
|
|
|
0,
|
|
|
|
|
textures,
|
|
|
|
|
true,
|
2026-08-03 22:34:52 +01:00
|
|
|
GL_FRONT,
|
|
|
|
|
true,
|
2026-07-28 19:02:45 +01:00
|
|
|
HYDRA_RENDERABLE_TYPE::HYDRA_COLOUR);
|
2026-08-04 22:40:48 +01:00
|
|
|
m_render_stages[DIRECTIONAL_RENDER_STAGE] = render_stage;
|
2026-07-28 00:26:04 +01:00
|
|
|
}
|
|
|
|
|
|
2026-08-04 22:40:48 +01:00
|
|
|
void HydraShadowPipeline::_CreateSpotRenderStage()
|
|
|
|
|
{
|
|
|
|
|
HydraRenderStage *render_stage = new HydraRenderStage();
|
|
|
|
|
std::string shader_path = std::string(shader_base);
|
|
|
|
|
HydraBufferManager *buffer_manager = GetEngine()->BufferManager();
|
|
|
|
|
|
|
|
|
|
HydraID pos_buffer_id = buffer_manager->FindBuffer("PositionsBuffer");
|
|
|
|
|
HydraID mat_buffer_id = buffer_manager->FindBuffer("MaterialBuffer");
|
|
|
|
|
HydraID tex_buffer_id = buffer_manager->FindBuffer("TextureBuffer");
|
|
|
|
|
HydraID shadow_buffer_id = buffer_manager->FindBuffer("ShadowBuffer");
|
|
|
|
|
HydraID per_frame_buffer_id = buffer_manager->FindBuffer("ShadowPerFrameUBO");
|
|
|
|
|
|
|
|
|
|
HydraShaderBinding shader_binding = {};
|
|
|
|
|
|
|
|
|
|
shader_binding.block_name.push_back("positions_buffer");
|
|
|
|
|
shader_binding.binding_point.push_back(1);
|
|
|
|
|
shader_binding.buffer_id.push_back(pos_buffer_id);
|
|
|
|
|
shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER);
|
|
|
|
|
|
|
|
|
|
shader_binding.block_name.push_back("material_buffer");
|
|
|
|
|
shader_binding.binding_point.push_back(2);
|
|
|
|
|
shader_binding.buffer_id.push_back(mat_buffer_id);
|
|
|
|
|
shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER);
|
|
|
|
|
|
|
|
|
|
shader_binding.block_name.push_back("texture_buffer");
|
|
|
|
|
shader_binding.binding_point.push_back(3);
|
|
|
|
|
shader_binding.buffer_id.push_back(tex_buffer_id);
|
|
|
|
|
shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER);
|
|
|
|
|
|
|
|
|
|
shader_binding.block_name.push_back("shadow_map_sets");
|
|
|
|
|
shader_binding.binding_point.push_back(5);
|
|
|
|
|
shader_binding.buffer_id.push_back(shadow_buffer_id);
|
|
|
|
|
shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER);
|
|
|
|
|
|
|
|
|
|
shader_binding.block_name.push_back("shadow_per_frame");
|
|
|
|
|
shader_binding.binding_point.push_back(1);
|
|
|
|
|
shader_binding.buffer_id.push_back(per_frame_buffer_id);
|
|
|
|
|
shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_UBO_BUFFER);
|
|
|
|
|
|
|
|
|
|
std::vector<uint32_t> textures;
|
|
|
|
|
|
|
|
|
|
render_stage->Initialise(shader_path + "shadow_spot_shader.vert",
|
|
|
|
|
shader_path + "shadow_spot_shader.frag",
|
|
|
|
|
"",
|
|
|
|
|
shader_binding,
|
|
|
|
|
0,
|
|
|
|
|
textures,
|
|
|
|
|
true,
|
|
|
|
|
GL_FRONT,
|
|
|
|
|
true,
|
|
|
|
|
HYDRA_RENDERABLE_TYPE::HYDRA_COLOUR);
|
|
|
|
|
m_render_stages[SPOT_RENDER_STAGE] = render_stage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-07-28 00:26:04 +01:00
|
|
|
void HydraShadowPipeline::_UpdateUBO(uint32_t shadow_idx)
|
|
|
|
|
{
|
2026-07-28 19:02:45 +01:00
|
|
|
HydraBufferManager *buffer_manager = GetEngine()->BufferManager();
|
|
|
|
|
buffer_manager->UpdatePartialBuffer(m_per_frame_ubo, 3 * sizeof(float), sizeof(uint32_t), &shadow_idx);
|
2026-07-28 00:26:04 +01:00
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, m_per_frame_ubo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HydraShadowPipeline::_BindFrameBufferAttachments(HydraID entity_id)
|
|
|
|
|
{
|
2026-08-04 18:32:37 +01:00
|
|
|
HydraDirectionalShadowSourceComponent shad_comp = GetEngine()->ECS()->GetComponent<HydraDirectionalShadowSourceComponent>(entity_id);
|
2026-07-28 19:02:45 +01:00
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, shad_comp.frame_buffer_id);
|
|
|
|
|
glBindTextureUnit(0, 0);
|
2026-07-28 00:26:04 +01:00
|
|
|
}
|
|
|
|
|
|
2026-07-28 19:02:45 +01:00
|
|
|
|
2026-07-28 00:26:04 +01:00
|
|
|
void HydraShadowPipeline::_CreateUBOs()
|
|
|
|
|
{
|
2026-07-28 19:02:45 +01:00
|
|
|
HydraBufferManager *buffer_manager = GetEngine()->BufferManager();
|
2026-07-28 00:26:04 +01:00
|
|
|
|
2026-07-28 19:02:45 +01:00
|
|
|
m_per_frame_ubo = buffer_manager->CreateGPUBuffer("ShadowPerFrameUBO",
|
|
|
|
|
sizeof(float) * 4, 0, HYDRA_BUFFER_TYPE::HYDRA_UBO_BUFFER);
|
2026-07-28 00:26:04 +01:00
|
|
|
}
|