#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" #include "../ecs/systems/HydraDirectionalShadowSourceSystem.h" #include "../ecs/systems/HydraSpotShadowSourceSystem.h" #include "../ecs/components/HydraLightComponent.h" #include "../mesh/StandardVertex.h" #include "../actor/HydraActorManager.h" #include "../actor/HydraOutputActor.h" void HydraShadowPipeline::Initialise() { m_render_stages.resize(2); _CreateUBOs(); _CreateDirectionalRenderStage(); _CreateSpotRenderStage(); } void HydraShadowPipeline::Shutdown() { } void HydraShadowPipeline::Render() { 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); _RenderDirectionalShadowMaps(); _RenderSpotShadowMaps(); } void HydraShadowPipeline::_RenderDirectionalShadowMaps() { HydraECS *ecs = GetEngine()->ECS(); std::shared_ptr render_system = ecs->GetSystem(); std::shared_ptr shadow_system = ecs->GetSystem(); for (HydraID entity_id : shadow_system->Entities) { HydraDirectionalShadowSourceComponent shad_comp = GetEngine()->ECS()->GetComponent(entity_id); HydraLightComponent light_comp = GetEngine()->ECS()->GetComponent(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[DIRECTIONAL_RENDER_STAGE]->Render(render_system->Entities, INVALID_HYDRA_ID); glBindFramebuffer(GL_FRAMEBUFFER, 0); } } void HydraShadowPipeline::_RenderSpotShadowMaps() { HydraECS *ecs = GetEngine()->ECS(); std::shared_ptr render_system = ecs->GetSystem(); std::shared_ptr shadow_system = ecs->GetSystem(); for (HydraID entity_id : shadow_system->Entities) { HydraSpotShadowSourceComponent shad_comp = GetEngine()->ECS()->GetComponent(entity_id); HydraLightComponent light_comp = GetEngine()->ECS()->GetComponent(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() { 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("DirectionalShadowBuffer"); 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("directional_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 textures; render_stage->Initialise(shader_path + "shadow_cascade_shader.vert", shader_path + "shadow_cascade_shader.frag", shader_path + "shadow_cascade_shader.geom", shader_binding, 0, textures, true, GL_FRONT, true, HYDRA_RENDERABLE_TYPE::HYDRA_COLOUR); m_render_stages[DIRECTIONAL_RENDER_STAGE] = render_stage; } 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("SpotShadowBuffer"); 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("spot_shadow_map_sets"); shader_binding.binding_point.push_back(6); 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 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; } void HydraShadowPipeline::_UpdateUBO(uint32_t shadow_idx) { HydraBufferManager *buffer_manager = GetEngine()->BufferManager(); buffer_manager->UpdatePartialBuffer(m_per_frame_ubo, 3 * sizeof(float), sizeof(uint32_t), &shadow_idx); glBindBuffer(GL_UNIFORM_BUFFER, m_per_frame_ubo); } void HydraShadowPipeline::_BindFrameBufferAttachments(HydraID entity_id) { HydraDirectionalShadowSourceComponent shad_comp = GetEngine()->ECS()->GetComponent(entity_id); glBindFramebuffer(GL_FRAMEBUFFER, shad_comp.frame_buffer_id); glBindTextureUnit(0, 0); } void HydraShadowPipeline::_CreateUBOs() { HydraBufferManager *buffer_manager = GetEngine()->BufferManager(); m_per_frame_ubo = buffer_manager->CreateGPUBuffer("ShadowPerFrameUBO", sizeof(float) * 4, 0, HYDRA_BUFFER_TYPE::HYDRA_UBO_BUFFER); }