#include "HydraShadowSourceSystem.h" #include "../../engine/HydraEngine.h" #include "../../camera/HydraCamera.h" #include "../HydraECS.h" #include "../components/HydraShadowSourceComponent.h" #include "../components/HydraPositionComponent.h" #include "../components/HydraLightComponent.h" #include "../../buffer/HydraShadowBuffer.h" #include "../../buffer/HydraTextureBufferManager.h" #include "../../scheduler/HydraTaskScheduler.h" #include "../../task/buffer/HydraCreateGPUBufferTask.hpp" #include "../../task/buffer/HydraUpdateWholeGPUBufferTask.hpp" #include "../../task/buffer/HydraUpdatePartialGPUBufferTask.hpp" #include "../../task/buffer/HydraCreateUnBoundTextureTask.hpp" #include "../../actor/HydraActorManager.h" void HydraShadowSourceSystem::Initialise() { HydraTaskScheduler *task_scheduler = GetEngine()->TaskScheduler(); HydraID create_gpu_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraCreateGPUBufferTask *task = static_cast(task_scheduler->GetTask(create_gpu_buffer_task_id)); task->Intialise("ShadowBuffer", 1, MAX_SHADOWS * sizeof(HydraShadowBuffer), &m_shadow_buffer_id, HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER); task_scheduler->WaitForTask(create_gpu_buffer_task_id); } void HydraShadowSourceSystem::InitialiseComponent(HydraID entity_id) { HydraEngine* engine = GetEngine(); HydraECS* ecs = engine->ECS(); HydraLightComponent& light_comp = ecs->GetComponent(entity_id); switch(light_comp.light_type) { case (int)HYDRA_LIGHT_TYPE::HYDRA_LIGHT_DIRECTIONAL: _InitialiseDirectionalLight(entity_id); break; } } void HydraShadowSourceSystem::UpdateSystem(float delta_t_seconds) { HydraEngine* engine = GetEngine(); HydraECS* ecs = engine->ECS(); std::vector shadows; for(HydraID entity_id:Entities) { HydraLightComponent& light_comp = ecs->GetComponent(entity_id); switch(light_comp.light_type) { case (int)HYDRA_LIGHT_TYPE::HYDRA_LIGHT_DIRECTIONAL: _UpdateDirectionalLight(entity_id); break; } HydraShadowSourceComponent shad_comp = ecs->GetComponent(entity_id); shadows.push_back(shad_comp); } _WriteToGPU(shadows); } void HydraShadowSourceSystem::_UpdateDirectionalLight(HydraID entity_id) { HydraEngine* engine = GetEngine(); HydraECS* ecs = engine->ECS(); HydraPositionComponent pos_comp = ecs->GetComponent(entity_id); HydraShadowSourceComponent& shad_comp = ecs->GetComponent(entity_id); float view_size = 5.0f; float view_near = -5.0f; float view_far = 5.0f; float PI = 3.1415927; float TWO_PI = 6.2831854; glm::vec3 light_dir = glm::vec3(0, 0, -1); glm::mat3 light_rot = glm::mat3(1); glm::vec3 light_euler = pos_comp.orientation; light_rot = glm::eulerAngleXYZ(light_euler.x, light_euler.y, light_euler.z); light_dir = light_rot * light_dir; light_dir = glm::normalize(light_dir); glm::vec3 camera_pos = GetEngine()->Camera()->GetPosition(); for (uint32_t i = 0; i < 6; i++) { glm::vec3 light_pos = camera_pos; // - (light_dir * light_distance); glm::mat4 light_trans = glm::translate(light_pos * glm::vec3(-1, -1, -1)); glm::mat4 light_orient = glm::eulerAngleXYZ(light_euler.x, light_euler.y, light_euler.z); glm::mat4 view = light_orient * light_trans; glm::mat4 proj = glm::orthoRH(view_size, -view_size, -view_size, view_size, -15000, 15000); // glm::mat4 proj = glm::orthoRH(view_size, -view_size, -view_size, view_size, view_near, view_far); shad_comp.far_plane[i] = view_far; shad_comp.near_plane[i] = view_near; shad_comp.light_space_proj[i] = proj; shad_comp.light_space_view[i] = view; view_far *= 3.0f; view_near = -view_far; view_size *= 3.0f; } } void HydraShadowSourceSystem::_InitialiseDirectionalLight(HydraID entity_id) { HydraEngine* engine = GetEngine(); HydraECS* ecs = engine->ECS(); HydraTextureBufferManager* tex_man = engine->TextureBufferManager(); HydraShadowSourceComponent& shad_comp = ecs->GetComponent(entity_id); shad_comp.entity_id = entity_id; shad_comp.cascade_count = 6; HydraTaskScheduler *task_scheduler = GetEngine()->TaskScheduler(); HydraID create_texture_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraCreateUnBoundTextureTask *task = static_cast(task_scheduler->GetTask(create_texture_task_id)); task->Initialise("shadow", SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, GL_R32F, GL_R32F, GL_LINEAR, GL_LINEAR, 6, GL_BYTE, 0, nullptr, &shad_comp.shadow_texture_id); task_scheduler->WaitForTask(create_texture_task_id); } void HydraShadowSourceSystem::_WriteToGPU(std::vector shadows) { HydraEngine* engine = GetEngine(); HydraECS* ecs = engine->ECS(); void *buffer = static_cast(shadows.data()); HydraTaskScheduler *task_scheduler = GetEngine()->TaskScheduler(); HydraID update_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraUpdatePartialGPUBufferTask *task = static_cast(task_scheduler->GetTask(update_buffer_task_id)); task->Intialise(m_shadow_buffer_id, 0, sizeof(HydraLightComponent) * shadows.size(), buffer); task_scheduler->WaitForTask(update_buffer_task_id); }