#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 "../camera/HydraCamera.h" #include "../renderer/HydraRenderer.h" #include "../ecs/HydraECS.h" #include "../ecs/systems/HydraRenderSystem.h" #include "../mesh/StandardVertex.h" #include "../actor/HydraActorManager.h" #include "../actor/HydraOutputActor.h" void HydraDeferredPipeline::Initialise() { _CreateUBOs(); //already on the render thread so dont neet another job _CreateOutputActor(); _CreateFrameBuffer(); _CreateColourRenderStage(); _CreateOutputRenderStage(); } 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); } 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("PositionsBuffer"); 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("MaterialBuffer"); 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("TextureBuffer"); 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, 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"); HydraShaderBinding shader_binding = {}; shader_binding.block_name.push_back("PositionsBuffer"); 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("TextureBuffer"); 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("LightBuffer"); 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); render_stage->Initialise(shader_path + "deferred_output_shader.vert", shader_path + "deferred_output_shader.frag", "", shader_binding, 0, textures, false, HYDRA_RENDERABLE_TYPE::HYDRA_OUTPUT); 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)); } 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); }