Files
HydraV3/HydraEngine/source/pipeline/HydraDeferredPipeline.cpp
T

362 lines
16 KiB
C++
Raw Normal View History

2026-07-17 15:30:29 +01:00
#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"
2026-08-03 22:34:52 +01:00
#include "TextureDebugUBO.hpp"
2026-07-17 15:30:29 +01:00
#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"
#include "../ecs/components/HydraDirectionalShadowSourceComponent.h"
2026-08-06 21:11:33 +01:00
#include "../ecs/systems/HydraSpotShadowSourceSystem.h"
#include "../ecs/components/HydraSpotShadowSourceComponent.h"
2026-07-17 15:30:29 +01:00
#include "../mesh/StandardVertex.h"
#include "../actor/HydraActorManager.h"
#include "../actor/HydraOutputActor.h"
2026-08-03 22:34:52 +01:00
#include "../actor/HydraTextureDebugActor.h"
2026-07-17 15:30:29 +01:00
void HydraDeferredPipeline::Initialise()
{
_CreateUBOs();
//already on the render thread so dont neet another job
_CreateOutputActor();
_CreateFrameBuffer();
_CreateColourRenderStage();
2026-08-03 22:34:52 +01:00
_CreateOutputRenderStage();
_CreateTextureDebugOutputStage();
2026-07-17 15:30:29 +01:00
}
void HydraDeferredPipeline::Shutdown()
{
for(uint32_t rs_idx =0; rs_idx <m_render_stages.size(); rs_idx++)
{
m_render_stages[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<HydraRenderSystem> render_system = ecs->GetSystem<HydraRenderSystem>();
2026-07-28 19:02:45 +01:00
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);
2026-07-17 15:30:29 +01:00
for(uint32_t rs_idx = 0; rs_idx <m_render_stages.size(); rs_idx++)
{
m_render_stages[rs_idx]->Render(render_system->Entities);
2026-08-03 22:34:52 +01:00
}
2026-07-17 15:30:29 +01:00
}
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);
2026-08-03 22:34:52 +01:00
2026-08-06 21:11:33 +01:00
std::shared_ptr<HydraSpotShadowSourceSystem> sys = GetEngine()->ECS()->GetSystem<HydraSpotShadowSourceSystem>();
2026-08-03 22:34:52 +01:00
HydraID texture_id = 0;
if(sys->Entities.size() > 0)
{
auto it = sys->Entities.begin();
2026-08-06 21:11:33 +01:00
HydraSpotShadowSourceComponent shad_comp = GetEngine()->ECS()->GetComponent<HydraSpotShadowSourceComponent>(*it);
2026-08-03 22:34:52 +01:00
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);
2026-07-17 15:30:29 +01:00
}
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<HydraOutputActor*>(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);
2026-07-28 19:02:45 +01:00
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);
2026-07-17 15:30:29 +01:00
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 = {};
2026-08-03 22:34:52 +01:00
shader_binding.block_name.push_back("positions_buffer");
2026-07-17 15:30:29 +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-08-03 22:34:52 +01:00
shader_binding.block_name.push_back("material_buffer");
2026-07-17 15:30:29 +01:00
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);
2026-08-03 22:34:52 +01:00
shader_binding.block_name.push_back("texture_buffer");
2026-07-17 15:30:29 +01:00
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<uint32_t> textures;
render_stage->Initialise(shader_path + "deferred_shader.vert",
2026-07-28 00:26:04 +01:00
shader_path + "deferred_shader.frag", "",
2026-07-17 15:30:29 +01:00
shader_binding,
m_frame_buffer_id,
textures,
true,
2026-08-03 22:34:52 +01:00
GL_BACK,
true,
2026-07-17 15:30:29 +01:00
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<uint32_t> textures;
GetEngine()->ActorManager()->InitialiseActor(m_output_actor_id);
HydraOutputActor* actor = static_cast<HydraOutputActor*>(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");
2026-08-06 21:11:33 +01:00
HydraID directional_shadow_buffer_id = buffer_manager->FindBuffer("DirectionalShadowBuffer");
HydraID spot_shadow_buffer_id = buffer_manager->FindBuffer("SpotShadowBuffer");
2026-07-17 15:30:29 +01:00
HydraShaderBinding shader_binding = {};
2026-08-03 22:34:52 +01:00
shader_binding.block_name.push_back("position_buffer");
2026-07-17 15:30:29 +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-08-03 22:34:52 +01:00
shader_binding.block_name.push_back("texture_buffer");
2026-07-17 15:30:29 +01:00
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);
2026-08-03 22:34:52 +01:00
shader_binding.block_name.push_back("light_buffer");
2026-07-17 15:30:29 +01:00
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);
2026-08-06 21:11:33 +01:00
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);
2026-07-17 15:30:29 +01:00
2026-08-06 21:11:33 +01:00
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);
2026-07-17 15:30:29 +01:00
render_stage->Initialise(shader_path + "deferred_output_shader.vert",
2026-07-28 00:26:04 +01:00
shader_path + "deferred_output_shader.frag", "",
2026-07-17 15:30:29 +01:00
shader_binding,
0,
textures,
false,
2026-08-03 22:34:52 +01:00
GL_BACK,
true,
2026-07-17 15:30:29 +01:00
HYDRA_RENDERABLE_TYPE::HYDRA_OUTPUT);
m_render_stages.push_back(render_stage);
}
2026-08-03 22:34:52 +01:00
void HydraDeferredPipeline::_CreateTextureDebugOutputStage()
{
HydraRenderStage* render_stage = new HydraRenderStage();
std::string shader_path = std::string(shader_base);
HydraBufferManager* buffer_manager = GetEngine()->BufferManager();
std::vector<uint32_t> textures;
GetEngine()->ActorManager()->InitialiseActor(m_output_actor_id);
HydraOutputActor* actor = static_cast<HydraOutputActor*>(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);
}
2026-07-17 15:30:29 +01:00
void HydraDeferredPipeline::_CreateOutputActor()
{
m_output_actor_id = GetEngine()->ActorManager()->CreateActor<HydraOutputActor>();
GetEngine()->ActorManager()->InitialiseActor(m_output_actor_id);
HydraOutputActor* actor = static_cast<HydraOutputActor*>(GetEngine()->ActorManager()->GetActor(m_output_actor_id));
2026-08-03 22:34:52 +01:00
m_texture_debug_actor_id = GetEngine()->ActorManager()->CreateActor<HydraTextureDebugActor>();
GetEngine()->ActorManager()->InitialiseActor(m_texture_debug_actor_id);
HydraTextureDebugActor* tex_actor = static_cast<HydraTextureDebugActor*>(GetEngine()->ActorManager()->GetActor(m_texture_debug_actor_id));
2026-07-17 15:30:29 +01:00
}
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);
2026-08-03 22:34:52 +01:00
m_texture_debug_ubo = buffer_manager->CreateGPUBuffer("TextureDebugUBO",
sizeof(TextureDebugUBO), 0, HYDRA_BUFFER_TYPE::HYDRA_UBO_BUFFER);
2026-07-17 15:30:29 +01:00
}