242 lines
7.2 KiB
C++
242 lines
7.2 KiB
C++
//
|
|
// Created by kj16609 on 9/23/25.
|
|
//
|
|
#include "CameraViewpoint.hpp"
|
|
|
|
#include "CameraInfo.hpp"
|
|
#include "RenderCamera.hpp"
|
|
#include "assets/model/Model.hpp"
|
|
#include "math/literals/size.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, static_cast< float >( this->m_extent.width ), static_cast< float >( this->m_extent.height ),
|
|
0.0f, 1.0f };
|
|
}
|
|
|
|
descriptors::DescriptorSetLayout& CameraViewpoint::getDescriptorLayout()
|
|
{
|
|
return camera_descriptor_set;
|
|
}
|
|
|
|
} // namespace fgl::engine
|