From 9ff05731f619fb40bc211f94e83c3827bf361e79 Mon Sep 17 00:00:00 2001 From: kj16609 Date: Sat, 27 Sep 2025 14:44:46 -0400 Subject: [PATCH] Start basic shadowmap stuff --- .../src/gui/{camera.cpp => RenderCamera.cpp} | 6 +- src/editor/src/gui/core.hpp | 2 + src/editor/src/gui/drawStats.cpp | 40 +- src/editor/src/gui/preview.cpp | 6 +- src/editor/src/gui/preview.hpp | 4 +- src/engine/EngineContext.cpp | 61 +-- src/engine/EngineContext.hpp | 14 +- src/engine/FrameInfo.cpp | 13 +- src/engine/FrameInfo.hpp | 14 +- src/engine/assets/model/Model.cpp | 1 - src/engine/assets/model/Model.hpp | 3 - .../assets/model/builders/SceneBuilder.cpp | 2 +- src/engine/camera/CameraInfo.hpp | 2 + src/engine/camera/CameraManager.cpp | 69 +++- src/engine/camera/CameraManager.hpp | 15 +- src/engine/camera/CameraViewpoint.cpp | 240 +++++++++++ .../{Camera.hpp => CameraViewpoint.hpp} | 185 +++------ src/engine/camera/GBufferCompositor.cpp | 9 +- src/engine/camera/GBufferCompositor.hpp | 4 +- src/engine/camera/GBufferRenderer.cpp | 3 +- .../camera/{Camera.cpp => RenderCamera.cpp} | 306 ++++---------- src/engine/camera/RenderCamera.hpp | 110 +++++ src/engine/camera/ShadowMap.cpp | 167 ++++++++ src/engine/camera/ShadowMap.hpp | 55 +++ src/engine/camera/Swapchain.cpp | 80 ++++ src/engine/camera/Swapchain.hpp | 69 ++++ src/engine/constants.hpp | 2 + src/engine/descriptors/DescriptorPool.cpp | 10 +- src/engine/descriptors/DescriptorPool.hpp | 3 - .../components/CameraComponent.hpp | 6 +- src/engine/lighting/lights/Sun.cpp | 12 + src/engine/lighting/lights/Sun.hpp | 19 + src/engine/lighting/shadows/ShadowMap.cpp | 59 --- src/engine/lighting/shadows/ShadowMap.hpp | 47 --- src/engine/primitives/Frustum.hpp | 4 +- .../primitives/rotation/UniversalRotation.cpp | 5 + .../primitives/rotation/UniversalRotation.hpp | 2 + src/engine/rendering/devices/extensions.hpp | 2 + src/engine/rendering/pipelines/Attachment.hpp | 51 --- .../pipelines/v2/PipelineBuilder.cpp | 378 +++++++++--------- src/engine/scene/Scene.hpp | 2 +- .../systems/prerender/CullingSystem.cpp | 13 +- .../systems/prerender/CullingSystem.hpp | 2 +- .../systems/render/EntityRendererSystem.cpp | 17 +- src/engine/systems/render/LineDrawer.cpp | 4 +- src/shaders/composition.slang | 14 +- src/shaders/culling.slang | 2 +- src/shaders/objects/camera.slang | 7 + src/shaders/objects/gamemodel.slang | 37 +- src/shaders/objects/gbuffer.slang | 7 + src/shaders/shadowmap.slang | 27 +- src/shaders/textured.slang | 16 +- 52 files changed, 1373 insertions(+), 855 deletions(-) rename src/editor/src/gui/{camera.cpp => RenderCamera.cpp} (94%) create mode 100644 src/engine/camera/CameraViewpoint.cpp rename src/engine/camera/{Camera.hpp => CameraViewpoint.hpp} (52%) rename src/engine/camera/{Camera.cpp => RenderCamera.cpp} (61%) create mode 100644 src/engine/camera/RenderCamera.hpp create mode 100644 src/engine/camera/ShadowMap.cpp create mode 100644 src/engine/camera/ShadowMap.hpp create mode 100644 src/engine/camera/Swapchain.cpp create mode 100644 src/engine/camera/Swapchain.hpp create mode 100644 src/engine/lighting/lights/Sun.cpp create mode 100644 src/engine/lighting/lights/Sun.hpp delete mode 100644 src/engine/lighting/shadows/ShadowMap.cpp delete mode 100644 src/engine/lighting/shadows/ShadowMap.hpp diff --git a/src/editor/src/gui/camera.cpp b/src/editor/src/gui/RenderCamera.cpp similarity index 94% rename from src/editor/src/gui/camera.cpp rename to src/editor/src/gui/RenderCamera.cpp index badee38..f29b024 100644 --- a/src/editor/src/gui/camera.cpp +++ b/src/editor/src/gui/RenderCamera.cpp @@ -2,7 +2,7 @@ // Created by kj16609 on 7/23/24. // -#include "engine/camera/Camera.hpp" +#include "engine/camera/RenderCamera.hpp" #include @@ -13,7 +13,7 @@ namespace fgl::engine::gui { - void handleCameraInput( const FrameInfo& info, Camera& camera ) + void handleCameraInput( const FrameInfo& info, RenderCamera& camera ) { const auto delta_time { info.delta_time }; @@ -104,7 +104,7 @@ namespace fgl::engine::gui assert( camera_ptr ); - Camera& camera { *camera_ptr }; + RenderCamera& camera { *camera_ptr }; std::string name {}; diff --git a/src/editor/src/gui/core.hpp b/src/editor/src/gui/core.hpp index 59fc51f..f3b9984 100644 --- a/src/editor/src/gui/core.hpp +++ b/src/editor/src/gui/core.hpp @@ -31,6 +31,8 @@ namespace fgl::engine::gui void drawComponentsList( GameObject& game_object ); void drawSelectedComponent(); + void drawShadowmaps( const FrameInfo& info ); + void drawCameraOutputs( FrameInfo& info ); void drawStats( const FrameInfo& info ); diff --git a/src/editor/src/gui/drawStats.cpp b/src/editor/src/gui/drawStats.cpp index c2d9ffc..2487bf0 100644 --- a/src/editor/src/gui/drawStats.cpp +++ b/src/editor/src/gui/drawStats.cpp @@ -2,13 +2,14 @@ #include #include "assets/transfer/TransferManager.hpp" +#include "camera/CameraManager.hpp" +#include "camera/ShadowMap.hpp" #include "core.hpp" #include "engine/debug/profiling/counters.hpp" #include "engine/debug/timing/FlameGraph.hpp" #include "engine/flags.hpp" #include "engine/math/literals/size.hpp" #include "engine/memory/buffers/BufferHandle.hpp" -#include "memory/buffers/BufferHandle.hpp" #include "safe_include.hpp" namespace fgl::engine::gui @@ -123,6 +124,38 @@ namespace fgl::engine::gui } } + void drawShadowmaps( const FrameInfo& info ) + { + ImGui::Begin( "Shadowmaps" ); + + static std::unordered_map< int*, std::vector< Texture > > textures {}; + + bool move_sun { false }; + + move_sun = ImGui::Button( "Move sun shadowmap to camera" ); + + for ( const auto& weak_shadowmap : getShadowmaps() ) + { + if ( weak_shadowmap.expired() ) continue; + + auto shadowmap_ptr { weak_shadowmap.lock() }; + + ShadowMap& shadowmap { *shadowmap_ptr }; + + // if ( move_sun ) + { + shadowmap.m_camera->moveTo( CameraManager::instance().getPrimary()->getTransform() ); + } + + const FrameIndex frame_index { info.in_flight_idx }; + // camera.getCompositeSwapchain().m_gbuffer_target[ frame_index ]->drawImGui( target_size ); + + shadowmap.m_swapchain->depthTexture( frame_index )->drawImGui(); + } + + ImGui::End(); + } + void drawStats( const FrameInfo& info ) { ImGui::Begin( "Stats" ); @@ -143,6 +176,11 @@ namespace fgl::engine::gui debug::timing::render(); } + if ( ImGui::CollapsingHeader( "Shadowmaps" ) ) + { + drawShadowmaps( info ); + } + if ( ImGui::Button( "Reload shaders" ) ) { flags::triggerShaderReload(); diff --git a/src/editor/src/gui/preview.cpp b/src/editor/src/gui/preview.cpp index 24f5636..534646d 100644 --- a/src/editor/src/gui/preview.cpp +++ b/src/editor/src/gui/preview.cpp @@ -7,7 +7,7 @@ #include "engine/FrameInfo.hpp" #include "engine/assets/model/Model.hpp" #include "engine/assets/model/builders/SceneBuilder.hpp" -#include "engine/camera/Camera.hpp" +#include "engine/camera/RenderCamera.hpp" #include "engine/filesystem/scanner/FileScanner.hpp" #include "engine/filesystem/types.hpp" #include "engine/rendering/PresentSwapChain.hpp" @@ -126,7 +126,7 @@ namespace fgl::engine::gui inline void drawConfigBar( [[maybe_unused]] const FrameInfo& info, - [[maybe_unused]] const Camera& camera, + [[maybe_unused]] const RenderCamera& camera, [[maybe_unused]] const FrameIndex frame_index, std::uint_fast8_t& current ) { @@ -167,7 +167,7 @@ namespace fgl::engine::gui } } - void drawRenderingOutputs( FrameInfo& info, const Camera& camera ) + void drawRenderingOutputs( FrameInfo& info, const RenderCamera& camera ) { ZoneScoped; const auto frame_index { info.in_flight_idx }; diff --git a/src/editor/src/gui/preview.hpp b/src/editor/src/gui/preview.hpp index 6634e50..649d53f 100644 --- a/src/editor/src/gui/preview.hpp +++ b/src/editor/src/gui/preview.hpp @@ -7,12 +7,12 @@ namespace fgl::engine { struct FrameInfo; - class Camera; + class RenderCamera; } // namespace fgl::engine namespace fgl::engine::gui { - void drawRenderingOutputs( FrameInfo& info, const Camera& camera ); + void drawRenderingOutputs( FrameInfo& info, const RenderCamera& camera ); } // namespace fgl::engine::gui diff --git a/src/engine/EngineContext.cpp b/src/engine/EngineContext.cpp index e61b8cd..ed4ff41 100644 --- a/src/engine/EngineContext.cpp +++ b/src/engine/EngineContext.cpp @@ -11,9 +11,10 @@ #include #include "KeyboardMovementController.hpp" -#include "camera/Camera.hpp" #include "camera/CameraManager.hpp" #include "camera/GBufferRenderer.hpp" +#include "camera/RenderCamera.hpp" +#include "camera/ShadowMap.hpp" #include "debug/timing/FlameGraph.hpp" #include "engine/assets/model/builders/SceneBuilder.hpp" #include "engine/assets/transfer/TransferManager.hpp" @@ -27,49 +28,20 @@ namespace fgl::engine constexpr float MAX_DELTA_TIME { 0.5 }; inline static EngineContext* instance { nullptr }; - PerFrameArray< std::unique_ptr< descriptors::DescriptorSet > > createDrawCommandsDescriptors( - PerFrameArray< DeviceVector< vk::DrawIndexedIndirectCommand > >& gpu_draw_commands, - PerFrameArray< DeviceVector< InstanceRenderInfo > >& per_vertex_info ) - { - PerFrameArray< std::unique_ptr< descriptors::DescriptorSet > > descriptors {}; - - for ( std::uint16_t i = 0; i < gpu_draw_commands.size(); ++i ) - { - auto& command_buffer { gpu_draw_commands[ i ] }; - auto& per_vertex_buffer { per_vertex_info[ i ] }; - auto descriptor { COMMANDS_SET.create() }; - - descriptor->bindStorageBuffer( 0, command_buffer ); - descriptor->bindStorageBuffer( 1, per_vertex_buffer ); - descriptor->update(); - descriptor->setName( "Command Buffer + Vertex Buffer" ); - - descriptors[ i ] = std::move( descriptor ); - } - - return descriptors; - } - EngineContext::EngineContext() : m_ubo_buffer_pool( 1_MiB, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostVisible ), - m_draw_parameter_pool( - 4_MiB, - vk::BufferUsageFlagBits::eIndirectBuffer | vk::BufferUsageFlagBits::eStorageBuffer, - vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible ), - m_gpu_draw_commands( - constructPerFrame< DeviceVector< vk::DrawIndexedIndirectCommand > >( m_draw_parameter_pool ) ), - m_per_vertex_infos( m_model_buffers.m_generated_instance_info ), - m_gpu_draw_cmds_desc( createDrawCommandsDescriptors( m_gpu_draw_commands, m_per_vertex_infos ) ), - m_delta_time( 0.0 ) + m_delta_time( 0.0 ), + m_camera_manager() { ZoneScoped; using namespace fgl::literals::size_literals; instance = this; - // memory::TransferManager::createInstance( device, 128_MiB ); + m_camera_manager.createPrimary(); + m_sun = std::make_unique< Sun >(); - m_draw_parameter_pool->setDebugName( "Draw parameter pool" ); + // memory::TransferManager::createInstance( device, 128_MiB ); } static Average< float, 60 * 15 > rolling_ms_average; @@ -116,10 +88,19 @@ namespace fgl::engine auto sh_camera { current_camera_ptr.lock() }; - Camera& current_camera { *sh_camera }; + RenderCamera& current_camera { *sh_camera }; current_camera.pass( frame_info ); } + + for ( auto& shadow_map : getShadowmaps() ) + { + if ( shadow_map.expired() ) continue; + + auto shadowmap { shadow_map.lock() }; + + shadowmap->pass( frame_info ); + } } void EngineContext::renderFrame() @@ -136,9 +117,6 @@ namespace fgl::engine // Begin by getting every single instance ready. DeviceVector< PrimitiveInstanceInfo >& instances { m_model_buffers.m_primitive_instances.vec() }; - m_gpu_draw_commands[ in_flight_idx ].resize( instances.size() ); - m_model_buffers.m_generated_instance_info[ in_flight_idx ].resize( instances.size() ); - FrameInfo frame_info { in_flight_idx, present_idx, m_delta_time, @@ -148,8 +126,9 @@ namespace fgl::engine m_renderer.getCurrentTracyCTX(), *m_model_buffers.m_primitives_desc, *m_model_buffers.m_instances_desc, - *m_gpu_draw_cmds_desc[ in_flight_idx ], - m_gpu_draw_commands[ in_flight_idx ], + instances, + // *m_gpu_draw_cmds_desc[ in_flight_idx ], + // m_gpu_draw_commands[ in_flight_idx ], m_game_objects, this->m_renderer.getSwapChain() }; diff --git a/src/engine/EngineContext.hpp b/src/engine/EngineContext.hpp index 7a9d2e6..4a451e9 100644 --- a/src/engine/EngineContext.hpp +++ b/src/engine/EngineContext.hpp @@ -12,6 +12,7 @@ #include "engine/assets/transfer/TransferManager.hpp" #include "engine/math/literals/size.hpp" #include "engine/rendering/Renderer.hpp" +#include "lighting/lights/Sun.hpp" #include "scene/World.hpp" #include "systems/composition/GuiSystem.hpp" @@ -67,9 +68,6 @@ namespace fgl::engine // Memory pool for shader uniforms. memory::Buffer m_ubo_buffer_pool; - // Memory pool for matrix info and draw parameters - memory::Buffer m_draw_parameter_pool; - public: std::vector< std::shared_ptr< GameObject > > m_game_objects {}; @@ -78,22 +76,18 @@ namespace fgl::engine private: - PerFrameArray< DeviceVector< vk::DrawIndexedIndirectCommand > > m_gpu_draw_commands; - //TODO: Outright remove this. Or the one in model buffers. - PerFrameArray< DeviceVector< InstanceRenderInfo > >& m_per_vertex_infos; - PerFrameArray< std::unique_ptr< descriptors::DescriptorSet > > m_gpu_draw_cmds_desc; - MaterialManager m_material_manager {}; - CameraManager m_camera_manager {}; - memory::TransferManager m_transfer_manager { m_device, 512_MiB }; std::chrono::time_point< Clock > m_last_tick { Clock::now() }; DeltaTime m_delta_time; + CameraManager m_camera_manager {}; // World m_world; + std::unique_ptr< Sun > m_sun; + public: // ModelManager& models() { return m_model_manager; } diff --git a/src/engine/FrameInfo.cpp b/src/engine/FrameInfo.cpp index 705e5be..adffbdf 100644 --- a/src/engine/FrameInfo.cpp +++ b/src/engine/FrameInfo.cpp @@ -4,20 +4,21 @@ #include "FrameInfo.hpp" -#include "camera/Camera.hpp" #include "camera/GBufferSwapchain.hpp" +#include "camera/RenderCamera.hpp" namespace fgl::engine { - descriptors::DescriptorSet& FrameInfo::getGBufferDescriptor() const - { - return camera->getSwapchain().getGBufferDescriptor( in_flight_idx ); - } + // descriptors::DescriptorSet& FrameInfo::getGBufferDescriptor() const + // { + // return camera->getSwapchain().getGBufferDescriptor( in_flight_idx ); + // } descriptors::DescriptorSet& FrameInfo::getCameraDescriptor() const { - return camera->getDescriptor( in_flight_idx ); + FGL_ASSERT( camera != nullptr, "Camera not set" ); + return *camera->m_camera_info_descriptors[ in_flight_idx ]; } void FrameInfo::bindCamera( [[maybe_unused]] Pipeline& pipeline ) diff --git a/src/engine/FrameInfo.hpp b/src/engine/FrameInfo.hpp index 29ae8eb..2203702 100644 --- a/src/engine/FrameInfo.hpp +++ b/src/engine/FrameInfo.hpp @@ -21,6 +21,7 @@ namespace fgl::engine { + class CameraViewpoint; struct PrimitiveRenderInfo; struct PrimitiveInstanceInfo; class Pipeline; @@ -31,7 +32,7 @@ namespace fgl::engine } class PresentSwapChain; - class Camera; + class RenderCamera; struct PointLight { @@ -81,9 +82,9 @@ namespace fgl::engine CommandBuffers& command_buffer; - Camera* camera { nullptr }; + CameraViewpoint* camera { nullptr }; - std::vector< std::weak_ptr< Camera > >& m_camera_list; + std::vector< std::weak_ptr< RenderCamera > >& m_camera_list; // descriptors::DescriptorSet& global_descriptor_set; // OctTreeNode& game_objects; @@ -91,16 +92,17 @@ namespace fgl::engine descriptors::DescriptorSet& m_primitives_desc; descriptors::DescriptorSet& m_instances_desc; - descriptors::DescriptorSet& m_command_buffer_desc; + DeviceVector< PrimitiveInstanceInfo >& instances; + // descriptors::DescriptorSet& m_command_buffer_desc; // out for rendering process //! Populated commands buffer by the culling pass - DeviceVector< vk::DrawIndexedIndirectCommand >& m_commands; + // DeviceVector< vk::DrawIndexedIndirectCommand >& m_commands; std::vector< std::shared_ptr< GameObject > >& m_game_objects; // descriptors::DescriptorSet& gui_input_descriptor; - [[nodiscard]] descriptors::DescriptorSet& getGBufferDescriptor() const; + // [[nodiscard]] descriptors::DescriptorSet& getGBufferDescriptor() const; [[nodiscard]] descriptors::DescriptorSet& getCameraDescriptor() const; PresentSwapChain& swap_chain; diff --git a/src/engine/assets/model/Model.cpp b/src/engine/assets/model/Model.cpp index 484b97d..8cb78ea 100644 --- a/src/engine/assets/model/Model.cpp +++ b/src/engine/assets/model/Model.cpp @@ -38,7 +38,6 @@ namespace fgl::engine 1_GiB, vk::BufferUsageFlagBits::eIndexBuffer | vk::BufferUsageFlagBits::eTransferDst, vk::MemoryPropertyFlagBits::eDeviceLocal ), - m_generated_instance_info( constructPerFrame< DeviceVector< InstanceRenderInfo > >( m_vertex_buffer ) ), m_primitive_info( m_long_buffer ), m_primitive_instances( m_short_buffer ), m_model_instances( m_short_buffer ) diff --git a/src/engine/assets/model/Model.hpp b/src/engine/assets/model/Model.hpp index 1347066..ffde8af 100644 --- a/src/engine/assets/model/Model.hpp +++ b/src/engine/assets/model/Model.hpp @@ -104,9 +104,6 @@ namespace fgl::engine memory::Buffer m_vertex_buffer; memory::Buffer m_index_buffer; - //! Generated by the compute shader, This vector contains the instance info for each primitive. - PerFrameArray< DeviceVector< InstanceRenderInfo > > m_generated_instance_info; - //! contains the core primitive info, like vertex and index offsets and counts IndexedVector< PrimitiveRenderInfo > m_primitive_info; //! contains a list of all rendered primitives diff --git a/src/engine/assets/model/builders/SceneBuilder.cpp b/src/engine/assets/model/builders/SceneBuilder.cpp index ce7c648..2f9420e 100644 --- a/src/engine/assets/model/builders/SceneBuilder.cpp +++ b/src/engine/assets/model/builders/SceneBuilder.cpp @@ -14,7 +14,7 @@ #include "assets/model/ModelVertex.hpp" #include "engine/assets/stores.hpp" -#include "engine/camera/Camera.hpp" +#include "engine/camera/RenderCamera.hpp" #include "engine/debug/logging/logging.hpp" #include "engine/descriptors/DescriptorSet.hpp" #include "engine/gameobjects/GameObject.hpp" diff --git a/src/engine/camera/CameraInfo.hpp b/src/engine/camera/CameraInfo.hpp index 391e4d7..e0926ed 100644 --- a/src/engine/camera/CameraInfo.hpp +++ b/src/engine/camera/CameraInfo.hpp @@ -4,6 +4,8 @@ #pragma once +#include + namespace fgl::engine { diff --git a/src/engine/camera/CameraManager.cpp b/src/engine/camera/CameraManager.cpp index 3690d8c..bfac59f 100644 --- a/src/engine/camera/CameraManager.cpp +++ b/src/engine/camera/CameraManager.cpp @@ -4,8 +4,8 @@ #include "CameraManager.hpp" -#include "Camera.hpp" #include "GBufferRenderer.hpp" +#include "RenderCamera.hpp" #include "engine/debug/DEBUG_NAMES.hpp" #include "engine/math/literals/size.hpp" @@ -14,35 +14,64 @@ namespace fgl::engine using namespace fgl::literals::size_literals; - std::vector< std::weak_ptr< Camera > >& CameraManager::getCameras() - { - return cameras; - } - - std::shared_ptr< Camera >& CameraManager::getPrimary() - { - return m_primary_camera; - } + inline static CameraManager* camera_manager_instance { nullptr }; CameraManager::CameraManager() : m_renderer( std::make_shared< GBufferRenderer >() ), m_data_buffer( 4_KiB, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostVisible ) { - m_primary_camera = createCamera( { 1920, 1080 } ); - m_primary_camera->setName( CAMERA_EDITOR_NAME ); - } + FGL_ASSERT( camera_manager_instance == nullptr, "CameraManager already initialized" ); + camera_manager_instance = this; - std::shared_ptr< Camera > CameraManager::createCamera( const vk::Extent2D extent ) - { - std::shared_ptr< Camera > camera { new Camera( extent, m_data_buffer, m_renderer ) }; - - this->cameras.emplace_back( camera ); - - return camera; + m_data_buffer->setDebugName( "Camera data buffer" ); } CameraManager::~CameraManager() { m_primary_camera.reset(); + camera_manager_instance = nullptr; + } + + std::vector< std::weak_ptr< RenderCamera > >& CameraManager::getCameras() + { + return cameras; + } + + std::shared_ptr< RenderCamera >& CameraManager::getPrimary() + { + return m_primary_camera; + } + + void CameraManager::createPrimary() + { + m_primary_camera = createCamera( { 1920, 1080 } ); + m_primary_camera->setName( CAMERA_EDITOR_NAME ); + } + + CameraManager& CameraManager::instance() + { + FGL_ASSERT( camera_manager_instance, "CameraManager not initialized" ); + return *camera_manager_instance; + } + + std::shared_ptr< RenderCamera > CameraManager::createCamera( const vk::Extent2D extent ) + { + auto& instance = CameraManager::instance(); + + std::shared_ptr< RenderCamera > camera { + new RenderCamera( extent, instance.m_data_buffer, instance.m_renderer ) + }; + + instance.cameras.emplace_back( camera ); + + return camera; + } + + std::shared_ptr< CameraViewpoint > CameraManager::createViewpoint( const vk::Extent2D extent ) + { + auto& instance = CameraManager::instance(); + std::shared_ptr< CameraViewpoint > camera_viewpoint { new CameraViewpoint( instance.m_data_buffer, extent ) }; + + return camera_viewpoint; } } // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/camera/CameraManager.hpp b/src/engine/camera/CameraManager.hpp index 8bd8ec8..e863148 100644 --- a/src/engine/camera/CameraManager.hpp +++ b/src/engine/camera/CameraManager.hpp @@ -5,7 +5,7 @@ #pragma once #include -#include "Camera.hpp" +#include "RenderCamera.hpp" #include "engine/memory/buffers/BufferHandle.hpp" namespace fgl::engine @@ -20,20 +20,23 @@ namespace fgl::engine std::shared_ptr< GBufferRenderer > m_renderer; memory::Buffer m_data_buffer; - std::shared_ptr< Camera > m_primary_camera { nullptr }; + std::shared_ptr< RenderCamera > m_primary_camera { nullptr }; - std::vector< std::weak_ptr< Camera > > cameras {}; + std::vector< std::weak_ptr< RenderCamera > > cameras {}; public: CameraManager(); ~CameraManager(); - std::vector< std::weak_ptr< Camera > >& getCameras(); + std::vector< std::weak_ptr< RenderCamera > >& getCameras(); - std::shared_ptr< Camera >& getPrimary(); + std::shared_ptr< RenderCamera >& getPrimary(); + void createPrimary(); - std::shared_ptr< Camera > createCamera( vk::Extent2D extent ); + static CameraManager& instance(); + static std::shared_ptr< RenderCamera > createCamera( vk::Extent2D extent ); + static std::shared_ptr< CameraViewpoint > createViewpoint( vk::Extent2D extent ); }; } // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/camera/CameraViewpoint.cpp b/src/engine/camera/CameraViewpoint.cpp new file mode 100644 index 0000000..264319b --- /dev/null +++ b/src/engine/camera/CameraViewpoint.cpp @@ -0,0 +1,240 @@ +// +// Created by kj16609 on 9/23/25. +// +#include "CameraViewpoint.hpp" + +#include "CameraInfo.hpp" +#include "RenderCamera.hpp" +#include "assets/model/Model.hpp" + +namespace fgl::engine +{ + + void CameraViewpoint::updateMatrix() + { + const auto& [ pos, scale, rotation ] = m_transform; + + const auto rotation_matrix { rotation.forcedQuat().mat() }; + + const glm::vec3 forward { rotation_matrix * glm::vec4( constants::WORLD_FORWARD, 0.0f ) }; + + const glm::vec3 camera_up { rotation_matrix * glm::vec4( -constants::WORLD_Z, 0.0f ) }; + + const WorldCoordinate center_pos { pos + forward }; + + m_view_matrix = Matrix< MatrixType::WorldToCamera >( glm::lookAt( pos.vec(), center_pos.vec(), camera_up ) ); + + m_inverse_view_matrix = glm::inverse( m_view_matrix ); + + updateFrustum(); + } + + void CameraViewpoint::updateFrustum() + { + m_last_frustum_pos = getPosition(); + + const Matrix< MatrixType::ModelToWorld > translation_matrix { frustumTranslationMatrix() }; + + m_frustum = translation_matrix * m_base_frustum; + } + + constexpr descriptors::Descriptor camera_descriptor { 0, + vk::DescriptorType::eUniformBuffer, + vk::ShaderStageFlagBits::eAllGraphics }; + + inline static descriptors::DescriptorSetLayout camera_descriptor_set { 1, camera_descriptor }; + + memory::BufferSuballocation& CameraViewpoint::frameInfo( const FrameIndex i ) + { + return m_camera_frame_info[ i ]; + } + + std::vector< std::unique_ptr< descriptors::DescriptorSet > > CameraViewpoint::createCameraDescriptors() + { + std::vector< std::unique_ptr< descriptors::DescriptorSet > > sets {}; + sets.reserve( constants::MAX_FRAMES_IN_FLIGHT ); + + for ( std::uint8_t i = 0; i < constants::MAX_FRAMES_IN_FLIGHT; ++i ) + { + auto set { camera_descriptor_set.create() }; + set->bindUniformBuffer( 0, m_camera_frame_info[ i ] ); + set->update(); + set->setName( std::format( "Viewpoint {} descriptor set {}", m_viewpoint_idx, i ) ); + + sets.emplace_back( std::move( set ) ); + } + return sets; + } + + using namespace fgl::literals::size_literals; + + PerFrameArray< std::unique_ptr< descriptors::DescriptorSet > > createDrawCommandsDescriptors( + PerFrameArray< DeviceVector< vk::DrawIndexedIndirectCommand > >& gpu_draw_commands, + PerFrameArray< DeviceVector< InstanceRenderInfo > >& per_vertex_info ) + { + PerFrameArray< std::unique_ptr< descriptors::DescriptorSet > > descriptors {}; + + for ( std::uint16_t i = 0; i < gpu_draw_commands.size(); ++i ) + { + auto& command_buffer { gpu_draw_commands[ i ] }; + auto& per_vertex_buffer { per_vertex_info[ i ] }; + auto descriptor { COMMANDS_SET.create() }; + + descriptor->bindStorageBuffer( 0, command_buffer ); + descriptor->bindStorageBuffer( 1, per_vertex_buffer ); + descriptor->update(); + descriptor->setName( "Command Buffer + Vertex Buffer" ); + + descriptors[ i ] = std::move( descriptor ); + } + + return descriptors; + } + + CameraViewpoint::CameraViewpoint( memory::Buffer& buffer, const vk::Extent2D extent ) : + m_extent( extent ), + m_camera_frame_info( buffer ), + m_draw_parameter_pool( + 4_MiB, + vk::BufferUsageFlagBits::eIndirectBuffer | vk::BufferUsageFlagBits::eStorageBuffer, + vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible ), + m_gpu_draw_commands( + constructPerFrame< DeviceVector< vk::DrawIndexedIndirectCommand > >( m_draw_parameter_pool ) ), + m_generated_instance_info( + constructPerFrame< DeviceVector< InstanceRenderInfo > >( getModelBuffers().m_vertex_buffer ) ), + m_gpu_draw_cmds_desc( createDrawCommandsDescriptors( m_gpu_draw_commands, m_generated_instance_info ) ), + m_camera_info_descriptors( createCameraDescriptors() ) + { + setFOV( m_fov_y ); + } + + Coordinate< CoordinateSpace::World > CameraViewpoint::getPosition() const + { + //Should maybe store the inverse view matrix + return WorldCoordinate( m_inverse_view_matrix[ 3 ] ); + } + + Matrix< MatrixType::WorldToScreen > CameraViewpoint::getProjectionViewMatrix() const + { + assert( m_projection_matrix != constants::MAT4_IDENTITY ); + return m_projection_matrix * m_view_matrix; + } + + glm::mat4 CameraViewpoint::getInverseViewMatrix() const + { + return glm::inverse( m_view_matrix ); + } + + FGL_FLATTEN_HOT void CameraViewpoint:: + setView( const WorldCoordinate pos, const QuatRotation& rotation, const ViewMode mode ) + { + switch ( mode ) + { + case ViewMode::TaitBryan: + { + m_transform.translation = pos; + m_transform.rotation = rotation; + updateMatrix(); + break; + } + case ViewMode::Euler: + [[fallthrough]]; + { + //TODO: Implement + //view_matrix = glm::lookAt(position, position + ); + } + default: + throw std::runtime_error( "Unimplemented view mode" ); + } + + updateFrustum(); + } + + void CameraViewpoint::setOrthographicProjection( + const float left, const float right, const float top, const float bottom, const float near, const float far ) + { + m_projection_matrix = Matrix< MatrixType::CameraToScreen >( glm::ortho( left, right, bottom, top, near, far ) ); + } + + FGL_FLATTEN_HOT void CameraViewpoint:: + setPerspectiveProjection( const float fovy, const float aspect, const float near, const float far ) + { + m_projection_matrix = Matrix< MatrixType::CameraToScreen >( glm::perspective( fovy, aspect, near, far ) ); + + m_base_frustum = createFrustum( aspect, fovy, near, far ); + } + + void CameraViewpoint::setViewport( const vk::raii::CommandBuffer& command_buffer ) + { + vk::Viewport viewport {}; + viewport.x = 0.0f; + viewport.y = 0.0f; + + const auto& [ width, height ] = m_extent; + viewport.width = static_cast< float >( width ); + viewport.height = static_cast< float >( height ); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + const std::vector< vk::Viewport > viewports { viewport }; + + command_buffer.setViewport( 0, viewports ); + } + + void CameraViewpoint::setScissor( const vk::raii::CommandBuffer& command_buffer ) + { + const vk::Rect2D scissor { { 0, 0 }, m_extent }; + + const std::vector< vk::Rect2D > scissors { scissor }; + + command_buffer.setScissor( 0, scissors ); + } + + void CameraViewpoint::setFOV( const float fov_y ) + { + m_fov_y = fov_y; + setPerspectiveProjection( m_fov_y, aspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE ); + } + + float CameraViewpoint::aspectRatio() const + { + return static_cast< float >( m_extent.width ) / static_cast< float >( m_extent.height ); + } + + void CameraViewpoint::moveTo( const WorldTransform pos ) + { + this->m_transform = pos; + } + + void CameraViewpoint::updateInfo( const FrameIndex frame_index ) + { + ZoneScoped; + updateMatrix(); + CameraInfo current_camera_info { .projection = getProjectionMatrix(), + .view = getViewMatrix(), + .inverse_view = getInverseViewMatrix() }; + + m_camera_frame_info[ frame_index ] = current_camera_info; + } + + void CameraViewpoint::setExtent( const vk::Extent2D extent ) + { + m_extent = extent; + } + + vk::Rect2D CameraViewpoint::scissor() const + { + return { { 0, 0 }, m_extent }; + } + + vk::Viewport CameraViewpoint::viewport() const + { + return { 0, 0, this->m_extent.width, this->m_extent.height, 0.0f, 1.0f }; + } + + descriptors::DescriptorSetLayout& CameraViewpoint::getDescriptorLayout() + { + return camera_descriptor_set; + } + +} // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/camera/Camera.hpp b/src/engine/camera/CameraViewpoint.hpp similarity index 52% rename from src/engine/camera/Camera.hpp rename to src/engine/camera/CameraViewpoint.hpp index b223be6..38f0f7d 100644 --- a/src/engine/camera/Camera.hpp +++ b/src/engine/camera/CameraViewpoint.hpp @@ -1,82 +1,37 @@ // -// Created by kj16609 on 11/28/23. +// Created by kj16609 on 9/23/25. // - #pragma once +#include -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Weffc++" -#pragma GCC diagnostic ignored "-Wduplicated-branches" -#define GLM_ENABLE_EXPERIMENTAL -#include -#include -#pragma GCC diagnostic pop - -#include "../primitives/rotation/QuatRotation.hpp" -#include "CompositeSwapchain.hpp" -#include "GBufferSwapchain.hpp" -#include "debug/Track.hpp" -#include "engine/descriptors/DescriptorSet.hpp" -#include "engine/memory/buffers/HostSingleT.hpp" -#include "engine/memory/buffers/UniqueFrameSuballocation.hpp" -#include "engine/primitives/Frustum.hpp" -#include "engine/primitives/Transform.hpp" -#include "engine/rendering/types.hpp" - -namespace vk::raii -{ - class CommandBuffer; - class RenderPass; -} // namespace vk::raii +#include "CameraInfo.hpp" +#include "memory/buffers/HostSingleT.hpp" +#include "memory/buffers/UniqueFrameSuballocation.hpp" +#include "primitives/Frustum.hpp" +#include "primitives/Transform.hpp" +#include "primitives/matricies/Matrix.hpp" +#include "rendering/PresentSwapChain.hpp" namespace fgl::engine { + struct InstanceRenderInfo; + namespace descriptors { class DescriptorSetLayout; - } - class Image; - struct FrameInfo; - class GBufferRenderer; + class DescriptorSet; + } // namespace descriptors - struct CameraInfo; - class Camera; - - FrustumBase createFrustum( float aspect, float fovy, float near, float far ); - - using CameraIDX = std::uint8_t; - - class Camera + class CameraViewpoint { - inline static CameraIDX m_camera_counter { 0 }; - - debug::Track< "CPU", "Camera" > m_camera {}; - - vk::Extent2D m_target_extent; - - std::unique_ptr< CompositeSwapchain > m_composite_swapchain; - std::unique_ptr< GBufferSwapchain > m_gbuffer_swapchain; - - //TODO: Move to deffered deleter - std::queue< std::unique_ptr< CompositeSwapchain > > m_old_composite_swapchain {}; - std::queue< std::unique_ptr< GBufferSwapchain > > m_old_gbuffer_swapchain {}; - - std::shared_ptr< GBufferRenderer > m_camera_renderer; - - //! True if the camera is active and to be rendered - bool m_active { true }; - - //! If true, The camera's swapchain is to be destroyed in order to preserve memory. - //! This is here to allow us to set a camera cold when it's not likely to be used soon - bool m_cold { false }; - - // Const is acceptable, Since this value should never change. EVER - const CameraIDX m_camera_idx { m_camera_counter++ }; + protected: + vk::Extent2D m_extent; Matrix< MatrixType::CameraToScreen > m_projection_matrix { 1.0f }; Matrix< MatrixType::WorldToCamera > m_view_matrix { 1.0f }; glm::mat4 m_inverse_view_matrix { 1.0f }; + bool m_ortho { false }; //! Frustum of the camera in model space relative to the camera //! @note Must be transformed by the inverse view matrix to get the frustum in world space @@ -86,58 +41,62 @@ namespace fgl::engine WorldTransform m_transform {}; - float m_fov_y { glm::radians( 90.0f ) }; + float& x { m_transform.translation.x }; + float& y { m_transform.translation.y }; + float& z { m_transform.translation.z }; PerFrameSuballocation< HostSingleT< CameraInfo > > m_camera_frame_info; + std::uint32_t m_viewpoint_idx { 0 }; + + memory::Buffer m_draw_parameter_pool; + + public: + + PerFrameArray< DeviceVector< vk::DrawIndexedIndirectCommand > > m_gpu_draw_commands; + PerFrameArray< DeviceVector< InstanceRenderInfo > > m_generated_instance_info; + + PerFrameArray< std::unique_ptr< descriptors::DescriptorSet > > m_gpu_draw_cmds_desc; + + memory::BufferSuballocation& frameInfo( FrameIndex i ); // Camera info is expected at binding 0 std::vector< std::unique_ptr< descriptors::DescriptorSet > > createCameraDescriptors(); std::vector< std::unique_ptr< descriptors::DescriptorSet > > m_camera_info_descriptors; - std::string m_name { "Unnamed Camera" }; + private: - [[nodiscard]] Matrix< MatrixType::ModelToWorld > frustumTranslationMatrix() const; - - void updateFrustum(); - -#ifdef EXPOSE_CAMERA_TESTS - //Constructor for tests - Camera( vk::Extent2D test_extent ) : m_target_extent( test_extent ) {} -#endif - - Camera( vk::Extent2D extent, memory::Buffer& buffer, const std::shared_ptr< GBufferRenderer >& renderer ); - - friend class CameraManager; + enum ViewMode + { + Euler, + TaitBryan + }; public: - float& x { m_transform.translation.x }; - float& y { m_transform.translation.y }; - float& z { m_transform.translation.z }; + float m_fov_y { glm::radians( 90.0f ) }; - FGL_DELETE_ALL_RO5( Camera ); + FGL_DELETE_ALL_RO5( CameraViewpoint ); - ~Camera(); + explicit CameraViewpoint( memory::Buffer& buffer, vk::Extent2D extent = { 1920, 1080 } ); - [[nodiscard]] CameraIDX getIDX() const; + [[nodiscard]] Coordinate< CoordinateSpace::World > getPosition() const; - [[nodiscard]] const std::string& getName() const; - - void setExtent( vk::Extent2D extent ); + WorldTransform& getTransform() { return m_transform; } [[nodiscard]] QuatRotation getRotation() const { return m_transform.rotation.forcedQuat(); } [[nodiscard]] const WorldTransform& getTransform() const { return m_transform; } - WorldTransform& getTransform() { return m_transform; } - - WorldCoordinate getFrustumPosition() const; - [[nodiscard]] const FrustumBase& getBaseFrustum() const { return m_base_frustum; } //! Returns the frustum of the camera in world space [[nodiscard]] const Frustum& getFrustumBounds() const { return m_frustum; } + [[nodiscard]] WorldCoordinate getFrustumPosition() const; + + void updateMatrix(); + void updateFrustum(); + [[nodiscard]] const Matrix< MatrixType::CameraToScreen >& getProjectionMatrix() const { return m_projection_matrix; @@ -148,20 +107,13 @@ namespace fgl::engine [[nodiscard]] Matrix< MatrixType::WorldToScreen > getProjectionViewMatrix() const; [[nodiscard]] glm::mat4 getInverseViewMatrix() const; - - enum ViewMode - { - Euler, - TaitBryan - }; + [[nodiscard]] Matrix< MatrixType::ModelToWorld > frustumTranslationMatrix() const; void setView( WorldCoordinate pos, const QuatRotation& rotation, ViewMode mode = TaitBryan ); void setOrthographicProjection( float left, float right, float top, float bottom, float near, float far ); void setPerspectiveProjection( float fovy, float aspect, float near, float far ); - [[nodiscard]] Coordinate< CoordinateSpace::World > getPosition() const; - - FGL_FORCE_INLINE NormalVector getUp() const { return -getDown(); } + FGL_FORCE_INLINE NormalVector getLeft() const { return -getRight(); } FGL_FORCE_INLINE NormalVector getRight() const { @@ -173,45 +125,30 @@ namespace fgl::engine return -NormalVector( glm::vec3( m_inverse_view_matrix[ 2 ] ) ); } - FGL_FORCE_INLINE NormalVector getLeft() const { return -getRight(); } - FGL_FORCE_INLINE NormalVector getBackward() const { return -getForward(); } + FGL_FORCE_INLINE NormalVector getUp() const { return -getDown(); } + FGL_FORCE_INLINE NormalVector getDown() const { return NormalVector( glm::vec3( m_inverse_view_matrix[ 1 ] ) ); } - //! Updates the required info for rendering - void updateInfo( FrameIndex frame_index ); - descriptors::DescriptorSet& getDescriptor( FrameIndex index ); - - void setFOV( float fov_y ); - - //! Performs the render pass for this camera - void pass( FrameInfo& frame_info ); - - [[nodiscard]] GBufferSwapchain& getSwapchain() const; - [[nodiscard]] CompositeSwapchain& getCompositeSwapchain() const; void setViewport( const vk::raii::CommandBuffer& command_buffer ); void setScissor( const vk::raii::CommandBuffer& command_buffer ); + void setFOV( float fov_y ); + [[nodiscard]] float aspectRatio() const; - void remakeSwapchain( vk::Extent2D extent ); + void moveTo( const WorldTransform pos ); - void setName( std::string_view str ); + //! Updates the required info for rendering + void updateInfo( FrameIndex frame_index ); - float aspectRatio() const; + void setExtent( vk::Extent2D extent ); - void copyOutput( const vk::raii::CommandBuffer& command_buffer, FrameIndex frame_index, Image& target ); - void updateMatrix(); + vk::Rect2D scissor() const; + vk::Viewport viewport() const; static descriptors::DescriptorSetLayout& getDescriptorLayout(); - -#ifdef EXPOSE_CAMERA_TESTS - - Camera CREATE_TESTING_CAMERA() { return { { 1920, 1080 } }; } - -#endif }; - -} // namespace fgl::engine +} // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/camera/GBufferCompositor.cpp b/src/engine/camera/GBufferCompositor.cpp index 1005621..bfa56ff 100644 --- a/src/engine/camera/GBufferCompositor.cpp +++ b/src/engine/camera/GBufferCompositor.cpp @@ -3,9 +3,10 @@ // #include "GBufferCompositor.hpp" -#include "Camera.hpp" #include "CompositeSwapchain.hpp" #include "GBufferSwapchain.hpp" +#include "RenderCamera.hpp" +#include "ShadowMap.hpp" #include "engine/rendering/pipelines/v2/AttachmentBuilder.hpp" namespace fgl::engine @@ -56,7 +57,8 @@ namespace fgl::engine PipelineBuilder builder { 0 }; builder.addDescriptorSet( gbuffer_set ); - builder.addDescriptorSet( Camera::getDescriptorLayout() ); + builder.addDescriptorSet( RenderCamera::getDescriptorLayout() ); + builder.addDescriptorSet( ShadowMap::getDescriptorLayout() ); builder.addColorAttachment().setFormat( pickColorFormat() ).finish(); @@ -73,7 +75,8 @@ namespace fgl::engine m_pipeline->setDebugName( "Composition pipeline" ); } - void GBufferCompositor::composite( CommandBuffer& command_buffer, Camera& camera, const FrameIndex frame_index ) + void GBufferCompositor:: + composite( CommandBuffer& command_buffer, RenderCamera& camera, const FrameIndex frame_index ) { auto& gbuffer_swapchain { camera.getSwapchain() }; auto& composite_swapchain { camera.getCompositeSwapchain() }; diff --git a/src/engine/camera/GBufferCompositor.hpp b/src/engine/camera/GBufferCompositor.hpp index 6b08027..94670c7 100644 --- a/src/engine/camera/GBufferCompositor.hpp +++ b/src/engine/camera/GBufferCompositor.hpp @@ -5,7 +5,7 @@ #include -#include "Camera.hpp" +#include "RenderCamera.hpp" #include "engine/rendering/pipelines/v2/Pipeline.hpp" #include "engine/rendering/types.hpp" #include "engine/systems/composition/Control.hpp" @@ -48,7 +48,7 @@ namespace fgl::engine GBufferCompositor( CompositeFlags flags = CompositeFlagBits_Standard ); - void composite( CommandBuffer& command_buffer, Camera& camera, FrameIndex frame_index ); + void composite( CommandBuffer& command_buffer, RenderCamera& camera, FrameIndex frame_index ); inline void switchMode( const CompositeFlags flags ) { m_flags = flags; } }; diff --git a/src/engine/camera/GBufferRenderer.cpp b/src/engine/camera/GBufferRenderer.cpp index 446b67d..b4ca39b 100644 --- a/src/engine/camera/GBufferRenderer.cpp +++ b/src/engine/camera/GBufferRenderer.cpp @@ -73,7 +73,8 @@ namespace fgl::engine camera_swapchain.transitionImages( command_buffer, GBufferSwapchain::FINAL, frame_info.in_flight_idx ); - m_compositor.composite( command_buffer, *frame_info.camera, frame_info.in_flight_idx ); + m_compositor + .composite( command_buffer, *static_cast< RenderCamera* >( frame_info.camera ), frame_info.in_flight_idx ); } } // namespace fgl::engine diff --git a/src/engine/camera/Camera.cpp b/src/engine/camera/RenderCamera.cpp similarity index 61% rename from src/engine/camera/Camera.cpp rename to src/engine/camera/RenderCamera.cpp index 2b70c82..31b33c8 100644 --- a/src/engine/camera/Camera.cpp +++ b/src/engine/camera/RenderCamera.cpp @@ -2,13 +2,12 @@ // Created by kj16609 on 11/28/23. // -#include "Camera.hpp" +#include "RenderCamera.hpp" #define GLM_ENABLE_EXPERIMENTAL #include #include -#include "CameraInfo.hpp" #include "GBufferRenderer.hpp" #include "GBufferSwapchain.hpp" #include "engine/debug/timing/FlameGraph.hpp" @@ -16,61 +15,67 @@ namespace fgl::engine { - Matrix< MatrixType::WorldToScreen > Camera::getProjectionViewMatrix() const + FrustumBase createFrustum( const float aspect, const float fov_y, const float near, const float far ) { - assert( m_projection_matrix != constants::MAT4_IDENTITY ); - return m_projection_matrix * m_view_matrix; + const Plane< CoordinateSpace::Model > near_plane { ModelCoordinate( constants::WORLD_FORWARD * near ), + NormalVector( constants::WORLD_FORWARD ) }; + const Plane< CoordinateSpace::Model > far_plane { ModelCoordinate( constants::WORLD_FORWARD * far ), + NormalVector( -constants::WORLD_FORWARD ) }; + + const float half_height { far * glm::tan( fov_y / 2.0f ) }; + const float half_width { half_height * aspect }; + + const ModelCoordinate far_forward { constants::WORLD_FORWARD * far }; + const ModelCoordinate right_half { constants::WORLD_RIGHT * half_width }; + + const Vector right_forward { ( far_forward + right_half ).vec() }; + const Vector left_forward { ( far_forward - right_half ).vec() }; + + const Plane< CoordinateSpace::Model > right_plane { + ModelCoordinate( constants::WORLD_CENTER ), + NormalVector( glm::cross( right_forward.vec(), constants::WORLD_Z_NEG ) ) + }; + const Plane< CoordinateSpace::Model > left_plane { + ModelCoordinate( constants::WORLD_CENTER ), + NormalVector( glm::cross( left_forward.vec(), constants::WORLD_Z ) ) + }; + + const ModelCoordinate top_half { constants::WORLD_Z * half_height }; + + const Vector top_forward { ( far_forward + top_half ).vec() }; + const Vector bottom_forward { ( far_forward - top_half ).vec() }; + + const Plane< CoordinateSpace::Model > top_plane { + ModelCoordinate( constants::WORLD_CENTER ), + NormalVector( glm::cross( top_forward.vec(), constants::WORLD_RIGHT ) ) + }; + + const Plane< CoordinateSpace::Model > bottom_plane { + ModelCoordinate( constants::WORLD_CENTER ), + NormalVector( glm::cross( bottom_forward.vec(), -constants::WORLD_RIGHT ) ) + }; + + return { near_plane, + far_plane, + top_plane, + bottom_plane, + right_plane, + left_plane, + Coordinate< CoordinateSpace::Model >( constants::WORLD_CENTER ) }; } - glm::mat4 Camera::getInverseViewMatrix() const + const std::string& RenderCamera::getName() const { - return glm::inverse( m_view_matrix ); + return m_name; } - void Camera::setOrthographicProjection( float left, float right, float top, float bottom, float near, float far ) - { - m_projection_matrix = Matrix< MatrixType::CameraToScreen >( glm::ortho( left, right, bottom, top, near, far ) ); - - //TODO: Figure out frustum culling for orthographic projection. (If we even wanna use it) - } - - FGL_FLATTEN_HOT void Camera:: - setPerspectiveProjection( const float fovy, const float aspect, const float near, const float far ) - { - m_projection_matrix = Matrix< MatrixType::CameraToScreen >( glm::perspective( fovy, aspect, near, far ) ); - - m_base_frustum = createFrustum( aspect, fovy, near, far ); - } - - Coordinate< CoordinateSpace::World > Camera::getPosition() const - { - //Should maybe store the inverse view matrix - return WorldCoordinate( m_inverse_view_matrix[ 3 ] ); - } - - void Camera::updateInfo( const FrameIndex frame_index ) - { - ZoneScoped; - CameraInfo current_camera_info { .projection = getProjectionMatrix(), - .view = getViewMatrix(), - .inverse_view = getInverseViewMatrix() }; - - m_camera_frame_info[ frame_index ] = current_camera_info; - } - - descriptors::DescriptorSet& Camera::getDescriptor( const FrameIndex index ) + descriptors::DescriptorSet& RenderCamera::getDescriptor( const FrameIndex index ) { assert( index < m_camera_info_descriptors.size() ); return *m_camera_info_descriptors[ index ]; } - void Camera::setFOV( const float fov_y ) - { - m_fov_y = fov_y; - setPerspectiveProjection( m_fov_y, aspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE ); - } - - void Camera::pass( FrameInfo& frame_info ) + void RenderCamera::pass( FrameInfo& frame_info ) { ZoneScopedN( "Camera::pass" ); auto timer = debug::timing::push( "Camera" ); @@ -98,45 +103,20 @@ namespace fgl::engine frame_info.camera = nullptr; } - GBufferSwapchain& Camera::getSwapchain() const + GBufferSwapchain& RenderCamera::getSwapchain() const { return *m_gbuffer_swapchain; } - CompositeSwapchain& Camera::getCompositeSwapchain() const + CompositeSwapchain& RenderCamera::getCompositeSwapchain() const { return *m_composite_swapchain; } - void Camera::setViewport( const vk::raii::CommandBuffer& command_buffer ) + void RenderCamera::remakeSwapchain( vk::Extent2D extent ) { - vk::Viewport viewport {}; - viewport.x = 0.0f; - viewport.y = 0.0f; - - const auto& [ width, height ] = m_gbuffer_swapchain->getExtent(); - viewport.width = static_cast< float >( width ); - viewport.height = static_cast< float >( height ); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - const std::vector< vk::Viewport > viewports { viewport }; - - command_buffer.setViewport( 0, viewports ); - } - - void Camera::setScissor( const vk::raii::CommandBuffer& command_buffer ) - { - const vk::Rect2D scissor { { 0, 0 }, m_gbuffer_swapchain->getExtent() }; - - const std::vector< vk::Rect2D > scissors { scissor }; - - command_buffer.setScissor( 0, scissors ); - } - - void Camera::remakeSwapchain( vk::Extent2D extent ) - { - this->setPerspectiveProjection( m_fov_y, aspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE ); + setExtent( extent ); + this->setPerspectiveProjection( m_fov_y, this->aspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE ); log::debug( "Camera swapchain recreated" ); @@ -148,20 +128,22 @@ namespace fgl::engine m_composite_swapchain = std::make_unique< CompositeSwapchain >( extent ); m_gbuffer_swapchain = std::make_unique< GBufferSwapchain >( extent ); + + CameraViewpoint::setExtent( extent ); } - void Camera::setName( const std::string_view str ) + void RenderCamera::setName( const std::string_view str ) { m_name = str; } - float Camera::aspectRatio() const + float RenderCamera::aspectRatio() const { return m_gbuffer_swapchain->getAspectRatio(); } - void Camera:: - copyOutput( const vk::raii::CommandBuffer& command_buffer, const FrameIndex frame_index, Image& target ) + void RenderCamera:: + copyOutput( const vk::raii::CommandBuffer& command_buffer, const FrameIndex frame_index, Image& target ) const { assert( m_gbuffer_swapchain->getExtent() == target.getExtent() ); @@ -271,175 +253,39 @@ namespace fgl::engine { barrier_to_source } ); } - void Camera::updateMatrix() + WorldCoordinate CameraViewpoint::getFrustumPosition() const { - const auto& [ pos, scale, rotation ] = m_transform; - - const auto rotation_matrix { rotation.forcedQuat().mat() }; - - const glm::vec3 forward { rotation_matrix * glm::vec4( constants::WORLD_FORWARD, 0.0f ) }; - - const glm::vec3 camera_up { rotation_matrix * glm::vec4( -constants::WORLD_Z, 0.0f ) }; - - const WorldCoordinate center_pos { pos + forward }; - - m_view_matrix = Matrix< MatrixType::WorldToCamera >( glm::lookAt( pos.vec(), center_pos.vec(), camera_up ) ); - - m_inverse_view_matrix = glm::inverse( m_view_matrix ); - - updateFrustum(); + return m_last_frustum_pos; } - FGL_FLATTEN_HOT void Camera::setView( const WorldCoordinate pos, const QuatRotation& rotation, const ViewMode mode ) + Matrix< MatrixType::ModelToWorld > CameraViewpoint::frustumTranslationMatrix() const { - switch ( mode ) - { - case ViewMode::TaitBryan: - { - m_transform.translation = pos; - m_transform.rotation = rotation; - updateMatrix(); - break; - } - case ViewMode::Euler: - [[fallthrough]]; - { - //TODO: Implement - //view_matrix = glm::lookAt(position, position + ); - } - default: - throw std::runtime_error( "Unimplemented view mode" ); - } - - updateFrustum(); + return m_transform.mat(); } - void Camera::updateFrustum() - { - m_last_frustum_pos = getPosition(); - - const Matrix< MatrixType::ModelToWorld > translation_matrix { frustumTranslationMatrix() }; - - m_frustum = translation_matrix * m_base_frustum; - } - - const std::string& Camera::getName() const - { - return m_name; - } - - constexpr descriptors::Descriptor camera_descriptor { 0, - vk::DescriptorType::eUniformBuffer, - vk::ShaderStageFlagBits::eAllGraphics }; - - inline static descriptors::DescriptorSetLayout camera_descriptor_set { 1, camera_descriptor }; - - descriptors::DescriptorSetLayout& Camera::getDescriptorLayout() - { - return camera_descriptor_set; - } - - Camera::Camera( + RenderCamera::RenderCamera( const vk::Extent2D extent, memory::Buffer& buffer, const std::shared_ptr< GBufferRenderer >& renderer ) : + CameraViewpoint( buffer, extent ), m_target_extent( extent ), m_composite_swapchain( std::make_unique< CompositeSwapchain >( m_target_extent ) ), m_gbuffer_swapchain( std::make_unique< GBufferSwapchain >( m_target_extent ) ), - m_camera_renderer( renderer ), - m_camera_frame_info( buffer ), - m_camera_info_descriptors( createCameraDescriptors() ) + m_camera_renderer( renderer ) { FGL_ASSERT( renderer, "Camera renderer is null" ); this->setPerspectiveProjection( m_fov_y, aspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE ); this->setView( WorldCoordinate( constants::CENTER ), QuatRotation( 0.0f, 0.0f, 0.0f ) ); } - std::vector< std::unique_ptr< descriptors::DescriptorSet > > Camera::createCameraDescriptors() - { - std::vector< std::unique_ptr< descriptors::DescriptorSet > > sets {}; - sets.reserve( constants::MAX_FRAMES_IN_FLIGHT ); + RenderCamera::~RenderCamera() = default; - for ( std::uint8_t i = 0; i < constants::MAX_FRAMES_IN_FLIGHT; ++i ) - { - auto set { camera_descriptor_set.create() }; - set->bindUniformBuffer( 0, m_camera_frame_info[ i ] ); - set->update(); - set->setName( std::format( "Camera {} descriptor set {}", m_camera_idx, i ) ); - - sets.emplace_back( std::move( set ) ); - } - return sets; - } - - void Camera::setExtent( const vk::Extent2D extent ) - { - m_target_extent = extent; - } - - FrustumBase createFrustum( const float aspect, const float fov_y, const float near, const float far ) - { - const Plane< CoordinateSpace::Model > near_plane { ModelCoordinate( constants::WORLD_FORWARD * near ), - NormalVector( constants::WORLD_FORWARD ) }; - const Plane< CoordinateSpace::Model > far_plane { ModelCoordinate( constants::WORLD_FORWARD * far ), - NormalVector( -constants::WORLD_FORWARD ) }; - - const float half_height { far * glm::tan( fov_y / 2.0f ) }; - const float half_width { half_height * aspect }; - - const ModelCoordinate far_forward { constants::WORLD_FORWARD * far }; - const ModelCoordinate right_half { constants::WORLD_RIGHT * half_width }; - - const Vector right_forward { ( far_forward + right_half ).vec() }; - const Vector left_forward { ( far_forward - right_half ).vec() }; - - const Plane< CoordinateSpace::Model > right_plane { - ModelCoordinate( constants::WORLD_CENTER ), - NormalVector( glm::cross( right_forward.vec(), constants::WORLD_Z_NEG ) ) - }; - const Plane< CoordinateSpace::Model > left_plane { - ModelCoordinate( constants::WORLD_CENTER ), - NormalVector( glm::cross( left_forward.vec(), constants::WORLD_Z ) ) - }; - - const ModelCoordinate top_half { constants::WORLD_Z * half_height }; - - const Vector top_forward { ( far_forward + top_half ).vec() }; - const Vector bottom_forward { ( far_forward - top_half ).vec() }; - - const Plane< CoordinateSpace::Model > top_plane { - ModelCoordinate( constants::WORLD_CENTER ), - NormalVector( glm::cross( top_forward.vec(), constants::WORLD_RIGHT ) ) - }; - - const Plane< CoordinateSpace::Model > bottom_plane { - ModelCoordinate( constants::WORLD_CENTER ), - NormalVector( glm::cross( bottom_forward.vec(), -constants::WORLD_RIGHT ) ) - }; - - return { near_plane, - far_plane, - top_plane, - bottom_plane, - right_plane, - left_plane, - Coordinate< CoordinateSpace::Model >( constants::WORLD_CENTER ) }; - } - - Matrix< MatrixType::ModelToWorld > Camera::frustumTranslationMatrix() const - { - return m_transform.mat(); - } - - WorldCoordinate Camera::getFrustumPosition() const - { - return m_last_frustum_pos; - } - - Camera::~Camera() - {} - - CameraIDX Camera::getIDX() const + CameraIDX RenderCamera::getIDX() const { return m_camera_idx; } + void RenderCamera::setExtent( const vk::Extent2D extent ) + { + m_target_extent = extent; + } + } // namespace fgl::engine diff --git a/src/engine/camera/RenderCamera.hpp b/src/engine/camera/RenderCamera.hpp new file mode 100644 index 0000000..c062291 --- /dev/null +++ b/src/engine/camera/RenderCamera.hpp @@ -0,0 +1,110 @@ +// +// Created by kj16609 on 11/28/23. +// + +#pragma once + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Weffc++" +#pragma GCC diagnostic ignored "-Wduplicated-branches" +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#pragma GCC diagnostic pop + +#include "CameraViewpoint.hpp" +#include "CompositeSwapchain.hpp" +#include "GBufferSwapchain.hpp" +#include "debug/Track.hpp" +#include "engine/descriptors/DescriptorSet.hpp" +#include "engine/memory/buffers/HostSingleT.hpp" +#include "engine/memory/buffers/UniqueFrameSuballocation.hpp" +#include "engine/primitives/Frustum.hpp" +#include "engine/rendering/types.hpp" + +namespace vk::raii +{ + class CommandBuffer; + class RenderPass; +} // namespace vk::raii + +namespace fgl::engine +{ + namespace descriptors + { + class DescriptorSetLayout; + } + class Image; + struct FrameInfo; + class GBufferRenderer; + + struct CameraInfo; + class RenderCamera; + + FrustumBase createFrustum( float aspect, float fovy, float near, float far ); + + using CameraIDX = std::uint8_t; + + class RenderCamera final : public CameraViewpoint + { + inline static CameraIDX m_camera_counter { 0 }; + + debug::Track< "CPU", "Camera" > m_camera {}; + + vk::Extent2D m_target_extent; + + std::unique_ptr< CompositeSwapchain > m_composite_swapchain; + std::unique_ptr< GBufferSwapchain > m_gbuffer_swapchain; + + //TODO: Move to deffered deleter + std::queue< std::unique_ptr< CompositeSwapchain > > m_old_composite_swapchain {}; + std::queue< std::unique_ptr< GBufferSwapchain > > m_old_gbuffer_swapchain {}; + + std::shared_ptr< GBufferRenderer > m_camera_renderer; + + //! True if the camera is active and to be rendered + bool m_active { true }; + + //! If true, The camera's swapchain is to be destroyed to preserve memory. + //! This is here to allow us to set a camera cold when it's not likely to be used soon + bool m_cold { false }; + + // Const is acceptable, Since this value should never change. EVER + const CameraIDX m_camera_idx { m_camera_counter++ }; + + std::string m_name { "Unnamed Camera" }; + + RenderCamera( vk::Extent2D extent, memory::Buffer& buffer, const std::shared_ptr< GBufferRenderer >& renderer ); + + friend class CameraManager; + + public: + + FGL_DELETE_ALL_RO5( RenderCamera ); + + ~RenderCamera(); + + [[nodiscard]] CameraIDX getIDX() const; + + [[nodiscard]] const std::string& getName() const; + + descriptors::DescriptorSet& getDescriptor( FrameIndex index ); + + void setExtent( vk::Extent2D extent ); + + //! Performs the render pass for this camera + void pass( FrameInfo& frame_info ); + + [[nodiscard]] GBufferSwapchain& getSwapchain() const; + [[nodiscard]] CompositeSwapchain& getCompositeSwapchain() const; + + void remakeSwapchain( vk::Extent2D extent ); + + void setName( std::string_view str ); + + [[nodiscard]] float aspectRatio() const; + + void copyOutput( const vk::raii::CommandBuffer& command_buffer, FrameIndex frame_index, Image& target ) const; + }; + +} // namespace fgl::engine diff --git a/src/engine/camera/ShadowMap.cpp b/src/engine/camera/ShadowMap.cpp new file mode 100644 index 0000000..8fdbcc5 --- /dev/null +++ b/src/engine/camera/ShadowMap.cpp @@ -0,0 +1,167 @@ +// +// Created by kj16609 on 9/23/25. +// +#include "ShadowMap.hpp" + +#include "CameraManager.hpp" +#include "assets/model/Model.hpp" +#include "assets/model/ModelVertex.hpp" +#include "debug/timing/FlameGraph.hpp" +#include "rendering/pipelines/v2/Pipeline.hpp" +#include "rendering/pipelines/v2/PipelineBuilder.hpp" + +namespace fgl::engine +{ + + std::shared_ptr< Swapchain > createDepthSwapchain( const vk::Extent2D extent ) + { + std::vector< SwapchainImageInfo > swapchain_images { + { .m_format = { .m_canidates = { vk::Format::eD32Sfloat, + vk::Format::eD32SfloatS8Uint, + vk::Format::eD24UnormS8Uint }, + .m_usage = + vk::ImageUsageFlagBits::eDepthStencilAttachment | vk::ImageUsageFlagBits::eSampled, + .m_features = vk::FormatFeatureFlagBits::eDepthStencilAttachment }, + .m_inital_layout = vk::ImageLayout::eUndefined, + .m_final_layout = vk::ImageLayout::eDepthReadOnlyOptimal, + .m_extent = extent, + .m_name = "Shadowmap Depth" } + }; + + return std::make_shared< Swapchain >( std::move( swapchain_images ) ); + } + + constexpr descriptors::Descriptor camera_descriptor { 0, + vk::DescriptorType::eUniformBuffer, + vk::ShaderStageFlagBits::eAllGraphics }; + + // 2d sampler + constexpr descriptors::Descriptor shadowmap_descriptor { 1, + vk::DescriptorType::eSampledImage, + vk::ShaderStageFlagBits::eFragment }; + + inline static descriptors::DescriptorSetLayout shadowmap_descriptor_set { 2, + camera_descriptor, + shadowmap_descriptor }; + + PerFrameArray< std::unique_ptr< descriptors::DescriptorSet > > ShadowMap::createShadowmapDescriptors() const + { + PerFrameArray< std::unique_ptr< descriptors::DescriptorSet > > data {}; + + for ( std::size_t i = 0; i < data.size(); ++i ) + { + auto set { shadowmap_descriptor_set.create() }; + + set->bindImage( + shadowmap_descriptor.m_index, + *this->m_swapchain->depthView( i ), + vk::ImageLayout::eDepthReadOnlyOptimal ); + set->bindUniformBuffer( camera_descriptor.m_index, this->m_camera->frameInfo( i ) ); + + set->update(); + + data[ i ] = std::move( set ); + } + + return data; + } + + ShadowMap::ShadowMap( const UniversalRotation& direction, const vk::Extent2D extent ) : + m_swapchain( createDepthSwapchain( extent ) ), + m_direction( direction ), + m_camera( CameraManager::createViewpoint( extent ) ), + m_extent( extent ), + m_shadowmap_descriptor( createShadowmapDescriptors() ) + { + PipelineBuilder builder { 0 }; + + builder.addDepthAttachment(); + + builder.addDescriptorSet( CameraViewpoint::getDescriptorLayout() ); + builder.setVertexShader( Shader::loadVertex( "shaders/shadowmap.slang" ) ); + builder.setFragmentShader( Shader::loadFragment( "shaders/shadowmap.slang" ) ); + + builder.setAttributeDescriptions( ModelVertex::getAttributeDescriptions() ); + builder.setBindingDescriptions( ModelVertex::getBindingDescriptions() ); + + m_shadow_pipeline = builder.create(); + m_shadow_pipeline->setDebugName( "Shadow pipeline" ); + } + + void ShadowMap::pass( FrameInfo info ) + { + ZoneScopedN( "ShadowMap::pass" ); + auto timer = debug::timing::push( "ShadowMap" ); + + info.camera = m_camera.get(); + + info.camera->updateInfo( info.in_flight_idx ); + + m_culling_system.pass( info ); + + auto& command_buffer { info.command_buffer.render_cb }; + + vk::RenderingInfo rendering_info {}; + vk::RenderingAttachmentInfo depth_info {}; + depth_info.setClearValue( vk::ClearDepthStencilValue( 1.0f, 0 ) ); + depth_info.setLoadOp( vk::AttachmentLoadOp::eClear ); + depth_info.setStoreOp( vk::AttachmentStoreOp::eStore ); + depth_info.imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal; + depth_info.imageView = m_swapchain->depthView( info.in_flight_idx )->getVkView(); + rendering_info.colorAttachmentCount = 0; + rendering_info.pColorAttachments = nullptr; + rendering_info.setRenderArea( { { 0, 0 }, this->m_extent } ); + rendering_info.layerCount = 1; + + rendering_info.setPDepthAttachment( &depth_info ); + + command_buffer->beginRendering( rendering_info ); + + command_buffer->setViewport( 0, { info.camera->viewport() } ); + command_buffer->setScissor( 0, { info.camera->scissor() } ); + + m_shadow_pipeline->bind( command_buffer ); + + m_shadow_pipeline->bindDescriptor( command_buffer, info.getCameraDescriptor() ); + + auto& model_buffers { getModelBuffers() }; + + const std::vector< vk::Buffer > vert_buffers { + model_buffers.m_vertex_buffer->getVkBuffer(), + info.camera->m_generated_instance_info[ info.in_flight_idx ].getVkBuffer(), + }; + + command_buffer->bindVertexBuffers( + 0, vert_buffers, { 0, info.camera->m_generated_instance_info[ info.in_flight_idx ].getOffset() } ); + command_buffer->bindIndexBuffer( model_buffers.m_index_buffer->getVkBuffer(), 0, vk::IndexType::eUint32 ); + + const auto& commands { info.camera->m_gpu_draw_commands[ info.in_flight_idx ] }; + + command_buffer + ->drawIndexedIndirect( commands.getVkBuffer(), commands.getOffset(), commands.size(), commands.stride() ); + + command_buffer->endRendering(); + } + + static std::vector< std::weak_ptr< ShadowMap > > shadowmaps {}; + + descriptors::DescriptorSetLayout& ShadowMap::getDescriptorLayout() + { + return shadowmap_descriptor_set; + } + + std::shared_ptr< ShadowMap > createShadowmap( UniversalRotation direction ) + { + constexpr int size { 1024 }; + auto ptr { std::make_shared< ShadowMap >( direction, vk::Extent2D { size, size } ) }; + + shadowmaps.emplace_back( ptr ); + + return ptr; + } + + std::vector< std::weak_ptr< ShadowMap > > getShadowmaps() + { + return shadowmaps; + } +} // namespace fgl::engine diff --git a/src/engine/camera/ShadowMap.hpp b/src/engine/camera/ShadowMap.hpp new file mode 100644 index 0000000..f053881 --- /dev/null +++ b/src/engine/camera/ShadowMap.hpp @@ -0,0 +1,55 @@ +// +// Created by kj16609 on 9/23/25. +// +#pragma once + +#include + +#include + +#include "RenderCamera.hpp" +#include "Swapchain.hpp" +#include "primitives/rotation/UniversalRotation.hpp" +#include "systems/prerender/CullingSystem.hpp" + +namespace fgl::engine +{ + namespace gui + { + void drawShadowmaps( const FrameInfo& info ); + } + + struct CameraInfo; + + class ShadowMap + { + std::shared_ptr< Swapchain > m_swapchain; + UniversalRotation m_direction; + + std::shared_ptr< CameraViewpoint > m_camera; + + std::unique_ptr< Pipeline > m_shadow_pipeline; + + CullingSystem m_culling_system; + vk::Extent2D m_extent; + + PerFrameArray< std::unique_ptr< descriptors::DescriptorSet > > createShadowmapDescriptors() const; + PerFrameArray< std::unique_ptr< descriptors::DescriptorSet > > m_shadowmap_descriptor; + + public: + + ShadowMap() = delete; + + ShadowMap( const UniversalRotation& direction, vk::Extent2D extent ); + + void pass( FrameInfo info ); + + friend void gui::drawShadowmaps( const FrameInfo& info ); + static descriptors::DescriptorSetLayout& getDescriptorLayout(); + }; + + std::shared_ptr< ShadowMap > createShadowmap( UniversalRotation direction ); + + std::vector< std::weak_ptr< ShadowMap > > getShadowmaps(); + +} // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/camera/Swapchain.cpp b/src/engine/camera/Swapchain.cpp new file mode 100644 index 0000000..2cb8779 --- /dev/null +++ b/src/engine/camera/Swapchain.cpp @@ -0,0 +1,80 @@ +// +// Created by kj16609 on 9/23/25. +// +#include "Swapchain.hpp" + +#include "assets/image/Image.hpp" +#include "assets/image/ImageView.hpp" +#include "assets/texture/Texture.hpp" +#include "constants.hpp" +#include "rendering/devices/Device.hpp" +#include "slang.h" + +namespace fgl::engine +{ + + vk::Format SwapchainImageInfo::pickBestFormat() const + { + return Device::getInstance() + .findSupportedFormat( m_format.m_canidates, vk::ImageTiling::eOptimal, m_format.m_features ); + } + + SwapchainImageSet::SwapchainImageSet( const SwapchainImageInfo& info ) + { + for ( int i = 0; i < constants::MAX_FRAMES_IN_FLIGHT; ++i ) + { + auto image_itter { m_image.emplace_back( + std::make_shared< Image >( + info.m_extent, + info.pickBestFormat(), + info.m_format.m_usage, + info.m_inital_layout, + info.m_final_layout ) ) }; + auto view_itter { m_view.emplace_back( image_itter->getView() ) }; + + image_itter->setName( std::format( "Swapchain image {}:{}", info.m_name, i ) ); + } + } + + std::shared_ptr< Texture > SwapchainImageSet::getTexture( const FrameIndex frame_index ) const + { + if ( m_texture.empty() ) m_texture.resize( constants::MAX_FRAMES_IN_FLIGHT ); + + if ( !m_texture[ frame_index ] ) + { + Sampler default_sampler {}; + m_texture[ frame_index ] = + std::make_shared< Texture >( m_image[ frame_index ], std::move( default_sampler ) ); + } + + return m_texture[ frame_index ]; + } + + std::shared_ptr< ImageView > Swapchain::depthView( const FrameIndex frame_index ) const + { + const SwapchainImageSet& set { m_depth.value() }; + + return set.m_view[ frame_index ]; + } + + std::shared_ptr< Image > Swapchain::depthImage( const FrameIndex frame_index ) const + { + return m_depth.value().m_image[ frame_index ]; + } + + std::shared_ptr< Texture > Swapchain::depthTexture( const FrameIndex frame_index ) const + { + return m_depth.value().getTexture( frame_index ); + } + + Swapchain::Swapchain( const std::vector< SwapchainImageInfo >& in ) + { + for ( const SwapchainImageInfo& info : in ) + { + if ( info.m_format.m_usage & vk::ImageUsageFlagBits::eDepthStencilAttachment ) + m_depth.emplace( info ); + else + m_swapchain_images.emplace_back( info ); + } + } +} // namespace fgl::engine diff --git a/src/engine/camera/Swapchain.hpp b/src/engine/camera/Swapchain.hpp new file mode 100644 index 0000000..7dbfe0a --- /dev/null +++ b/src/engine/camera/Swapchain.hpp @@ -0,0 +1,69 @@ +// +// Created by kj16609 on 9/23/25. +// +#pragma once +#include + +#include +#include +#include + +#include "FGL_DEFINES.hpp" +#include "assets/texture/Texture.hpp" +#include "rendering/types.hpp" + +namespace fgl::engine +{ + class Image; + class ImageView; + + struct SwapchainImageInfo + { + struct + { + std::vector< vk::Format > m_canidates; + vk::ImageUsageFlags m_usage; + vk::FormatFeatureFlags m_features; + } m_format; + + vk::ImageLayout m_inital_layout; + vk::ImageLayout m_final_layout; + + vk::Extent2D m_extent; + std::string m_name; + + [[nodiscard]] vk::Format pickBestFormat() const; + }; + + class SwapchainImageSet + { + std::vector< std::shared_ptr< Image > > m_image {}; + std::vector< std::shared_ptr< ImageView > > m_view {}; + mutable std::vector< std::shared_ptr< Texture > > m_texture {}; + + friend class Swapchain; + + public: + + SwapchainImageSet() = delete; + + [[nodiscard]] SwapchainImageSet( const SwapchainImageInfo& info ); + std::shared_ptr< Texture > getTexture( FrameIndex frame_index ) const; + }; + + class Swapchain + { + std::vector< SwapchainImageSet > m_swapchain_images {}; + std::optional< SwapchainImageSet > m_depth {}; + + public: + + [[nodiscard]] std::shared_ptr< ImageView > depthView( FrameIndex frame_index ) const; + [[nodiscard]] std::shared_ptr< Image > depthImage( FrameIndex frame_index ) const; + std::shared_ptr< Texture > depthTexture( FrameIndex frame_index ) const; + + FGL_DELETE_ALL_RO5( Swapchain ); + + [[nodiscard]] explicit Swapchain( const std::vector< SwapchainImageInfo >& in ); + }; +} // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/constants.hpp b/src/engine/constants.hpp index 410dd48..74883dd 100644 --- a/src/engine/constants.hpp +++ b/src/engine/constants.hpp @@ -55,4 +55,6 @@ namespace fgl::engine::constants constexpr glm::vec3 DEFAULT_SCALE { 1.0f }; + constexpr glm::vec3 SUN_DIR { 0.0f, 0.0f, 1.0f }; + } // namespace fgl::engine::constants diff --git a/src/engine/descriptors/DescriptorPool.cpp b/src/engine/descriptors/DescriptorPool.cpp index ec616a8..5657453 100644 --- a/src/engine/descriptors/DescriptorPool.cpp +++ b/src/engine/descriptors/DescriptorPool.cpp @@ -9,7 +9,15 @@ namespace fgl::engine::descriptors { - vk::raii::DescriptorPool createPool( std::uint32_t set_count ) + static const std::unordered_map< vk::DescriptorType, float > DESCRIPTOR_ALLOCATION_RATIOS { + { vk::DescriptorType::eUniformBuffer, 1.0f }, + { vk::DescriptorType::eCombinedImageSampler, 2.0f }, + { vk::DescriptorType::eStorageBuffer, 1.0f }, + { vk::DescriptorType::eInputAttachment, 0.5f }, + { vk::DescriptorType::eSampledImage, 2.0f } + }; + + vk::raii::DescriptorPool createPool( const std::uint32_t set_count ) { std::vector< vk::DescriptorPoolSize > pool_sizes {}; for ( auto& [ type, ratio ] : DESCRIPTOR_ALLOCATION_RATIOS ) diff --git a/src/engine/descriptors/DescriptorPool.hpp b/src/engine/descriptors/DescriptorPool.hpp index 25d7ab4..0b9ed0a 100644 --- a/src/engine/descriptors/DescriptorPool.hpp +++ b/src/engine/descriptors/DescriptorPool.hpp @@ -17,9 +17,6 @@ namespace fgl::engine namespace fgl::engine::descriptors { - static const std::unordered_map< vk::DescriptorType, float > DESCRIPTOR_ALLOCATION_RATIOS { - { vk::DescriptorType::eUniformBuffer, 2.0f }, { vk::DescriptorType::eCombinedImageSampler, 2.0f } - }; class DescriptorPool { diff --git a/src/engine/gameobjects/components/CameraComponent.hpp b/src/engine/gameobjects/components/CameraComponent.hpp index b60e734..ebcff79 100644 --- a/src/engine/gameobjects/components/CameraComponent.hpp +++ b/src/engine/gameobjects/components/CameraComponent.hpp @@ -10,16 +10,16 @@ namespace fgl::engine { - class Camera; + class RenderCamera; COMPONENT_CLASS( CameraComponent, CameraComponentID ) { - std::shared_ptr< Camera > m_camera; + std::shared_ptr< RenderCamera > m_camera; public: CameraComponent() = delete; - CameraComponent( std::shared_ptr< Camera > & camera ); + CameraComponent( std::shared_ptr< RenderCamera > & camera ); ~CameraComponent(); }; diff --git a/src/engine/lighting/lights/Sun.cpp b/src/engine/lighting/lights/Sun.cpp new file mode 100644 index 0000000..1495bca --- /dev/null +++ b/src/engine/lighting/lights/Sun.cpp @@ -0,0 +1,12 @@ +// +// Created by kj16609 on 9/23/25. +// +#include "Sun.hpp" + +#include "camera/ShadowMap.hpp" + +namespace fgl::engine +{ + Sun::Sun() : m_shadowmap( createShadowmap( UniversalRotation::pointAt( constants::SUN_DIR ) ) ) + {} +} // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/lighting/lights/Sun.hpp b/src/engine/lighting/lights/Sun.hpp new file mode 100644 index 0000000..57f58a5 --- /dev/null +++ b/src/engine/lighting/lights/Sun.hpp @@ -0,0 +1,19 @@ +// +// Created by kj16609 on 9/23/25. +// +#pragma once +#include + +namespace fgl::engine +{ + class ShadowMap; + + struct Sun + { + std::shared_ptr< ShadowMap > m_shadowmap; + + public: + + Sun(); + }; +} // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/lighting/shadows/ShadowMap.cpp b/src/engine/lighting/shadows/ShadowMap.cpp deleted file mode 100644 index ba559fe..0000000 --- a/src/engine/lighting/shadows/ShadowMap.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// Created by kj16609 on 2/17/25. -// -#include "ShadowMap.hpp" - -#include "assets/image/Image.hpp" -#include "assets/texture/Texture.hpp" - -namespace fgl::engine::shadows -{ - - std::shared_ptr< Image > getDepthImage( const vk::Extent2D extent ) - { - constexpr auto format { vk::Format::eR16Unorm }; - constexpr vk::ImageUsageFlags usage_flags { vk::ImageUsageFlagBits::eSampled - | vk::ImageUsageFlagBits::eDepthStencilAttachment }; - constexpr auto inital_layout { vk::ImageLayout::eUndefined }; - constexpr auto final_layout { vk::ImageLayout::eDepthReadOnlyOptimal }; - - return std::make_shared< Image >( extent, format, usage_flags, inital_layout, final_layout ); - } - - PerFrameArray< std::shared_ptr< Image > > createDepthImages( vk::Extent2D extent ) - { - PerFrameArray< std::shared_ptr< Image > > array {}; - - for ( std::size_t i = 0; i < array.size(); ++i ) array[ i ] = getDepthImage( extent ); - - return array; - } - - PerFrameArray< std::shared_ptr< Texture > > ShadowMap::createDepthTargets() - { - PerFrameArray< std::shared_ptr< Texture > > array {}; - - Sampler default_sampler {}; - for ( std::size_t i = 0; i < array.size(); ++i ) - array[ i ] = std::make_shared< Texture >( m_image[ i ], std::move( default_sampler ) ); - - return array; - } - - void ShadowMap::renderForCamera( const Camera& camera ) - { - // model -> world -> camera (identity) -> screen (shadow) - // since the camera in this case is the shadow map we just need to convert the screen space to world space. So we can just use an identity matrix - - const Matrix< MatrixType::WorldToCamera > camera_matrix { m_transform.mat() }; - const Matrix< MatrixType::CameraToScreen > identity { 1.0f }; - - const Matrix< MatrixType::WorldToScreen > matrix { camera_matrix * identity }; - } - - ShadowMap::ShadowMap( const vk::Extent2D extent ) : - m_image( createDepthImages( extent ) ), - m_target( createDepthTargets() ) - {} - -} // namespace fgl::engine::shadows \ No newline at end of file diff --git a/src/engine/lighting/shadows/ShadowMap.hpp b/src/engine/lighting/shadows/ShadowMap.hpp deleted file mode 100644 index 61b4054..0000000 --- a/src/engine/lighting/shadows/ShadowMap.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// Created by kj16609 on 2/17/25. -// -#pragma once -#include - -#include - -#include "primitives/Transform.hpp" -#include "primitives/matricies/Matrix.hpp" -#include "primitives/matricies/MatrixEvolvedTypes.hpp" -#include "rendering/PresentSwapChain.hpp" - -namespace fgl::engine -{ - class Image; - class Texture; -} // namespace fgl::engine - -namespace fgl::engine::shadows -{ - - class ShadowMap - { - PerFrameArray< std::shared_ptr< Image > > m_image; - PerFrameArray< std::shared_ptr< Texture > > m_target; - - Matrix< MatrixType::WorldToScreen > m_matrix { 1.0f }; - - Transform< CoordinateSpace::World > m_transform {}; - - PerFrameArray< std::shared_ptr< Texture > > createDepthTargets(); - - public: - - void renderForCamera( const Camera& camera ); - - ShadowMap( vk::Extent2D extent ); - ~ShadowMap(); - }; - -} // namespace fgl::engine::shadows - -namespace fgl::engine -{ - using namespace shadows; -} \ No newline at end of file diff --git a/src/engine/primitives/Frustum.hpp b/src/engine/primitives/Frustum.hpp index 8c6775f..f99f6d8 100644 --- a/src/engine/primitives/Frustum.hpp +++ b/src/engine/primitives/Frustum.hpp @@ -15,7 +15,7 @@ namespace fgl::engine { - class Camera; + class RenderCamera; //! Frustum constructed in model space (To be translated to a World space frustum later) struct FrustumBase @@ -60,7 +60,7 @@ namespace fgl::engine WorldCoordinate m_position {}; - friend class Camera; + friend class RenderCamera; public: diff --git a/src/engine/primitives/rotation/UniversalRotation.cpp b/src/engine/primitives/rotation/UniversalRotation.cpp index 0ff7bd3..1eadd55 100644 --- a/src/engine/primitives/rotation/UniversalRotation.cpp +++ b/src/engine/primitives/rotation/UniversalRotation.cpp @@ -6,6 +6,11 @@ namespace fgl::engine { + UniversalRotation UniversalRotation::pointAt( const glm::vec3 vec ) + { + return UniversalRotation( QuatRotation( glm::normalize( vec ) ) ); + } + void UniversalRotation::addX( const float value ) { if ( isQuat() ) [[likely]] diff --git a/src/engine/primitives/rotation/UniversalRotation.hpp b/src/engine/primitives/rotation/UniversalRotation.hpp index 937c931..1bd8204 100644 --- a/src/engine/primitives/rotation/UniversalRotation.hpp +++ b/src/engine/primitives/rotation/UniversalRotation.hpp @@ -75,6 +75,8 @@ namespace fgl::engine return q_rotation; } + static UniversalRotation pointAt( const glm::vec3 vec ); + // Universal modification void addX( float value ); void addY( float value ); diff --git a/src/engine/rendering/devices/extensions.hpp b/src/engine/rendering/devices/extensions.hpp index 235fc6c..1159ce7 100644 --- a/src/engine/rendering/devices/extensions.hpp +++ b/src/engine/rendering/devices/extensions.hpp @@ -14,6 +14,8 @@ inline const static std::vector< const char* > DEVICE_EXTENSIONS = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, // Used for descriptor indexing + VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, + // VK_EXT_MESH_SHADER_EXTENSION_NAME, // MAGICAL SHIT VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME // Required until vulkan 1.4 }; diff --git a/src/engine/rendering/pipelines/Attachment.hpp b/src/engine/rendering/pipelines/Attachment.hpp index 386284e..0a65bdc 100644 --- a/src/engine/rendering/pipelines/Attachment.hpp +++ b/src/engine/rendering/pipelines/Attachment.hpp @@ -168,45 +168,6 @@ namespace fgl::engine friend class RenderPassBuilder; }; - template < std::size_t index, vk::ImageLayout layout > - struct InputAttachment - { - static constexpr bool is_input { true }; - static constexpr vk::ImageLayout m_layout { layout }; - static constexpr std::size_t m_index { index }; - }; - - template < std::size_t index, vk::ImageLayout layout > - struct UsedAttachment - { - static constexpr vk::ImageLayout m_layout { layout }; - static constexpr std::size_t m_index { index }; - static constexpr bool is_input { false }; - }; - - template < typename T > - concept is_input_attachment = requires( T a ) { - { a.is_input } -> std::same_as< const bool& >; - { a.m_layout } -> std::same_as< const vk::ImageLayout& >; - } && T::is_input; - - template < typename T > - concept is_used_attachment = requires( T a ) { - { a.is_input } -> std::same_as< const bool& >; - { a.m_layout } -> std::same_as< const vk::ImageLayout& >; - } && !T::is_input; - - template < typename T > concept is_wrapped_attachment = is_input_attachment< T > || is_used_attachment< T >; - - template < typename T > - requires is_wrapped_attachment< T > - using UnwrappedAttachment = std::conditional_t< is_wrapped_attachment< T >, typename T::Attachment, T >; - - //! Checks if the wrapped attachment is a depth attachment - template < typename T > - concept is_wrapped_depth_attachment = is_wrapped_attachment< T > && is_attachment< UnwrappedAttachment< T > > - && ( T::m_layout == vk::ImageLayout::eDepthStencilAttachmentOptimal ); - //Helper functions template < is_attachment Attachment, is_attachment... Attachments > consteval std::uint32_t maxIndex() @@ -221,18 +182,6 @@ namespace fgl::engine } } - template < is_attachment... Attachments > - static std::vector< vk::ImageView > getViewsForFrame( const FrameIndex frame_idx, Attachments... attachments ) - { - std::vector< vk::ImageView > view {}; - view.resize( sizeof...( Attachments ) ); - static_assert( maxIndex< Attachments... >() + 1 == sizeof...( Attachments ) ); - - ( ( view[ attachments.m_index ] = *attachments.getView( frame_idx ) ), ... ); - - return view; - } - template < is_attachment... Attachments > static std::vector< vk::ClearValue > gatherClearValues( Attachments... attachments ) { diff --git a/src/engine/rendering/pipelines/v2/PipelineBuilder.cpp b/src/engine/rendering/pipelines/v2/PipelineBuilder.cpp index 4e625e7..1d97014 100644 --- a/src/engine/rendering/pipelines/v2/PipelineBuilder.cpp +++ b/src/engine/rendering/pipelines/v2/PipelineBuilder.cpp @@ -13,6 +13,189 @@ namespace fgl::engine { + vk::raii::PipelineLayout PipelineBuilder::createLayout() + { + vk::PipelineLayoutCreateInfo info {}; + + if ( m_state->push_constant.size > 0 ) info.setPushConstantRanges( m_state->push_constant ); + + std::vector< vk::DescriptorSetLayout > set_layouts {}; + + set_layouts.reserve( m_state->descriptor_set_layouts.size() ); + + SetID max_set_idx { 0 }; + + for ( const auto& [ set_idx, _ ] : m_state->descriptor_set_layouts ) + { + max_set_idx = std::max( max_set_idx, set_idx ); + } + + // Any sets not used, Should be set to VK_NULL_HANDLE + set_layouts.resize( max_set_idx + 1 ); + + for ( std::size_t i = 0; i < set_layouts.size(); ++i ) + { + auto itter { m_state->descriptor_set_layouts.find( static_cast< SetID >( i ) ) }; + if ( itter == m_state->descriptor_set_layouts.end() ) + { + // Could not find it. Empty + set_layouts[ i ] = m_empty_set_layout.layout(); + } + else + { + set_layouts[ i ] = itter->second; + } + } + + for ( const auto& [ set_idx, layout ] : m_state->descriptor_set_layouts ) + { + set_layouts[ set_idx ] = layout; + } + + info.setSetLayouts( set_layouts ); + + return Device::getInstance()->createPipelineLayout( info ); + } + + void PipelineBuilder:: + addDescriptorSet( const SetID idx, const vk::raii::DescriptorSetLayout& descriptor_set_layout ) const + { + FGL_ASSERT( !m_state->descriptor_set_layouts.contains( idx ), "Descriptor already set! Conflicting SetIDs" ); + m_state->descriptor_set_layouts.insert( std::make_pair( idx, *descriptor_set_layout ) ); + } + + void PipelineBuilder::addDescriptorSet( descriptors::DescriptorSetLayout& descriptor ) + { + addDescriptorSet( descriptor.m_set_idx, descriptor.layout() ); + } + + void PipelineBuilder::addDynamicState( vk::DynamicState dynamic_state ) + { + m_state->m_dynamic_state.emplace_back( dynamic_state ); + } + + void PipelineBuilder::setPushConstant( const vk::ShaderStageFlags flags, std::uint32_t size ) + { + m_state->push_constant.offset = 0; + m_state->push_constant.size = size; + m_state->push_constant.stageFlags = flags; + } + + void PipelineBuilder::setBindPoint( vk::PipelineBindPoint bind_point ) + { + m_state->bind_point = bind_point; + } + + PipelineBuilder::BuilderState::Formats::Formats() + {} + + [[nodiscard]] vk::PipelineColorBlendAttachmentState& PipelineBuilder::BuilderState::addColorAttachment() + { + color_blend_attachment.emplace_back(); + color_blend_info.setAttachments( color_blend_attachment ); + return color_blend_attachment.back(); + } + + PipelineBuilder::BuilderState::BuilderState( std::uint32_t subpass ) : m_subpass_stage( subpass ) + { + setDefault(); + } + + void PipelineBuilder::BuilderState::setDefault() + { + viewport_info.viewportCount = 1; + viewport_info.pViewports = nullptr; + viewport_info.scissorCount = 1; + viewport_info.pScissors = nullptr; + + assembly_info.topology = vk::PrimitiveTopology::eTriangleList; + assembly_info.primitiveRestartEnable = VK_FALSE; + + rasterization_info.depthClampEnable = VK_FALSE; + rasterization_info.rasterizerDiscardEnable = VK_FALSE; + rasterization_info.polygonMode = vk::PolygonMode::eFill; + rasterization_info.cullMode = vk::CullModeFlagBits::eBack; + rasterization_info.frontFace = vk::FrontFace::eClockwise; + rasterization_info.depthBiasEnable = VK_FALSE; + rasterization_info.depthBiasConstantFactor = 0.0f; + rasterization_info.depthBiasClamp = 0.0f; + rasterization_info.depthBiasSlopeFactor = 0.0f; + rasterization_info.lineWidth = 1.0f; + + multisample_info.rasterizationSamples = vk::SampleCountFlagBits::e1; + multisample_info.sampleShadingEnable = VK_FALSE; + multisample_info.minSampleShading = 1.0f; + multisample_info.pSampleMask = nullptr; + multisample_info.alphaToCoverageEnable = VK_FALSE; + multisample_info.alphaToOneEnable = VK_FALSE; + + color_blend_info.logicOpEnable = VK_FALSE; + color_blend_info.logicOp = vk::LogicOp::eCopy; + color_blend_info.attachmentCount = 0; + color_blend_info.pAttachments = nullptr; + color_blend_info.blendConstants[ 0 ] = 0.0f; + color_blend_info.blendConstants[ 1 ] = 0.0f; + color_blend_info.blendConstants[ 2 ] = 0.0f; + color_blend_info.blendConstants[ 3 ] = 0.0f; + + depth_stencil_info.depthTestEnable = VK_TRUE; + depth_stencil_info.depthWriteEnable = VK_TRUE; + depth_stencil_info.depthCompareOp = vk::CompareOp::eLess; + depth_stencil_info.depthBoundsTestEnable = VK_FALSE; + depth_stencil_info.stencilTestEnable = VK_FALSE; + //depth_stencil_info.front = {}; + //depth_stencil_info.back = {}; + depth_stencil_info.minDepthBounds = 0.0f; + depth_stencil_info.maxDepthBounds = 1.0f; + + dynamic_state_enables = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; + dynamic_state_info.setDynamicStates( dynamic_state_enables ); + //info.dynamic_state_info.flags = 0; + } + + void PipelineBuilder::setTopology( const vk::PrimitiveTopology primitive_topology ) + { + m_state->assembly_info.topology = primitive_topology; + } + + void PipelineBuilder::disableVertexInput() + { + m_state->vertex_input_descriptions.bindings = {}; + m_state->vertex_input_descriptions.attributes = {}; + } + + void PipelineBuilder::disableCulling() + { + m_state->rasterization_info.cullMode = vk::CullModeFlagBits::eNone; + } + + void PipelineBuilder::addDepthAttachment() + { + m_state->formats.depth = pickDepthFormat(); + } + + AttachmentBuilder PipelineBuilder::addAttachment() + { + return { *this }; + } + + AttachmentBuilder PipelineBuilder::addColorAttachment() + { + AttachmentBuilder builder { addAttachment() }; + return builder; + } + + void PipelineBuilder::setBindingDescriptions( const std::vector< vk::VertexInputBindingDescription >& descriptions ) + { + m_state->vertex_input_descriptions.bindings = descriptions; + } + + void PipelineBuilder:: + setAttributeDescriptions( const std::vector< vk::VertexInputAttributeDescription >& descriptions ) const + { + m_state->vertex_input_descriptions.attributes = descriptions; + } + PipelineBuilder::PipelineBuilder( std::uint32_t subpass ) : m_state( std::make_unique< BuilderState >( subpass ) ) { addDynamicState( vk::DynamicState::eViewport ); @@ -87,6 +270,12 @@ namespace fgl::engine return pipeline; } + vk::raii::Pipeline PipelineBuilder::createDynamicPipeline( BuilderState& state, vk::raii::PipelineLayout& layout ) + { + if ( state.shaders.compute ) return createComputePipeline( state, layout ); + return createGraphicsPipeline( state, layout ); + } + vk::raii::Pipeline PipelineBuilder::createComputePipeline( BuilderState& state, vk::raii::PipelineLayout& layout ) { vk::StructureChain< vk::ComputePipelineCreateInfo > chain {}; @@ -106,12 +295,6 @@ namespace fgl::engine return Device::getInstance()->createComputePipeline( VK_NULL_HANDLE, info ); } - vk::raii::Pipeline PipelineBuilder::createDynamicPipeline( BuilderState& state, vk::raii::PipelineLayout& layout ) - { - if ( state.shaders.compute ) return createComputePipeline( state, layout ); - return createGraphicsPipeline( state, layout ); - } - vk::raii::Pipeline PipelineBuilder::createGraphicsPipeline( BuilderState& state, vk::raii::PipelineLayout& layout ) { vk::StructureChain< vk::GraphicsPipelineCreateInfo, vk::PipelineRenderingCreateInfo > chain {}; @@ -174,189 +357,6 @@ namespace fgl::engine return pipeline; } - vk::raii::PipelineLayout PipelineBuilder::createLayout() - { - vk::PipelineLayoutCreateInfo info {}; - - if ( m_state->push_constant.size > 0 ) info.setPushConstantRanges( m_state->push_constant ); - - std::vector< vk::DescriptorSetLayout > set_layouts {}; - - set_layouts.reserve( m_state->descriptor_set_layouts.size() ); - - SetID max_set_idx { 0 }; - - for ( const auto& [ set_idx, _ ] : m_state->descriptor_set_layouts ) - { - max_set_idx = std::max( max_set_idx, set_idx ); - } - - // Any sets not used, Should be set to VK_NULL_HANDLE - set_layouts.resize( max_set_idx + 1 ); - - for ( std::size_t i = 0; i < set_layouts.size(); ++i ) - { - auto itter { m_state->descriptor_set_layouts.find( static_cast< SetID >( i ) ) }; - if ( itter == m_state->descriptor_set_layouts.end() ) - { - // Could not find it. Empty - set_layouts[ i ] = m_empty_set_layout.layout(); - } - else - { - set_layouts[ i ] = itter->second; - } - } - - for ( const auto& [ set_idx, layout ] : m_state->descriptor_set_layouts ) - { - set_layouts[ set_idx ] = layout; - } - - info.setSetLayouts( set_layouts ); - - return Device::getInstance()->createPipelineLayout( info ); - } - - void PipelineBuilder:: - addDescriptorSet( const SetID idx, const vk::raii::DescriptorSetLayout& descriptor_set_layout ) const - { - FGL_ASSERT( !m_state->descriptor_set_layouts.contains( idx ), "Descriptor already set!" ); - m_state->descriptor_set_layouts.insert( std::make_pair( idx, *descriptor_set_layout ) ); - } - - void PipelineBuilder::addDescriptorSet( descriptors::DescriptorSetLayout& descriptor ) - { - addDescriptorSet( descriptor.m_set_idx, descriptor.layout() ); - } - - void PipelineBuilder::addDynamicState( vk::DynamicState dynamic_state ) - { - m_state->m_dynamic_state.emplace_back( dynamic_state ); - } - - void PipelineBuilder::setPushConstant( const vk::ShaderStageFlags flags, std::uint32_t size ) - { - m_state->push_constant.offset = 0; - m_state->push_constant.size = size; - m_state->push_constant.stageFlags = flags; - } - - void PipelineBuilder::setBindPoint( vk::PipelineBindPoint bind_point ) - { - m_state->bind_point = bind_point; - } - - PipelineBuilder::BuilderState::Formats::Formats() - {} - - [[nodiscard]] vk::PipelineColorBlendAttachmentState& PipelineBuilder::BuilderState::addColorAttachment() - { - color_blend_attachment.emplace_back(); - color_blend_info.setAttachments( color_blend_attachment ); - return color_blend_attachment.back(); - } - - void PipelineBuilder::BuilderState::setDefault() - { - viewport_info.viewportCount = 1; - viewport_info.pViewports = nullptr; - viewport_info.scissorCount = 1; - viewport_info.pScissors = nullptr; - - assembly_info.topology = vk::PrimitiveTopology::eTriangleList; - assembly_info.primitiveRestartEnable = VK_FALSE; - - rasterization_info.depthClampEnable = VK_FALSE; - rasterization_info.rasterizerDiscardEnable = VK_FALSE; - rasterization_info.polygonMode = vk::PolygonMode::eFill; - rasterization_info.cullMode = vk::CullModeFlagBits::eBack; - rasterization_info.frontFace = vk::FrontFace::eClockwise; - rasterization_info.depthBiasEnable = VK_FALSE; - rasterization_info.depthBiasConstantFactor = 0.0f; - rasterization_info.depthBiasClamp = 0.0f; - rasterization_info.depthBiasSlopeFactor = 0.0f; - rasterization_info.lineWidth = 1.0f; - - multisample_info.rasterizationSamples = vk::SampleCountFlagBits::e1; - multisample_info.sampleShadingEnable = VK_FALSE; - multisample_info.minSampleShading = 1.0f; - multisample_info.pSampleMask = nullptr; - multisample_info.alphaToCoverageEnable = VK_FALSE; - multisample_info.alphaToOneEnable = VK_FALSE; - - color_blend_info.logicOpEnable = VK_FALSE; - color_blend_info.logicOp = vk::LogicOp::eCopy; - color_blend_info.attachmentCount = 0; - color_blend_info.pAttachments = nullptr; - color_blend_info.blendConstants[ 0 ] = 0.0f; - color_blend_info.blendConstants[ 1 ] = 0.0f; - color_blend_info.blendConstants[ 2 ] = 0.0f; - color_blend_info.blendConstants[ 3 ] = 0.0f; - - depth_stencil_info.depthTestEnable = VK_TRUE; - depth_stencil_info.depthWriteEnable = VK_TRUE; - depth_stencil_info.depthCompareOp = vk::CompareOp::eLess; - depth_stencil_info.depthBoundsTestEnable = VK_FALSE; - depth_stencil_info.stencilTestEnable = VK_FALSE; - //depth_stencil_info.front = {}; - //depth_stencil_info.back = {}; - depth_stencil_info.minDepthBounds = 0.0f; - depth_stencil_info.maxDepthBounds = 1.0f; - - dynamic_state_enables = { vk::DynamicState::eViewport, vk::DynamicState::eScissor }; - dynamic_state_info.setDynamicStates( dynamic_state_enables ); - //info.dynamic_state_info.flags = 0; - } - - PipelineBuilder::BuilderState::BuilderState( std::uint32_t subpass ) : m_subpass_stage( subpass ) - { - setDefault(); - } - - void PipelineBuilder::setTopology( const vk::PrimitiveTopology primitive_topology ) - { - m_state->assembly_info.topology = primitive_topology; - } - - void PipelineBuilder::disableVertexInput() - { - m_state->vertex_input_descriptions.bindings = {}; - m_state->vertex_input_descriptions.attributes = {}; - } - - void PipelineBuilder::disableCulling() - { - m_state->rasterization_info.cullMode = vk::CullModeFlagBits::eNone; - } - - void PipelineBuilder::addDepthAttachment() - { - m_state->formats.depth = pickDepthFormat(); - } - - AttachmentBuilder PipelineBuilder::addAttachment() - { - return { *this }; - } - - AttachmentBuilder PipelineBuilder::addColorAttachment() - { - AttachmentBuilder builder { addAttachment() }; - return builder; - } - - void PipelineBuilder::setBindingDescriptions( const std::vector< vk::VertexInputBindingDescription >& descriptions ) - { - m_state->vertex_input_descriptions.bindings = descriptions; - } - - void PipelineBuilder:: - setAttributeDescriptions( const std::vector< vk::VertexInputAttributeDescription >& descriptions ) const - { - m_state->vertex_input_descriptions.attributes = descriptions; - } - vk::raii::Pipeline PipelineBuilder::createFromState( BuilderState& state, vk::raii::PipelineLayout& layout ) { return createDynamicPipeline( state, layout ); diff --git a/src/engine/scene/Scene.hpp b/src/engine/scene/Scene.hpp index 2e6172f..20caaf9 100644 --- a/src/engine/scene/Scene.hpp +++ b/src/engine/scene/Scene.hpp @@ -2,7 +2,7 @@ // Created by kj16609 on 2/28/25. // #pragma once -#include "camera/Camera.hpp" +#include "camera/RenderCamera.hpp" namespace fgl::engine { diff --git a/src/engine/systems/prerender/CullingSystem.cpp b/src/engine/systems/prerender/CullingSystem.cpp index 70f6547..a4ed4e8 100644 --- a/src/engine/systems/prerender/CullingSystem.cpp +++ b/src/engine/systems/prerender/CullingSystem.cpp @@ -8,7 +8,7 @@ #include "assets/model/Model.hpp" #include "engine/FrameInfo.hpp" -#include "engine/camera/Camera.hpp" +#include "engine/camera/RenderCamera.hpp" namespace fgl::engine { @@ -44,7 +44,7 @@ namespace fgl::engine CullingSystem::~CullingSystem() {} - void CullingSystem::pass( FrameInfo& info ) + void CullingSystem::pass( const FrameInfo& info ) { ZoneScopedN( "Culling pass" ); @@ -61,10 +61,13 @@ namespace fgl::engine m_cull_compute->bindDescriptor( command_buffer, info.m_primitives_desc ); // primitive set m_cull_compute->bindDescriptor( command_buffer, info.m_instances_desc ); // instances - m_cull_compute->bindDescriptor( command_buffer, info.m_command_buffer_desc ); // commands output + m_cull_compute->bindDescriptor( + command_buffer, *info.camera->m_gpu_draw_cmds_desc[ info.in_flight_idx ] ); // commands output + auto& commands { info.camera->m_gpu_draw_commands[ info.in_flight_idx ] }; + commands.resize( info.instances.size() ); CullPushConstants push_constants {}; - push_constants.draw_count = info.m_commands.size(); + push_constants.draw_count = commands.size(); command_buffer->pushConstants< CullPushConstants >( m_cull_compute->layout(), vk::ShaderStageFlagBits::eCompute, 0, { push_constants } ); @@ -76,7 +79,7 @@ namespace fgl::engine command_buffer->dispatch( group_count, 1, 1 ); - // Add a memory barrier to ensure synchronization between the compute and subsequent stages + // Add a memory barrier to ensure synchronization between the compute and later stages vk::MemoryBarrier memory_barrier { vk::AccessFlagBits::eShaderWrite, vk::AccessFlagBits::eVertexAttributeRead | vk::AccessFlagBits::eIndirectCommandRead, diff --git a/src/engine/systems/prerender/CullingSystem.hpp b/src/engine/systems/prerender/CullingSystem.hpp index 2478118..4d937f3 100644 --- a/src/engine/systems/prerender/CullingSystem.hpp +++ b/src/engine/systems/prerender/CullingSystem.hpp @@ -38,7 +38,7 @@ namespace fgl::engine ~CullingSystem(); - void pass( FrameInfo& info ); + void pass( const FrameInfo& info ); }; static_assert( is_system< CullingSystem > ); diff --git a/src/engine/systems/render/EntityRendererSystem.cpp b/src/engine/systems/render/EntityRendererSystem.cpp index c2c4d41..bdda447 100644 --- a/src/engine/systems/render/EntityRendererSystem.cpp +++ b/src/engine/systems/render/EntityRendererSystem.cpp @@ -10,7 +10,7 @@ #include "EngineContext.hpp" #include "assets/model/ModelVertex.hpp" #include "engine/assets/material/Material.hpp" -#include "engine/camera/Camera.hpp" +#include "engine/camera/RenderCamera.hpp" #include "engine/debug/timing/FlameGraph.hpp" #include "engine/rendering/pipelines/v2/Pipeline.hpp" #include "engine/rendering/pipelines/v2/PipelineBuilder.hpp" @@ -29,7 +29,7 @@ namespace fgl::engine addGBufferAttachments( builder ); - builder.addDescriptorSet( Camera::getDescriptorLayout() ); + builder.addDescriptorSet( RenderCamera::getDescriptorLayout() ); builder.addDescriptorSet( Texture::getDescriptorLayout() ); builder.addDescriptorSet( Material::getDescriptorLayout() ); @@ -92,18 +92,17 @@ namespace fgl::engine const std::vector< vk::Buffer > vert_buffers { model_buffers.m_vertex_buffer->getVkBuffer(), - model_buffers.m_generated_instance_info[ info.in_flight_idx ].getVkBuffer() + info.camera->m_generated_instance_info[ info.in_flight_idx ].getVkBuffer(), }; command_buffer->bindVertexBuffers( - 0, vert_buffers, { 0, model_buffers.m_generated_instance_info[ info.in_flight_idx ].getOffset() } ); + 0, vert_buffers, { 0, info.camera->m_generated_instance_info[ info.in_flight_idx ].getOffset() } ); command_buffer->bindIndexBuffer( model_buffers.m_index_buffer->getVkBuffer(), 0, vk::IndexType::eUint32 ); - command_buffer->drawIndexedIndirect( - info.m_commands.getVkBuffer(), - info.m_commands.getOffset(), - info.m_commands.size(), - info.m_commands.stride() ); + const auto& commands { info.camera->m_gpu_draw_commands[ info.in_flight_idx ] }; + + command_buffer + ->drawIndexedIndirect( commands.getVkBuffer(), commands.getOffset(), commands.size(), commands.stride() ); }; } // namespace fgl::engine diff --git a/src/engine/systems/render/LineDrawer.cpp b/src/engine/systems/render/LineDrawer.cpp index 8e5450c..a061624 100644 --- a/src/engine/systems/render/LineDrawer.cpp +++ b/src/engine/systems/render/LineDrawer.cpp @@ -6,7 +6,7 @@ #include "engine/FrameInfo.hpp" #include "engine/assets/model/SimpleVertex.hpp" -#include "engine/camera/Camera.hpp" +#include "engine/camera/RenderCamera.hpp" #include "engine/debug/drawers.hpp" #include "engine/primitives/points/Coordinate.hpp" #include "engine/rendering/pipelines/v2/Pipeline.hpp" @@ -27,7 +27,7 @@ namespace fgl::engine { PipelineBuilder builder { 0 }; - builder.addDescriptorSet( Camera::getDescriptorLayout() ); + builder.addDescriptorSet( RenderCamera::getDescriptorLayout() ); addGBufferAttachments( builder ); diff --git a/src/shaders/composition.slang b/src/shaders/composition.slang index 8643c90..a8f636e 100644 --- a/src/shaders/composition.slang +++ b/src/shaders/composition.slang @@ -1,6 +1,7 @@ #version 450 import objects.camera; +import objects.gbuffer; struct Vertex { vec4 position : SV_Position; @@ -24,13 +25,6 @@ struct CompositeFragment { vec4 color; }; -struct GBufferInput { - SubpassInput color : COLOR; - SubpassInput position : POSITION; - SubpassInput normal : NORMAL; - SubpassInput metallic : METALLIC; - SubpassInput emissive : EMISSIVE; -}; // SubpassInput< vec4 > test : TEST; @@ -46,6 +40,12 @@ ParameterBlock gbuffer : GBUFFER; [[vk::binding(0,1)]] ParameterBlock< CameraData > camera : CAMERA; +[[vk::binding(0,2)]] +ParameterBlock< CameraData > sun_camera; + +[[vk::binding(1,2)]] +Sampler2D shadow_sampler; + //TODO: constant flags // Direction the sun is facing diff --git a/src/shaders/culling.slang b/src/shaders/culling.slang index 0469e50..3a79cad 100644 --- a/src/shaders/culling.slang +++ b/src/shaders/culling.slang @@ -75,7 +75,7 @@ void computeMain( uint3 dispatch_id : SV_DispatchThreadID) out_instances[ instance_index ].material_id = instance.material_id; const ModelInstanceInfo model_instance = model_instances[ instance.model_index ]; - out_instances[ instance_index ].model_matrix = model_instance.model_matrix; + out_instances[ instance_index ].model_matrix = {model_instance.model_matrix}; // out_instances[ instance_index ].normal_matrix = model_instance.normal_matrix; } else diff --git a/src/shaders/objects/camera.slang b/src/shaders/objects/camera.slang index d2561cc..7f9533f 100644 --- a/src/shaders/objects/camera.slang +++ b/src/shaders/objects/camera.slang @@ -14,6 +14,13 @@ public struct CameraData return vec3( inverse_view[ 0 ][ 3 ], inverse_view[ 1 ][ 3 ], inverse_view[ 2 ][ 3 ] ); } + public vec4 toCameraSpace(const vec4 world_coordinate) + { + return mul(mat(), world_coordinate); + } + + + public mat4x4 mat() { return mul( projection, view ); diff --git a/src/shaders/objects/gamemodel.slang b/src/shaders/objects/gamemodel.slang index a2c30a6..0172d76 100644 --- a/src/shaders/objects/gamemodel.slang +++ b/src/shaders/objects/gamemodel.slang @@ -11,6 +11,41 @@ public struct PrimitiveRenderInfo { public uint32_t index_count; }; +public struct ModelMatrix +{ + mat4x4 matrix; + + public mat3 toNormalMatrix() + { + return transpose( inverse( mat3( matrix ) ) ); + } + + public vec3 normalizeNormal( vec3 normal ) + { + return normalize( mul( toNormalMatrix(), normal ) ); + } + + public vec4 toWorldSpace( vec4 position ) + { + return mul(matrix, position); + } + + public __init( mat4x4 matrix_in ) + { + matrix = matrix_in; + } + + public mat4x4 mat() + { + return matrix; + } +}; + +ModelMatrix operator=(mat4x4 matrix) +{ + return {matrix}; +} + // Each primitive has one instance public struct PrimitiveInstanceInfo { @@ -22,7 +57,7 @@ public struct PrimitiveInstanceInfo // One object exists for each render instance public struct InstanceRenderInfo { - public mat4x4 model_matrix; + public ModelMatrix model_matrix; // public mat4x4 normal_matrix; public uint32_t material_id; }; diff --git a/src/shaders/objects/gbuffer.slang b/src/shaders/objects/gbuffer.slang index 668a691..0d9aab2 100644 --- a/src/shaders/objects/gbuffer.slang +++ b/src/shaders/objects/gbuffer.slang @@ -11,3 +11,10 @@ public struct GBufferFragment public vec3 emissive : EMISSIVE; }; +public struct GBufferInput { + public SubpassInput color : COLOR; + public SubpassInput position : POSITION; + public SubpassInput normal : NORMAL; + public SubpassInput metallic : METALLIC; + public SubpassInput emissive : EMISSIVE; +}; diff --git a/src/shaders/shadowmap.slang b/src/shaders/shadowmap.slang index b1482fb..4e28eb9 100644 --- a/src/shaders/shadowmap.slang +++ b/src/shaders/shadowmap.slang @@ -1,15 +1,36 @@ - +#version 450 import model.vertex; +import objects.camera; struct CoarseVertex { float4 position : SV_Position; -} +}; + +struct Fragment +{ +}; + +[ [ vk::binding( 0, 1 ) ] ] +ConstantBuffer< CameraData > camera : CAMERA; [shader("vertex")] -CoarseVertex vertexMain( ModelVertex in_vertex ) +CoarseVertex vertexMain(ModelVertex in_vertex) { + CoarseVertex out_vertex; + vec4 world_pos = in_vertex.instance.model_matrix.toWorldSpace( vec4(in_vertex.simple.position, 1.0) ); + out_vertex.position = camera.toCameraSpace( world_pos ); + return out_vertex; } + +[shader("fragment")] +Fragment fragmentMain(CoarseVertex vertex) +{ + Fragment fragment; + + return fragment; + +} \ No newline at end of file diff --git a/src/shaders/textured.slang b/src/shaders/textured.slang index ad81cee..a77a68a 100644 --- a/src/shaders/textured.slang +++ b/src/shaders/textured.slang @@ -23,18 +23,20 @@ CoarseVertex vertexMain( ModelVertex in_vertex ) { CoarseVertex out_vertex; - vec4 world_pos = mul(in_vertex.instance.model_matrix, vec4(in_vertex.simple.position, 1.0)); - - const float4 transformed_pos = mul( camera.mat(), world_pos ); - out_vertex.position = transformed_pos; +// vec4 world_pos = mul(in_vertex.instance.model_matrix, vec4(in_vertex.simple.position, 1.0)); + vec4 world_pos = in_vertex.instance.model_matrix.toWorldSpace( vec4(in_vertex.simple.position, 1.0) ); out_vertex.world_pos = world_pos.xyz; - mat3 normal_matrix = transpose( inverse( mat3( in_vertex.instance.model_matrix ) ) ); + out_vertex.position = camera.toCameraSpace( world_pos) ; - out_vertex.normal = normalize( mul(normal_matrix, in_vertex.normal) ); +// mat3 normal_matrix = transpose( inverse( mat3( in_vertex.instance.model_matrix ) ) ); + mat3 normal_matrix = in_vertex.instance.model_matrix.toNormalMatrix(); + +// out_vertex.normal = normalize( mul(normal_matrix, in_vertex.normal) ); + out_vertex.normal = in_vertex.instance.model_matrix.normalizeNormal( in_vertex.normal ); out_vertex.tex_coord = in_vertex.uv; out_vertex.material_id = in_vertex.instance.material_id; - out_vertex.matrix = in_vertex.instance.model_matrix; + out_vertex.matrix = in_vertex.instance.model_matrix.mat(); out_vertex.tangent = in_vertex.tangent; return out_vertex;