Start basic shadowmap stuff
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
// Created by kj16609 on 7/23/24.
|
||||
//
|
||||
|
||||
#include "engine/camera/Camera.hpp"
|
||||
#include "engine/camera/RenderCamera.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@@ -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 {};
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
#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();
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
#include <iostream>
|
||||
|
||||
#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() };
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glm/mat4x4.hpp>
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
#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
|
||||
240
src/engine/camera/CameraViewpoint.cpp
Normal file
240
src/engine/camera/CameraViewpoint.cpp
Normal file
@@ -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
|
||||
@@ -1,82 +1,37 @@
|
||||
//
|
||||
// Created by kj16609 on 11/28/23.
|
||||
// Created by kj16609 on 9/23/25.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Weffc++"
|
||||
#pragma GCC diagnostic ignored "-Wduplicated-branches"
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#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
|
||||
@@ -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() };
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
|
||||
#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; }
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
// Created by kj16609 on 11/28/23.
|
||||
//
|
||||
|
||||
#include "Camera.hpp"
|
||||
#include "RenderCamera.hpp"
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#include <tracy/Tracy.hpp>
|
||||
|
||||
#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" );
|
||||
return m_transform.mat();
|
||||
}
|
||||
|
||||
updateFrustum();
|
||||
}
|
||||
|
||||
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
|
||||
110
src/engine/camera/RenderCamera.hpp
Normal file
110
src/engine/camera/RenderCamera.hpp
Normal file
@@ -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 <glm/glm.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#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
|
||||
167
src/engine/camera/ShadowMap.cpp
Normal file
167
src/engine/camera/ShadowMap.cpp
Normal file
@@ -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
|
||||
55
src/engine/camera/ShadowMap.hpp
Normal file
55
src/engine/camera/ShadowMap.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// Created by kj16609 on 9/23/25.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#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
|
||||
80
src/engine/camera/Swapchain.cpp
Normal file
80
src/engine/camera/Swapchain.cpp
Normal file
@@ -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
|
||||
69
src/engine/camera/Swapchain.hpp
Normal file
69
src/engine/camera/Swapchain.hpp
Normal file
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// Created by kj16609 on 9/23/25.
|
||||
//
|
||||
#pragma once
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#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
|
||||
@@ -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
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
12
src/engine/lighting/lights/Sun.cpp
Normal file
12
src/engine/lighting/lights/Sun.cpp
Normal file
@@ -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
|
||||
19
src/engine/lighting/lights/Sun.hpp
Normal file
19
src/engine/lighting/lights/Sun.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Created by kj16609 on 9/23/25.
|
||||
//
|
||||
#pragma once
|
||||
#include <memory>
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
class ShadowMap;
|
||||
|
||||
struct Sun
|
||||
{
|
||||
std::shared_ptr< ShadowMap > m_shadowmap;
|
||||
|
||||
public:
|
||||
|
||||
Sun();
|
||||
};
|
||||
} // namespace fgl::engine
|
||||
@@ -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
|
||||
@@ -1,47 +0,0 @@
|
||||
//
|
||||
// Created by kj16609 on 2/17/25.
|
||||
//
|
||||
#pragma once
|
||||
#include <vulkan/vulkan_raii.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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]]
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Created by kj16609 on 2/28/25.
|
||||
//
|
||||
#pragma once
|
||||
#include "camera/Camera.hpp"
|
||||
#include "camera/RenderCamera.hpp"
|
||||
|
||||
namespace fgl::engine
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace fgl::engine
|
||||
|
||||
~CullingSystem();
|
||||
|
||||
void pass( FrameInfo& info );
|
||||
void pass( const FrameInfo& info );
|
||||
};
|
||||
|
||||
static_assert( is_system< CullingSystem > );
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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<vec4> color : COLOR;
|
||||
SubpassInput<vec4> position : POSITION;
|
||||
SubpassInput<vec4> normal : NORMAL;
|
||||
SubpassInput<vec4> metallic : METALLIC;
|
||||
SubpassInput<vec4> emissive : EMISSIVE;
|
||||
};
|
||||
|
||||
// SubpassInput< vec4 > test : TEST;
|
||||
|
||||
@@ -46,6 +40,12 @@ ParameterBlock<GBufferInput> 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -11,3 +11,10 @@ public struct GBufferFragment
|
||||
public vec3 emissive : EMISSIVE;
|
||||
};
|
||||
|
||||
public struct GBufferInput {
|
||||
public SubpassInput<vec4> color : COLOR;
|
||||
public SubpassInput<vec4> position : POSITION;
|
||||
public SubpassInput<vec4> normal : NORMAL;
|
||||
public SubpassInput<vec4> metallic : METALLIC;
|
||||
public SubpassInput<vec4> emissive : EMISSIVE;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user