#include "HydraDeferredPipeline.h" #include "HydraRenderStage.h" #include "../engine/HydraEngine.h" #include "../buffer/HydraBufferManager.h" #include "../buffer/HydraTextureBufferManager.h" #include "../buffer/HydraLightBufferManager.h" #include "PerFrameUBO.hpp" #include "TextureDebugUBO.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/components/HydraDirectionalShadowSourceComponent.h" #include "../ecs/systems/HydraSpotShadowSourceSystem.h" #include "../ecs/components/HydraSpotShadowSourceComponent.h" #include "../mesh/StandardVertex.h" #include "../actor/HydraActorManager.h" #include "../actor/HydraOutputActor.h" #include "../actor/HydraTextureDebugActor.h" void HydraDeferredPipeline::Initialise() { _CreateUBOs(); //already on the render thread so dont neet another job _CreateOutputActor(); _CreateFrameBuffer(); _CreateColourRenderStage(); _CreateOutputRenderStage(); _CreateTextureDebugOutputStage(); } void HydraDeferredPipeline::Shutdown() { for(uint32_t rs_idx =0; rs_idx ShutDown(); delete m_render_stages[rs_idx]; } glDeleteFramebuffers(1, &m_frame_buffer_id); } void HydraDeferredPipeline::Render() { _UpdateUBO(); HydraECS* ecs = GetEngine()->ECS(); std::shared_ptr render_system = ecs->GetSystem(); HydraRenderSettings render_settings = GetEngine()->RenderSettings(); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glViewport(0, 0, render_settings.ViewportWidth, render_settings.ViewportHeight); float clear_colour[4] = {0, 0, 0, 0}; float depth_value = 1; glClearNamedFramebufferfv(m_frame_buffer_id, GL_COLOR, 0, clear_colour); glClearNamedFramebufferfv(m_frame_buffer_id, GL_COLOR, 1, clear_colour); glClearNamedFramebufferfv(m_frame_buffer_id, GL_COLOR, 2, clear_colour); glClearNamedFramebufferfv(m_frame_buffer_id, GL_COLOR, 3, clear_colour); glClearNamedFramebufferfv(m_frame_buffer_id, GL_DEPTH, 0, &depth_value); float screen_colour[4] = {0.0f, 0.5f, 0.7f, 1.0f}; glClearNamedFramebufferfv(0, GL_COLOR, 0, screen_colour); glClearNamedFramebufferfv(0, GL_DEPTH, 0, &depth_value); for(uint32_t rs_idx = 0; rs_idx Render(render_system->Entities); } } void HydraDeferredPipeline::_UpdateUBO() { HydraCamera* camera = GetEngine()->Camera(); PerFrameUBO ubo = {}; uint32_t light_count = GetEngine()->GetLightCount(); ubo.view = camera->GetView(); ubo.proj = camera->GetProjection(); ubo.viewer_pos = camera->GetPosition(); ubo.light_count = light_count; HydraBufferManager* buffer_manager = GetEngine()->BufferManager(); buffer_manager->UpdateWholeBuffer(m_per_frame_ubo, &ubo); glBindBuffer(GL_UNIFORM_BUFFER, m_per_frame_ubo); PerFrameUBO output_ubo = {}; output_ubo.view = glm::mat4(1); output_ubo.proj = glm::ortho(-0.5f, 0.5f, -0.5f, 0.5f); output_ubo.viewer_pos = camera->GetPosition(); output_ubo.light_count = light_count; buffer_manager->UpdateWholeBuffer(m_per_frame_output_ubo, &output_ubo); glBindBuffer(GL_UNIFORM_BUFFER, m_per_frame_output_ubo); std::shared_ptr sys = GetEngine()->ECS()->GetSystem(); HydraID texture_id = 0; if(sys->Entities.size() > 0) { auto it = sys->Entities.begin(); HydraSpotShadowSourceComponent shad_comp = GetEngine()->ECS()->GetComponent(*it); texture_id = shad_comp.shadow_texture_id; } TextureDebugUBO texture_ubo = {}; texture_ubo.view = glm::translate(glm::vec3(1,1,0)); texture_ubo.proj = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f); texture_ubo.shadow_idx = texture_id; buffer_manager->UpdateWholeBuffer(m_texture_debug_ubo, &texture_ubo); glBindBuffer(GL_UNIFORM_BUFFER, m_texture_debug_ubo); } void HydraDeferredPipeline::_CreateFrameBuffer() { HydraEngine* engine = GetEngine(); HydraTextureBufferManager* tex_buffer_manager = engine->TextureBufferManager(); HydraRenderSettings render_settings = engine->RenderSettings(); glGenFramebuffers(1, &m_frame_buffer_id); glBindFramebuffer(GL_FRAMEBUFFER, m_frame_buffer_id); HydraOutputActor* actor = static_cast(GetEngine()->ActorManager()->GetActor(m_output_actor_id)); HydraTextureBuffer depth_texture = tex_buffer_manager->GetTexture(actor->texture_buffers[0]); HydraTextureBuffer buffer_0_texture = tex_buffer_manager->GetTexture(actor->texture_buffers[1]); HydraTextureBuffer metal_rough_texture = tex_buffer_manager->GetTexture(actor->texture_buffers[2]); HydraTextureBuffer normal_texture = tex_buffer_manager->GetTexture(actor->texture_buffers[3]); HydraTextureBuffer position_texture = tex_buffer_manager->GetTexture(actor->texture_buffers[4]); glBindTexture(GL_TEXTURE_2D, buffer_0_texture.gl_tex_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buffer_0_texture.gl_tex_id, 0); glBindTexture(GL_TEXTURE_2D, metal_rough_texture.gl_tex_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, metal_rough_texture.gl_tex_id, 0); glBindTexture(GL_TEXTURE_2D, normal_texture.gl_tex_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normal_texture.gl_tex_id, 0); glBindTexture(GL_TEXTURE_2D, position_texture.gl_tex_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, position_texture.gl_tex_id, 0); glBindTexture(GL_TEXTURE_2D, depth_texture.gl_tex_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture.gl_tex_id, 0); GLenum draw_buffers[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3}; glDrawBuffers(4, draw_buffers); glBindTexture(GL_TEXTURE_2D, 0); tex_buffer_manager->BindTexture(depth_texture.texture_id, GL_TEXTURE_2D); tex_buffer_manager->BindTexture(buffer_0_texture.texture_id, GL_TEXTURE_2D); tex_buffer_manager->BindTexture(metal_rough_texture.texture_id, GL_TEXTURE_2D); tex_buffer_manager->BindTexture(normal_texture.texture_id, GL_TEXTURE_2D); tex_buffer_manager->BindTexture(position_texture.texture_id, GL_TEXTURE_2D); HydraBufferManager* buffer_manager = GetEngine()->BufferManager(); buffer_manager->UpdateWholeBuffer(m_output_texture_ubo, &actor->texture_buffers[0]); glBindBuffer(GL_UNIFORM_BUFFER, m_output_texture_ubo); } void HydraDeferredPipeline::_CreateColourRenderStage() { 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 per_frame_buffer_id = buffer_manager->FindBuffer("DeferredPerFrameUBO"); 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("uniform_per_frame"); shader_binding.binding_point.push_back(0); 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 + "deferred_shader.vert", shader_path + "deferred_shader.frag", "", shader_binding, m_frame_buffer_id, textures, true, GL_BACK, true, HYDRA_RENDERABLE_TYPE::HYDRA_COLOUR); m_render_stages.push_back(render_stage); } void HydraDeferredPipeline::_CreateOutputRenderStage() { HydraRenderStage* render_stage = new HydraRenderStage(); std::string shader_path = std::string(shader_base); HydraBufferManager* buffer_manager = GetEngine()->BufferManager(); std::vector textures; GetEngine()->ActorManager()->InitialiseActor(m_output_actor_id); HydraOutputActor* actor = static_cast(GetEngine()->ActorManager()->GetActor(m_output_actor_id)); HydraTextureBufferManager* tex_buf_manager = GetEngine()->TextureBufferManager(); HydraID pos_buffer_id = buffer_manager->FindBuffer("PositionsBuffer"); HydraID per_frame_buffer_id = buffer_manager->FindBuffer("DeferredOutputPerFrameUBO"); HydraID tex_buffer_id = buffer_manager->FindBuffer("TextureBuffer"); HydraID output_texture_buffer_id = buffer_manager->FindBuffer("DeferredOutputTextureUBO"); HydraID light_buffer_id = buffer_manager->FindBuffer("LightBuffer"); HydraID directional_shadow_buffer_id = buffer_manager->FindBuffer("DirectionalShadowBuffer"); HydraID spot_shadow_buffer_id = buffer_manager->FindBuffer("SpotShadowBuffer"); HydraShaderBinding shader_binding = {}; shader_binding.block_name.push_back("position_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("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("uniform_per_frame"); shader_binding.binding_point.push_back(0); shader_binding.buffer_id.push_back(per_frame_buffer_id); shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_UBO_BUFFER); shader_binding.block_name.push_back("uniform_output_textures"); shader_binding.binding_point.push_back(1); shader_binding.buffer_id.push_back(output_texture_buffer_id); shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_UBO_BUFFER); shader_binding.block_name.push_back("light_buffer"); shader_binding.binding_point.push_back(4); shader_binding.buffer_id.push_back(light_buffer_id); shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER); shader_binding.block_name.push_back("directional_shadow_buffer"); shader_binding.binding_point.push_back(5); shader_binding.buffer_id.push_back(directional_shadow_buffer_id); shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER); shader_binding.block_name.push_back("spot_shadow_buffer"); shader_binding.binding_point.push_back(6); shader_binding.buffer_id.push_back(spot_shadow_buffer_id); shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER); render_stage->Initialise(shader_path + "deferred_output_shader.vert", shader_path + "deferred_output_shader.frag", "", shader_binding, 0, textures, false, GL_BACK, true, HYDRA_RENDERABLE_TYPE::HYDRA_OUTPUT); m_render_stages.push_back(render_stage); } void HydraDeferredPipeline::_CreateTextureDebugOutputStage() { HydraRenderStage* render_stage = new HydraRenderStage(); std::string shader_path = std::string(shader_base); HydraBufferManager* buffer_manager = GetEngine()->BufferManager(); std::vector textures; GetEngine()->ActorManager()->InitialiseActor(m_output_actor_id); HydraOutputActor* actor = static_cast(GetEngine()->ActorManager()->GetActor(m_output_actor_id)); HydraTextureBufferManager* tex_buf_manager = GetEngine()->TextureBufferManager(); HydraID pos_buffer_id = buffer_manager->FindBuffer("PositionsBuffer"); HydraID tex_buffer_id = buffer_manager->FindBuffer("TextureBuffer"); HydraID texture_debug_ubo = buffer_manager->FindBuffer("TextureDebugUBO"); HydraShaderBinding shader_binding = {}; shader_binding.block_name.push_back("position_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("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("uniform_per_frame"); shader_binding.binding_point.push_back(0); shader_binding.buffer_id.push_back(texture_debug_ubo); shader_binding.buffer_type.push_back(HYDRA_BUFFER_TYPE::HYDRA_UBO_BUFFER); render_stage->Initialise(shader_path + "texture_debug_shader.vert", shader_path + "texture_debug_shader.frag", "", shader_binding, 0, textures, false, GL_BACK, false, HYDRA_RENDERABLE_TYPE::HYDRA_TEXTURE_DEBUG); m_render_stages.push_back(render_stage); } void HydraDeferredPipeline::_CreateOutputActor() { m_output_actor_id = GetEngine()->ActorManager()->CreateActor(); GetEngine()->ActorManager()->InitialiseActor(m_output_actor_id); HydraOutputActor* actor = static_cast(GetEngine()->ActorManager()->GetActor(m_output_actor_id)); m_texture_debug_actor_id = GetEngine()->ActorManager()->CreateActor(); GetEngine()->ActorManager()->InitialiseActor(m_texture_debug_actor_id); HydraTextureDebugActor* tex_actor = static_cast(GetEngine()->ActorManager()->GetActor(m_texture_debug_actor_id)); } void HydraDeferredPipeline::_CreateUBOs() { HydraBufferManager* buffer_manager = GetEngine()->BufferManager(); m_per_frame_ubo = buffer_manager->CreateGPUBuffer("DeferredPerFrameUBO", sizeof(PerFrameUBO), 0, HYDRA_BUFFER_TYPE::HYDRA_UBO_BUFFER); m_per_frame_output_ubo = buffer_manager->CreateGPUBuffer("DeferredOutputPerFrameUBO", sizeof(PerFrameUBO), 0, HYDRA_BUFFER_TYPE::HYDRA_UBO_BUFFER); m_output_texture_ubo = buffer_manager->CreateGPUBuffer("DeferredOutputTextureUBO", sizeof(uint32_t)*16, 0, HYDRA_BUFFER_TYPE::HYDRA_UBO_BUFFER); m_texture_debug_ubo = buffer_manager->CreateGPUBuffer("TextureDebugUBO", sizeof(TextureDebugUBO), 0, HYDRA_BUFFER_TYPE::HYDRA_UBO_BUFFER); }