Get debugging information mostly working

This commit is contained in:
2024-01-29 14:00:15 -05:00
parent 933f58b33e
commit 23fc3371f4
17 changed files with 861 additions and 236 deletions

View File

@@ -12,6 +12,7 @@ namespace fgl::engine
void Camera::setOrthographicProjection( float left, float right, float top, float bottom, float near, float far )
{
ZoneScoped;
projection_matrix = glm::mat4 { 1.0f };
projection_matrix[ 0 ][ 0 ] = 2.0f / ( right - left );
projection_matrix[ 1 ][ 1 ] = 2.0f / ( bottom - top );
@@ -19,10 +20,13 @@ namespace fgl::engine
projection_matrix[ 3 ][ 0 ] = -( right + left ) / ( right - left );
projection_matrix[ 3 ][ 1 ] = -( bottom + top ) / ( bottom - top );
projection_matrix[ 3 ][ 2 ] = -near / ( far - near );
//TODO: Figure out frustum culling for orthographic projection. (If we even wanna use it)
}
void Camera::setPerspectiveProjection( float fovy, float aspect, float near, float far )
{
ZoneScoped;
assert( glm::abs( aspect - std::numeric_limits< float >::epsilon() ) > 0 );
const float tan_half_fovy { std::tan( fovy / 2.0f ) };
projection_matrix = glm::mat4 { 0.0f };
@@ -31,50 +35,57 @@ namespace fgl::engine
projection_matrix[ 2 ][ 2 ] = far / ( far - near );
projection_matrix[ 2 ][ 3 ] = 1.0f;
projection_matrix[ 3 ][ 2 ] = -( far * near ) / ( far - near );
base_frustum = createFrustum( *this, aspect, fovy, near, far );
}
void Camera::setViewDirection( glm::vec3 position, glm::vec3 direction, glm::vec3 up )
{
const glm::vec3 w { glm::normalize( direction ) };
const glm::vec3 u { glm::normalize( glm::cross( w, up ) ) };
const glm::vec3 v { glm::cross( w, u ) };
ZoneScoped;
const glm::vec3 w_direction { glm::normalize( direction ) };
const glm::vec3 u_right { glm::normalize( glm::cross( w_direction, up ) ) };
const glm::vec3 v_up { glm::cross( w_direction, u_right ) };
/*
* view_matrix
* u_r = view_right
* v_u = view_up
* w_d = view_direction
*
* | u_r.x u_r.y u_r.z 0 |
* | v_u.x v_u.y v_u.z 0 |
* | w_d.x w_d.y w_d.z 0 |
* | 0 0 0 1 |
*/
view_matrix = glm::mat4 { 1.0f };
view_matrix[ 0 ][ 0 ] = u.x;
view_matrix[ 1 ][ 0 ] = u.y;
view_matrix[ 2 ][ 0 ] = u.z;
view_matrix[ 0 ][ 1 ] = v.x;
view_matrix[ 1 ][ 1 ] = v.y;
view_matrix[ 2 ][ 1 ] = v.z;
view_matrix[ 0 ][ 2 ] = w.x;
view_matrix[ 1 ][ 2 ] = w.y;
view_matrix[ 2 ][ 2 ] = w.z;
view_matrix[ 3 ][ 0 ] = -glm::dot( u, position );
view_matrix[ 3 ][ 1 ] = -glm::dot( v, position );
view_matrix[ 3 ][ 2 ] = -glm::dot( w, position );
view_matrix[ 0 ][ 0 ] = u_right.x;
view_matrix[ 1 ][ 0 ] = u_right.y;
view_matrix[ 2 ][ 0 ] = u_right.z;
inverse_view_matrix = glm::mat4 { 1.0f };
inverse_view_matrix[ 0 ][ 0 ] = u.x;
inverse_view_matrix[ 0 ][ 1 ] = u.y;
inverse_view_matrix[ 0 ][ 2 ] = u.z;
inverse_view_matrix[ 1 ][ 0 ] = v.x;
inverse_view_matrix[ 1 ][ 1 ] = v.y;
inverse_view_matrix[ 1 ][ 2 ] = v.z;
inverse_view_matrix[ 2 ][ 0 ] = w.x;
inverse_view_matrix[ 2 ][ 1 ] = w.y;
inverse_view_matrix[ 2 ][ 2 ] = w.z;
inverse_view_matrix[ 3 ][ 0 ] = position.x;
inverse_view_matrix[ 3 ][ 1 ] = position.y;
inverse_view_matrix[ 3 ][ 2 ] = position.z;
view_matrix[ 0 ][ 1 ] = v_up.x;
view_matrix[ 1 ][ 1 ] = v_up.y;
view_matrix[ 2 ][ 1 ] = v_up.z;
view_matrix[ 0 ][ 2 ] = w_direction.x;
view_matrix[ 1 ][ 2 ] = w_direction.y;
view_matrix[ 2 ][ 2 ] = w_direction.z;
view_matrix[ 3 ][ 0 ] = -glm::dot( u_right, position );
view_matrix[ 3 ][ 1 ] = -glm::dot( v_up, position );
view_matrix[ 3 ][ 2 ] = -glm::dot( w_direction, position );
frustum = base_frustum * view_matrix;
}
void Camera::setViewTarget( glm::vec3 position, glm::vec3 target, glm::vec3 up )
{
setViewDirection( position, target - position, up );
setViewDirection( position, glm::normalize( target - position ), up );
}
void Camera::setViewYXZ( glm::vec3 position, glm::vec3 rotation )
{
ZoneScoped;
const float c3 { glm::cos( rotation.z ) };
const float s3 { glm::sin( rotation.z ) };
const float c2 { glm::cos( rotation.x ) };
@@ -84,33 +95,52 @@ namespace fgl::engine
const glm::vec3 u { ( c1 * c3 + s1 * s2 * s3 ), ( c2 * s3 ), ( c1 * s2 * s3 - c3 * s1 ) };
const glm::vec3 v { ( c3 * s1 * s2 - c1 * s3 ), ( c2 * c3 ), ( c1 * c3 * s2 + s1 * s3 ) };
const glm::vec3 w { ( c2 * s1 ), ( -s2 ), ( c1 * c2 ) };
view_matrix = glm::mat4 { 1.0f };
view_matrix[ 0 ][ 0 ] = u.x;
view_matrix[ 1 ][ 0 ] = u.y;
view_matrix[ 2 ][ 0 ] = u.z;
view_matrix[ 0 ][ 1 ] = v.x;
view_matrix[ 1 ][ 1 ] = v.y;
view_matrix[ 2 ][ 1 ] = v.z;
view_matrix[ 0 ][ 2 ] = w.x;
view_matrix[ 1 ][ 2 ] = w.y;
view_matrix[ 2 ][ 2 ] = w.z;
view_matrix[ 3 ][ 0 ] = -glm::dot( u, position );
view_matrix[ 3 ][ 1 ] = -glm::dot( v, position );
view_matrix[ 3 ][ 2 ] = -glm::dot( w, position );
inverse_view_matrix = glm::mat4 { 1.0f };
inverse_view_matrix[ 0 ][ 0 ] = u.x;
inverse_view_matrix[ 0 ][ 1 ] = u.y;
inverse_view_matrix[ 0 ][ 2 ] = u.z;
inverse_view_matrix[ 1 ][ 0 ] = v.x;
inverse_view_matrix[ 1 ][ 1 ] = v.y;
inverse_view_matrix[ 1 ][ 2 ] = v.z;
inverse_view_matrix[ 2 ][ 0 ] = w.x;
inverse_view_matrix[ 2 ][ 1 ] = w.y;
inverse_view_matrix[ 2 ][ 2 ] = w.z;
inverse_view_matrix[ 3 ][ 0 ] = position.x;
inverse_view_matrix[ 3 ][ 1 ] = position.y;
inverse_view_matrix[ 3 ][ 2 ] = position.z;
frustum = base_frustum * view_matrix;
}
Frustum
createFrustum( const Camera& camera, const float aspect, const float fov_y, const float near, const float far )
{
Plane near_plane { camera.getForward(), near };
Plane far_plane { camera.getBackward(), far };
const float half_width { near * glm::tan( fov_y / 2.0f ) }; // halfHSide
const float half_height { half_width / aspect }; //halfVSide
constexpr glm::vec3 ZERO { 0.0f, 0.0f, 0.0f };
const auto far_forward { camera.getForward() * far };
//top_dir is the direction pointing at the highest point on the far plane
const auto far_up { camera.getUp() * half_height };
const glm::vec3 top_dir { glm::normalize( far_up + far_forward ) };
Plane top_plane { glm::cross( top_dir, camera.getUp() ), 0.0f };
Plane bottom_plane { glm::cross( top_dir, camera.getDown() ), 0.0f };
const glm::vec3 right_dir { glm::normalize( camera.getRight() * half_width + far_forward ) };
Plane right_plane { glm::cross( right_dir, camera.getRight() ), 0.0f };
Plane left_plane { glm::cross( right_dir, camera.getLeft() ), 0.0f };
return { near_plane, far_plane, top_plane, bottom_plane, right_plane, left_plane };
}
} // namespace fgl::engine

View File

@@ -8,29 +8,70 @@
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include "engine/coordinates/WorldCoordinate.hpp"
namespace fgl::engine
{
constexpr static auto WORLD_UP { glm::vec3 { 0.0f, 1.0f, 0.0f } };
class Camera;
Frustum
createFrustum( const Camera& camera, const float aspect, const float fovy, const float near, const float far );
class Camera
{
glm::mat4 projection_matrix { 1.0f };
glm::mat4 view_matrix { 1.0f };
glm::mat4 inverse_view_matrix { 1.0f };
//! 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
Frustum base_frustum {};
Frustum frustum {};
friend Frustum createFrustum(
const Camera& camera, const float aspect, const float fovy, const float near, const float far );
public:
//! Returns the frustum of the camera in world space
const Frustum& getFrustumBounds() const { return frustum; }
const glm::mat4& getProjectionMatrix() const { return projection_matrix; }
const glm::mat4& getViewMatrix() const { return view_matrix; }
const glm::mat4& getInverseView() const { return inverse_view_matrix; }
const glm::mat4 getProjectionViewMatrix() const { return projection_matrix * view_matrix; }
void setOrthographicProjection( float left, float right, float top, float bottom, float near, float far );
void setPerspectiveProjection( float fovy, float aspect, float near, float far );
const glm::vec3 getPosition() const { return glm::vec3( inverse_view_matrix[ 3 ] ); }
const glm::vec3 getPosition() const { return glm::vec3( -view_matrix[ 3 ] ); }
void setViewDirection( glm::vec3 pos, glm::vec3 direction, glm::vec3 up = glm::vec3 { 0.0f, -1.0f, 0.0f } );
void setViewTarget( glm::vec3 pos, glm::vec3 target, glm::vec3 up = glm::vec3 { 0.0f, -1.0f, 0.0f } );
const glm::vec3 getUp() const
{
return glm::normalize( glm::vec3( view_matrix[ 0 ][ 1 ], view_matrix[ 1 ][ 1 ], view_matrix[ 2 ][ 1 ] ) );
}
const glm::vec3 getRight() const
{
return glm::normalize( glm::vec3( view_matrix[ 0 ][ 0 ], view_matrix[ 1 ][ 0 ], view_matrix[ 2 ][ 0 ] ) );
}
const glm::vec3 getForward() const
{
return glm::normalize( glm::vec3( view_matrix[ 0 ][ 2 ], view_matrix[ 1 ][ 2 ], view_matrix[ 2 ][ 2 ] ) );
}
const glm::vec3 getLeft() const { return -getRight(); }
const glm::vec3 getBackward() const { return -getForward(); }
const glm::vec3 getDown() const { return -getUp(); }
void setViewDirection( glm::vec3 pos, glm::vec3 direction, glm::vec3 up = WORLD_UP );
void setViewTarget( glm::vec3 pos, glm::vec3 target, glm::vec3 up = WORLD_UP );
void setViewYXZ( glm::vec3 pos, glm::vec3 rotation );
};

View File

@@ -27,6 +27,7 @@
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wconversion"
#include "engine/debug/drawers.hpp"
#include "imgui/imgui.h"
#include "imgui/imgui_impl_glfw.h"
#include "imgui/imgui_impl_vulkan.h"
@@ -104,6 +105,10 @@ namespace fgl::engine
auto previous_frame_start { std::chrono::high_resolution_clock::now() };
//camera.setOrthographicProjection( -aspect, aspect, -1, 1, -1, 1 );
const float aspect { m_renderer.getAspectRatio() };
camera.setPerspectiveProjection( glm::radians( 50.0f ), aspect, 0.1f, 100.f );
while ( !m_window.shouldClose() )
{
ZoneScopedN( "Poll" );
@@ -127,20 +132,25 @@ namespace fgl::engine
current_time = new_time;
delta_time = glm::min( delta_time, MAX_DELTA_TIME );
#if ENABLE_IMGUI
{
ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
}
#endif
camera_controller.moveInPlaneXZ( m_window.window(), delta_time, viewer );
camera.setViewYXZ( viewer.transform.translation, viewer.transform.rotation );
const float aspect { m_renderer.getAspectRatio() };
//camera.setOrthographicProjection( -aspect, aspect, -1, 1, -1, 1 );
camera.setPerspectiveProjection( glm::radians( 50.0f ), aspect, 0.1f, 100.f );
if ( auto command_buffer = m_renderer.beginFrame(); command_buffer )
{
ZoneScopedN( "Render" );
//Update
const std::uint16_t frame_index { m_renderer.getFrameIndex() };
const auto view_frustum { camera.getFrustumBounds() };
FrameInfo frame_info { frame_index,
delta_time,
command_buffer,
@@ -150,177 +160,184 @@ namespace fgl::engine
m_renderer.getCurrentTracyCTX(),
matrix_info_buffers[ frame_index ],
draw_parameter_buffers[ frame_index ],
m_renderer.getGBufferDescriptor( frame_index ) };
m_renderer.getGBufferDescriptor( frame_index ),
view_frustum };
#if TRACY_ENABLE
auto& tracy_ctx { frame_info.tracy_ctx };
#endif
CameraInfo current_camera_info { .projection = camera.getProjectionMatrix(),
.view = camera.getViewMatrix(),
.inverse_view = camera.getInverseView() };
.view = camera.getViewMatrix() };
camera_info[ frame_index ] = current_camera_info;
#if ENABLE_IMGUI
{
ZoneScopedN( "ImGui recording" );
ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
ImGui::Begin( "Titor Dev Menu" );
ImGui::Text( "Framerate" );
ImGui::SameLine();
ImGui::Text( "%.1f FPS", ImGui::GetIO().Framerate );
ImGui::Text( "Frame Time" );
ImGui::SameLine();
ImGui::Text( "%.3f ms", 1000.0f / ImGui::GetIO().Framerate );
ImGui::Text( "Average rolling frametime: %.3f ms", rolling_ms_average.average() );
if ( ImGui::CollapsingHeader( "Camera" ) )
{
ImGui::Begin( "Titor Dev Menu" );
ImGui::Text( "Framerate" );
ImGui::PushItemWidth( 80 );
ImGui::DragFloat( "Pos X", &viewer.transform.translation.x, 0.1f );
ImGui::SameLine();
ImGui::Text( "%.1f FPS", ImGui::GetIO().Framerate );
ImGui::Text( "Frame Time" );
ImGui::DragFloat( "Pos Y", &viewer.transform.translation.y, 0.1f );
ImGui::SameLine();
ImGui::Text( "%.3f ms", 1000.0f / ImGui::GetIO().Framerate );
ImGui::Text( "Average rolling frametime: %.3f ms", rolling_ms_average.average() );
ImGui::DragFloat( "Pos Z", &viewer.transform.translation.z, 0.1f );
ImGui::PopItemWidth();
if ( ImGui::CollapsingHeader( "Camera" ) )
ImGui::Separator();
ImGui::PushItemWidth( 80 );
ImGui::DragFloat( "Rot X", &viewer.transform.rotation.x, 0.1f, 0.0f, glm::two_pi< float >() );
ImGui::SameLine();
ImGui::DragFloat( "Rot Y", &viewer.transform.rotation.y, 0.1f, 0.0f, glm::two_pi< float >() );
ImGui::SameLine();
ImGui::DragFloat( "Rot Z", &viewer.transform.rotation.z, 0.1f, 0.0f, glm::two_pi< float >() );
ImGui::PopItemWidth();
}
if ( ImGui::CollapsingHeader( "View Frustum" ) )
{
const auto& frustum { camera.getFrustumBounds() };
auto printVec3 = []( const glm::vec3& vec )
{ ImGui::Text( "(%.2f, %.2f, %.2f)", vec.x, vec.y, vec.z ); };
auto printPlane = [ printVec3 ]( const Plane& plane, const std::string name )
{
ImGui::PushItemWidth( 80 );
ImGui::DragFloat( "Pos X", &viewer.transform.translation.x, 0.1f );
ImGui::SameLine();
ImGui::DragFloat( "Pos Y", &viewer.transform.translation.y, 0.1f );
ImGui::SameLine();
ImGui::DragFloat( "Pos Z", &viewer.transform.translation.z, 0.1f );
ImGui::PopItemWidth();
const std::string name_str { "Plane " + name + ": " };
ImGui::Separator();
ImGui::PushItemWidth( 80 );
ImGui::
DragFloat( "Rot X", &viewer.transform.rotation.x, 0.1f, 0.0f, glm::two_pi< float >() );
ImGui::Text( name_str.c_str() );
ImGui::SameLine( 120.0f );
printVec3( plane.direction() );
ImGui::SameLine();
ImGui::
DragFloat( "Rot Y", &viewer.transform.rotation.y, 0.1f, 0.0f, glm::two_pi< float >() );
ImGui::SameLine();
ImGui::
DragFloat( "Rot Z", &viewer.transform.rotation.z, 0.1f, 0.0f, glm::two_pi< float >() );
ImGui::PopItemWidth();
}
ImGui::Text( "Distance: %.6f", plane.distance() );
};
if ( ImGui::CollapsingHeader( "Models" ) )
printPlane( frustum.near, "Near" );
printPlane( frustum.far, "Far" );
printPlane( frustum.top, "Top" );
printPlane( frustum.bottom, "Bottom" );
printPlane( frustum.right, "Right" );
printPlane( frustum.left, "Left" );
}
if ( ImGui::CollapsingHeader( "Models" ) )
{
for ( auto& [ id, game_object ] : game_objects )
{
for ( auto& [ id, game_object ] : game_objects )
if ( game_object.model == nullptr ) continue;
ImGui::PushID( std::to_string( id ).c_str() );
if ( ImGui::TreeNode( game_object.model->getName().c_str() ) )
{
if ( game_object.model == nullptr ) continue;
ImGui::PushID( std::to_string( id ).c_str() );
if ( ImGui::TreeNode( game_object.model->getName().c_str() ) )
ImGui::PushID( game_object.model->getName().c_str() );
{
ImGui::PushID( game_object.model->getName().c_str() );
ImGui::PushID( "Position" );
ImGui::PushItemWidth( 80 );
ImGui::Text( "Position" );
ImGui::SameLine();
ImGui::DragFloat( "X", &game_object.transform.translation.x, 0.1f );
ImGui::SameLine();
ImGui::DragFloat( "Y", &game_object.transform.translation.y, 0.1f );
ImGui::SameLine();
ImGui::DragFloat( "Z", &game_object.transform.translation.z, 0.1f );
ImGui::PopID();
}
ImGui::Separator();
{
ImGui::PushID( "Rotation" );
ImGui::PushItemWidth( 80 );
ImGui::Text( "Rotation" );
ImGui::SameLine();
ImGui::DragFloat(
"X", &game_object.transform.rotation.x, 0.1f, 0.0f, glm::two_pi< float >() );
ImGui::SameLine();
ImGui::DragFloat(
"Y", &game_object.transform.rotation.y, 0.1f, 0.0f, glm::two_pi< float >() );
ImGui::SameLine();
ImGui::DragFloat(
"Z", &game_object.transform.rotation.z, 0.1f, 0.0f, glm::two_pi< float >() );
ImGui::PopID();
}
ImGui::Separator();
{
ImGui::PushID( "Scale" );
ImGui::PushItemWidth( 80 );
ImGui::Text( "Scale" );
ImGui::SameLine();
ImGui::DragFloat( "X", &game_object.transform.scale.x, 0.1f );
ImGui::SameLine();
ImGui::DragFloat( "Y", &game_object.transform.scale.y, 0.1f );
ImGui::SameLine();
ImGui::DragFloat( "Z", &game_object.transform.scale.z, 0.1f );
ImGui::TreePop();
ImGui::PopID();
}
if ( ImGui::CollapsingHeader( "Textures" ) )
{
std::vector< TextureID > textures;
ImGui::PushID( "Textures" );
for ( auto& primitive : game_object.model->m_primitives )
{
ImGui::PushID( "Position" );
ImGui::PushItemWidth( 80 );
ImGui::Text( "Position" );
ImGui::SameLine();
ImGui::DragFloat( "X", &game_object.transform.translation.x, 0.1f );
ImGui::SameLine();
ImGui::DragFloat( "Y", &game_object.transform.translation.y, 0.1f );
ImGui::SameLine();
ImGui::DragFloat( "Z", &game_object.transform.translation.z, 0.1f );
ImGui::PopID();
}
if ( !primitive.m_texture.has_value() ) continue;
ImGui::Separator();
auto& texture { primitive.m_texture.value() };
{
ImGui::PushID( "Rotation" );
ImGui::PushItemWidth( 80 );
ImGui::Text( "Rotation" );
ImGui::SameLine();
ImGui::DragFloat(
"X",
&game_object.transform.rotation.x,
0.1f,
0.0f,
glm::two_pi< float >() );
ImGui::SameLine();
ImGui::DragFloat(
"Y",
&game_object.transform.rotation.y,
0.1f,
0.0f,
glm::two_pi< float >() );
ImGui::SameLine();
ImGui::DragFloat(
"Z",
&game_object.transform.rotation.z,
0.1f,
0.0f,
glm::two_pi< float >() );
ImGui::PopID();
}
const auto& extent { texture.getExtent() };
ImGui::Separator();
auto& image_view { texture.getImageView() };
auto& sampler { image_view.getSampler() };
{
ImGui::PushID( "Scale" );
ImGui::PushItemWidth( 80 );
ImGui::Text( "Scale" );
ImGui::SameLine();
ImGui::DragFloat( "X", &game_object.transform.scale.x, 0.1f );
ImGui::SameLine();
ImGui::DragFloat( "Y", &game_object.transform.scale.y, 0.1f );
ImGui::SameLine();
ImGui::DragFloat( "Z", &game_object.transform.scale.z, 0.1f );
ImGui::TreePop();
ImGui::PopID();
}
if ( !sampler.has_value() ) continue;
if ( ImGui::CollapsingHeader( "Textures" ) )
{
std::vector< TextureID > textures;
ImVec2 size;
size.x = extent.width;
size.y = extent.height;
ImGui::PushID( "Textures" );
for ( auto& primitive : game_object.model->m_primitives )
if ( std::find( textures.begin(), textures.end(), texture.getID() )
== textures.end() )
{
if ( !primitive.m_texture.has_value() ) continue;
textures.emplace_back( texture.getID() );
auto& texture { primitive.m_texture.value() };
const auto& extent { texture.getExtent() };
auto& image_view { texture.getImageView() };
auto& sampler { image_view.getSampler() };
if ( !sampler.has_value() ) continue;
ImVec2 size;
size.x = extent.width;
size.y = extent.height;
if ( std::find( textures.begin(), textures.end(), texture.getID() )
== textures.end() )
{
textures.emplace_back( texture.getID() );
ImGui::Image(
static_cast< ImTextureID >( primitive.m_texture
->getImGuiDescriptorSet() ),
size );
}
ImGui::Image(
static_cast< ImTextureID >( primitive.m_texture
->getImGuiDescriptorSet() ),
size );
}
ImGui::PopID();
}
ImGui::PopID();
}
ImGui::PopID();
}
ImGui::PopID();
}
}
//TODO: Add in a collapsable header to view all buffers, And their suballocations
/*
//TODO: Add in a collapsable header to view all buffers, And their suballocations
/*
if ( ImGui::CollapsingHeader( "Buffer allocations" ) )
{
for ( const auto& buffer : Buffer::getActiveBufferHandles() )
@@ -329,14 +346,7 @@ namespace fgl::engine
ImGui::Text( "Size: %zu", buffer.lock()->size() );
}
}*/
ImGui::End();
}
//Render
ImGui::Render();
}
ImDrawData* data { ImGui::GetDrawData() };
#endif
m_renderer.beginSwapchainRendererPass( command_buffer );
@@ -348,6 +358,13 @@ namespace fgl::engine
#if TRACY_ENABLE
TracyVkZone( tracy_ctx, command_buffer, "ImGui Rendering" );
#endif
debug::world::drawPointText( { 0.0f, 0.0f, 0.0f }, camera, { 1.0f, 0.0f, 0.0f } );
ImGui::End();
ImGui::Render();
ImDrawData* data { ImGui::GetDrawData() };
ImGui_ImplVulkan_RenderDrawData( data, command_buffer );
}
#endif
@@ -359,6 +376,9 @@ namespace fgl::engine
#endif
m_renderer.endFrame();
std::this_thread::sleep_until( new_time + std::chrono::milliseconds( 16 ) );
FrameMark;
}
}
@@ -398,9 +418,9 @@ namespace fgl::engine
m_entity_renderer.getVertexBuffer(),
m_entity_renderer.getIndexBuffer() ) };
for ( int x = 0; x < 4; ++x )
for ( int x = 0; x < 1; ++x )
{
for ( int y = 0; y < 4; ++y )
for ( int y = 0; y < 1; ++y )
{
auto sponza = GameObject::createGameObject();
sponza.model = model;

View File

@@ -9,10 +9,10 @@
#include "Device.hpp"
#include "GameObject.hpp"
#include "Model.hpp"
#include "Renderer.hpp"
#include "Window.hpp"
#include "engine/descriptors/DescriptorPool.hpp"
#include "engine/model/Model.hpp"
#include "engine/systems/EntityRendererSystem.hpp"
namespace fgl::engine

View File

@@ -32,7 +32,6 @@ namespace fgl::engine
{
glm::mat4 projection { 1.0f };
glm::mat4 view { 1.0f };
glm::mat4 inverse_view { 1.0f };
glm::vec4 ambient_light_color { 1.0f, 1.0f, 1.0f, 0.02f };
};
@@ -79,6 +78,8 @@ namespace fgl::engine
Buffer& draw_parameter_buffer;
DescriptorSet& gbuffer_descriptor_set;
const Frustum& camera_frustum;
};
} // namespace fgl::engine

View File

@@ -0,0 +1,49 @@
//
// Created by kj16609 on 1/27/24.
//
#include "WorldCoordinate.hpp"
namespace fgl::engine
{
double Plane::distanceFrom( const Coordinate& coord ) const
{
return -( glm::dot( coord.position, m_direction ) - m_distance );
}
bool Plane::isForward( const Coordinate& coord ) const
{
return distanceFrom( coord ) > 0.0;
}
bool Plane::isBehind( const Coordinate& coord ) const
{
return !isForward( coord );
}
Plane Plane::operator*( glm::mat4 matrix ) const
{
assert( m_distance != std::numeric_limits< float >::max() );
assert( m_direction != DEFAULT_COORDINATE_VEC3 );
Plane result = *this;
const glm::vec3 new_direction { matrix * glm::vec4( m_direction, 1.0f ) };
const auto new_distance { glm::dot( new_direction, m_direction ) + m_distance };
result.m_direction = glm::normalize( new_direction );
result.m_distance = new_distance;
return result;
}
bool Frustum::pointInside( const Coordinate& coord ) const
{
// clang-format off
return
near.isForward( coord ) && far.isForward( coord )
&& top.isForward( coord ) && bottom.isForward( coord )
&& right.isForward( coord ) && left.isForward( coord );
// clang-format on
}
} // namespace fgl::engine

View File

@@ -0,0 +1,129 @@
//
// Created by kj16609 on 1/26/24.
//
#pragma once
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
namespace fgl::engine
{
constexpr static auto DEFAULT_COORDINATE_VEC3 { glm::vec3( std::numeric_limits< float >::max() ) };
struct Coordinate
{
glm::vec3 position { DEFAULT_COORDINATE_VEC3 };
Coordinate() = default;
Coordinate( glm::vec3 position ) : position( position ) {}
Coordinate( const Coordinate& other ) = default;
Coordinate( Coordinate&& other ) : position( std::move( other.position ) )
{
other.position = DEFAULT_COORDINATE_VEC3;
}
};
class Plane
{
float m_distance { std::numeric_limits< float >::max() };
glm::vec3 m_direction { DEFAULT_COORDINATE_VEC3 };
public:
bool valid() const
{
return m_distance != std::numeric_limits< float >::max() && m_direction != DEFAULT_COORDINATE_VEC3;
}
Plane( const glm::vec3 vector, const float distance ) : m_distance( distance ), m_direction( vector ) {}
Plane( const glm::vec3 normal, const glm::vec3 point ) :
Plane( glm::normalize( normal ), glm::dot( glm::normalize( normal ), point ) )
{}
Plane() = default;
Plane operator*( glm::mat4 matrix ) const;
//! Returns the closest point on the plane to the 0,0,0 origin
glm::vec3 getPosition() const
{
assert( m_distance != std::numeric_limits< float >::max() );
assert( m_direction != DEFAULT_COORDINATE_VEC3 );
return m_direction * m_distance;
}
bool isForward( const Coordinate& coord ) const;
bool isBehind( const Coordinate& coord ) const;
//! Returns the distance from a point to the plane. Negative if behind, positive if in front
double distanceFrom( const Coordinate& coord ) const;
glm::vec3 direction() const { return m_direction; }
float distance() const { return m_distance; }
};
struct Frustum
{
Plane near;
Plane far;
Plane top;
Plane bottom;
Plane right;
Plane left;
friend class Camera;
public:
Frustum() = default;
Frustum(
const Plane near_plane,
const Plane far_plane,
const Plane top_plane,
const Plane bottom_plane,
const Plane right_plane,
const Plane left_plane ) :
near( near_plane ),
far( far_plane ),
top( top_plane ),
bottom( bottom_plane ),
right( right_plane ),
left( left_plane )
{
assert( near.valid() );
assert( far.valid() );
assert( top.valid() );
assert( bottom.valid() );
assert( right.valid() );
assert( left.valid() );
assert( right_plane.direction() != left_plane.direction() );
assert( top_plane.direction() != bottom_plane.direction() );
assert( near_plane.direction() != far_plane.direction() );
}
Frustum operator*( glm::mat4 matrix ) const
{
Frustum result = *this;
result.near = near * matrix;
result.far = far * matrix;
result.top = top * matrix;
result.bottom = bottom * matrix;
result.right = right * matrix;
result.left = left * matrix;
return result;
}
bool pointInside( const Coordinate& coord ) const;
};
} // namespace fgl::engine

View File

@@ -0,0 +1,232 @@
//
// Created by kj16609 on 1/27/24.
//
#include "BoundingBox.hpp"
#include <array>
#include "engine/coordinates/WorldCoordinate.hpp"
namespace fgl::engine
{
bool engine::BoundingBox::isInFrustum( const Frustum& frustum ) const
{
ZoneScoped;
const auto points { this->points() };
for ( const auto& point : points )
{
if ( frustum.pointInside( point ) ) return true;
}
return false;
}
consteval std::array< std::uint32_t, BoundingBox::indicies_count > BoundingBox::triangleIndicies()
{
/**
* Order (Top)
* 1 =========== 0
* || ||
* || ||
* 2 =========== 3
*
* Order (Bottom)
* 5 =========== 4
* || ||
* || ||
* 6 =========== 7
*
* Order (Side - 1)
* 2 =========== 3
* || ||
* || ||
* 6 =========== 7
*
* Order (Side - 2)
* 1 =========== 0
* || ||
* || ||
* 5 =========== 4
*
* Order (Side - 3)
* 3 =========== 0
* || ||
* || ||
* 7 =========== 4
*
* Order (Side - 4)
* 2 =========== 1
* || ||
* || ||
* 6 =========== 5
*/
// clang-format off
std::array< std::uint32_t, indicies_count > data {
//Top tris
0, 1, 2,
1, 2, 3,
//Bottom tris
4, 5, 6,
5, 6, 7,
//Side 1
2, 3, 6,
3, 6, 7,
//Side 2
1, 0, 5,
0, 5, 4,
//Side 3
3, 0, 7,
0, 7, 4,
//Side 4
2, 1, 6,
1, 6, 5
};
// clang-format on
return data;
}
std::vector< glm::vec3 > BoundingBox::points() const
{
assert( middle != DEFAULT_COORDINATE_VEC3 );
assert( scale != glm::vec3( 0.0f ) );
std::vector< glm::vec3 > points;
// xp == x positive (Highest x point)
// xn == x negative (Lowest x point)
const glm::vec3 xp_yp_zp { middle + scale };
const glm::vec3 xn_yn_zn { middle - scale };
const auto xn { xn_yn_zn.x };
const auto yn { xn_yn_zn.y };
const auto zn { xn_yn_zn.z };
const auto xp { xp_yp_zp.x };
const auto yp { xp_yp_zp.y };
const auto zp { xp_yp_zp.z };
//Top
const glm::vec3 xn_yp_zp { xn, yp, zp }; // (- + +)
const glm::vec3 xn_yp_zn { xn, yp, zn }; // (- + -)
const glm::vec3 xp_yp_zn { xp, yp, zn }; // (+ + -)
/*
* Top-Down view (X,Y,Z)
* (-,+,+) =========== (+,+,+)
* || ||
* || ||
* (-,+,-) =========== (+,+,-)
*
* Order (Top)
* 1 =========== 0
* || ||
* || ||
* 2 =========== 3
*
* Order (Bottom)
* 5 =========== 4
* || ||
* || ||
* 6 =========== 7
*/
points.resize( 8 );
points[ 0 ] = xp_yp_zp;
points[ 1 ] = xn_yp_zp;
points[ 2 ] = xn_yp_zn;
points[ 3 ] = xp_yp_zn;
//Bottom
const glm::vec3 xn_yn_zp { xn, yn, zp }; // (- - +)
const glm::vec3 xp_yn_zn { xp, yn, zn }; // (+ - -)
const glm::vec3 xp_yn_zp { xp, yn, zp }; // (+ - +)
/*
* Bottom-Top view (X,Y,Z)
* (-,-,+) =========== (+,-,+)
* || ||
* || ||
* (-,-,-) =========== (+,-,-)
*/
points[ 4 ] = xp_yn_zp;
points[ 5 ] = xn_yn_zp;
points[ 6 ] = xn_yn_zn;
points[ 7 ] = xp_yn_zn;
return points;
}
BoundingBox BoundingBox::combine( const BoundingBox& other ) const
{
ZoneScoped;
if ( middle == DEFAULT_COORDINATE_VEC3 )
return other;
else
{
const auto& other_points { other.points() };
std::vector< glm::vec3 > points { this->points() };
points.insert( points.end(), other_points.begin(), other_points.end() );
//TODO: There might be a way to do this without needing to do yet another point calculation.
return generateBoundingFromPoints( points );
}
}
BoundingBox BoundingBox::operator*( const glm::mat4 matrix ) const
{
ZoneScoped;
const glm::vec3 new_middle { matrix * glm::vec4( middle, 1.0f ) };
const glm::vec3 new_scale { matrix * glm::vec4( scale, 0.0f ) };
return { new_middle, new_scale };
}
std::vector< std::pair< glm::vec3, glm::vec3 > > BoundingBox::lines() const
{
const auto points { this->points() };
std::vector< std::pair< glm::vec3, glm::vec3 > > lines;
for ( std::uint32_t i = 0; i < points.size() - 1; ++i )
{
lines.emplace_back( points[ i ], points[ i + 1 ] );
}
return lines;
}
BoundingBox generateBoundingFromPoints( std::vector< glm::vec3 >& points )
{
ZoneScoped;
assert( points.size() > 0 );
// neg (min)
glm::vec3 top_left_front { points[ 0 ] };
// pos (max)
glm::vec3 bottom_right_back { points[ 0 ] };
for ( const auto& pos : points )
{
top_left_front.x = std::min( pos.x, top_left_front.x );
top_left_front.y = std::min( pos.y, top_left_front.y );
top_left_front.z = std::min( pos.z, top_left_front.z );
bottom_right_back.x = std::max( pos.x, bottom_right_back.x );
bottom_right_back.y = std::max( pos.y, bottom_right_back.y );
bottom_right_back.z = std::max( pos.z, bottom_right_back.z );
}
//Calculate midpoint
const glm::vec3 midpoint { ( top_left_front + bottom_right_back ) / glm::vec3( 2.0f ) };
const glm::vec3 scale { bottom_right_back - midpoint };
std::cout << "Generated bounding box from " << points.size() << "points. Output:\n\tMidpoint:" << midpoint.x
<< " " << midpoint.y << " " << midpoint.z << "\n\tScale:" << scale.x << " " << scale.y << " "
<< scale.z << std::endl;
return { midpoint, scale };
}
} // namespace fgl::engine

View File

@@ -0,0 +1,46 @@
//
// Created by kj16609 on 1/27/24.
//
#pragma once
#include <glm/vec3.hpp>
#include <array>
#include <vector>
#include "engine/coordinates/WorldCoordinate.hpp"
namespace fgl::engine
{
class Frustum;
struct BoundingBox
{
glm::vec3 middle { DEFAULT_COORDINATE_VEC3 };
glm::vec3 scale { 0.0f };
//! Returns the top left (-x, -y, -z) coordinate
inline glm::vec3 topLeftFront() const { return middle - scale; }
//! Returns the bottom right (x, y, z) coordinate
inline glm::vec3 bottomRightBack() const { return middle + scale; }
// 6 sides, 2 triangles each, 3 verts per triangle
constexpr static std::uint32_t indicies_count { 6 * 2 * 3 };
consteval static std::array< std::uint32_t, indicies_count > triangleIndicies();
std::vector< glm::vec3 > points() const;
std::vector< std::pair< glm::vec3, glm::vec3 > > lines() const;
bool isInFrustum( const Frustum& frustum ) const;
BoundingBox combine( const BoundingBox& other ) const;
BoundingBox operator*( glm::mat4 matrix ) const;
};
BoundingBox generateBoundingFromPoints( std::vector< glm::vec3 >& points );
} // namespace fgl::engine

View File

@@ -28,7 +28,7 @@
#include "objectloaders/tiny_obj_loader.h"
#pragma GCC diagnostic pop
#include "utils.hpp"
#include "engine/utils.hpp"
namespace std
{
@@ -69,6 +69,19 @@ namespace fgl::engine
return draw_parameters;
}
BoundingBox Model::buildBoundingBox( const std::vector< Primitive >& primitives )
{
//TODO:
BoundingBox box;
for ( const auto& primitive : primitives )
{
box = box.combine( primitive.m_bounding_box );
}
return box;
}
std::vector< vk::DrawIndexedIndirectCommand > Model::getDrawCommand( const std::uint32_t index ) const
{
std::vector< vk::DrawIndexedIndirectCommand > draw_commands;
@@ -84,20 +97,25 @@ namespace fgl::engine
return draw_commands;
}
Model::Model( Device& device, Builder& builder ) :
Model::Model( Device& device, ModelBuilder& builder, const BoundingBox bounding_box ) :
m_device( device ),
m_draw_parameters( buildParameters( builder.m_primitives ) )
m_draw_parameters( buildParameters( builder.m_primitives ) ),
m_bounding_box( bounding_box )
{
assert( bounding_box.middle != DEFAULT_COORDINATE_VEC3 );
m_primitives = std::move( builder.m_primitives );
}
std::unique_ptr< Model > Model::
createModel( Device& device, const std::filesystem::path& path, Buffer& vertex_buffer, Buffer& index_buffer )
{
Builder builder { vertex_buffer, index_buffer };
ModelBuilder builder { vertex_buffer, index_buffer };
builder.loadModel( path );
return std::make_unique< Model >( device, builder );
//Calculate bounding box
BoundingBox bounding_box { buildBoundingBox( builder.m_primitives ) };
return std::make_unique< Model >( device, builder, bounding_box );
}
void Model::syncBuffers( vk::CommandBuffer& cmd_buffer )
@@ -141,7 +159,7 @@ namespace fgl::engine
return attribute_descriptions;
}
void Model::Builder::loadModel( const std::filesystem::path& filepath )
void ModelBuilder::loadModel( const std::filesystem::path& filepath )
{
if ( filepath.extension() == ".obj" )
{
@@ -220,7 +238,7 @@ namespace fgl::engine
}
};
void Model::Builder::loadGltf( const std::filesystem::path& filepath )
void ModelBuilder::loadGltf( const std::filesystem::path& filepath )
{
std::cout << "Loading gltf model " << filepath << std::endl;
@@ -244,6 +262,8 @@ namespace fgl::engine
for ( const tinygltf::Mesh& mesh : model.meshes )
{
std::vector< glm::vec3 > model_positions;
for ( const tinygltf::Primitive& primitive : mesh.primitives )
{
//TODO: Implement modes
@@ -279,6 +299,9 @@ namespace fgl::engine
//Load positions
auto& position_accessor { model.accessors.at( primitive.attributes.at( "POSITION" ) ) };
std::vector< glm::vec3 > position_data { extractData< glm::vec3 >( model, position_accessor ) };
model_positions.insert( model_positions.end(), position_data.begin(), position_data.end() );
BoundingBox bounding_box { generateBoundingFromPoints( position_data ) };
std::vector< glm::vec3 > normals;
@@ -399,7 +422,9 @@ namespace fgl::engine
Device::getInstance().endSingleTimeCommands( cmd );
tex.dropStaging();
Primitive prim { std::move( vertex_buffer ), std::move( index_buffer ), std::move( tex ) };
Primitive prim {
std::move( vertex_buffer ), std::move( index_buffer ), bounding_box, std::move( tex )
};
m_primitives.emplace_back( std::move( prim ) );
@@ -409,7 +434,7 @@ namespace fgl::engine
else
std::cout << "No material" << std::endl;
Primitive prim { std::move( vertex_buffer ), std::move( index_buffer ) };
Primitive prim { std::move( vertex_buffer ), std::move( index_buffer ), bounding_box };
m_primitives.emplace_back( std::move( prim ) );
}
@@ -433,7 +458,7 @@ namespace fgl::engine
std::cout << "Meshes: " << model.meshes.size() << std::endl;
}
void Model::Builder::loadObj( const std::filesystem::path& filepath )
void ModelBuilder::loadObj( const std::filesystem::path& filepath )
{
m_primitives.clear();
@@ -507,9 +532,18 @@ namespace fgl::engine
}
}
std::vector< glm::vec3 > vert_pos;
for ( const auto& vert : verts )
{
vert_pos.emplace_back( vert.m_position );
}
BoundingBox bounding_box { generateBoundingFromPoints( vert_pos ) };
m_primitives.emplace_back(
VertexBufferSuballocation( m_vertex_buffer, std::move( verts ) ),
IndexBufferSuballocation( m_index_buffer, std::move( indicies ) ) );
IndexBufferSuballocation( m_index_buffer, std::move( indicies ) ),
bounding_box );
std::cout << unique_verts.size() << " unique verts" << std::endl;
}

View File

@@ -14,13 +14,14 @@
#include <optional>
#include <vector>
#include "Device.hpp"
#include "BoundingBox.hpp"
#include "engine/Device.hpp"
#include "engine/buffers/Buffer.hpp"
#include "engine/buffers/BufferSuballocation.hpp"
#include "engine/buffers/vector/DeviceVector.hpp"
#include "engine/buffers/vector/HostVector.hpp"
#include "engine/texture/Texture.hpp"
#include "utils.hpp"
#include "engine/utils.hpp"
namespace fgl::engine
{
@@ -62,18 +63,27 @@ namespace fgl::engine
{
VertexBufferSuballocation m_vertex_buffer;
IndexBufferSuballocation m_index_buffer;
BoundingBox m_bounding_box;
std::optional< Texture > m_texture { std::nullopt };
Primitive( VertexBufferSuballocation&& vertex_buffer, IndexBufferSuballocation&& index_buffer ) :
Primitive(
VertexBufferSuballocation&& vertex_buffer,
IndexBufferSuballocation&& index_buffer,
BoundingBox& bounding_box ) :
m_vertex_buffer( std::move( vertex_buffer ) ),
m_index_buffer( std::move( index_buffer ) )
m_index_buffer( std::move( index_buffer ) ),
m_bounding_box( bounding_box )
{}
Primitive(
VertexBufferSuballocation&& vertex_buffer, IndexBufferSuballocation&& index_buffer, Texture&& texture ) :
VertexBufferSuballocation&& vertex_buffer,
IndexBufferSuballocation&& index_buffer,
BoundingBox& bounding_box,
Texture&& texture ) :
m_vertex_buffer( std::move( vertex_buffer ) ),
m_index_buffer( std::move( index_buffer ) ),
m_bounding_box( bounding_box ),
m_texture( std::move( texture ) )
{}
@@ -82,39 +92,49 @@ namespace fgl::engine
Primitive( Primitive&& other ) = default;
};
struct ModelBuilder
{
Buffer& m_vertex_buffer;
Buffer& m_index_buffer;
std::vector< ::fgl::engine::Primitive > m_primitives {};
ModelBuilder() = delete;
ModelBuilder( Buffer& parent_vertex_buffer, Buffer& parent_index_buffer ) :
m_vertex_buffer( parent_vertex_buffer ),
m_index_buffer( parent_index_buffer )
{}
void loadModel( const std::filesystem::path& filepath );
void loadObj( const std::filesystem::path& filepath );
void loadGltf( const std::filesystem::path& filepath );
};
class Model
{
Device& m_device;
std::vector< vk::DrawIndexedIndirectCommand > buildParameters( const std::vector< Primitive >& primitives );
static std::vector< vk::DrawIndexedIndirectCommand > buildParameters( const std::vector< Primitive >&
primitives );
static BoundingBox buildBoundingBox( const std::vector< Primitive >& primitives );
std::vector< vk::DrawIndexedIndirectCommand > m_draw_parameters;
std::string m_name { "Unnamed model" };
//! Bounding box of the model
BoundingBox m_bounding_box;
public:
//! Returns the bounding box in model space
const BoundingBox& getBoundingBox() const { return m_bounding_box; }
BoundingBox getBoundingBox( const glm::mat4 matrix ) const { return m_bounding_box * matrix; }
std::vector< ::fgl::engine::Primitive > m_primitives {};
struct Builder
{
Buffer& m_vertex_buffer;
Buffer& m_index_buffer;
std::vector< ::fgl::engine::Primitive > m_primitives {};
Builder() = delete;
Builder( Buffer& parent_vertex_buffer, Buffer& parent_index_buffer ) :
m_vertex_buffer( parent_vertex_buffer ),
m_index_buffer( parent_index_buffer )
{}
void loadModel( const std::filesystem::path& filepath );
void loadObj( const std::filesystem::path& filepath );
void loadGltf( const std::filesystem::path& filepath );
};
std::vector< vk::DrawIndexedIndirectCommand > getDrawCommand( const std::uint32_t index ) const;
static std::unique_ptr< Model > createModel(
@@ -124,7 +144,7 @@ namespace fgl::engine
const std::string& getName() const { return m_name; }
Model( Device& device, Builder& builder );
Model( Device& device, ModelBuilder& builder, const BoundingBox bounding_box );
~Model() = default;

View File

@@ -7,7 +7,7 @@
#include <array>
#include <fstream>
#include "engine/Model.hpp"
#include "engine/model/Model.hpp"
namespace fgl::engine
{

View File

@@ -4,7 +4,7 @@
#include "PipelineConfigInfo.hpp"
#include "engine/Model.hpp"
#include "engine/model/Model.hpp"
namespace fgl::engine
{

View File

@@ -8,6 +8,9 @@
#define GLM_FORCE_DEPTH_ZERO_TO_ON
#include <glm/glm.hpp>
#include <glm/gtc/constants.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/intersect.hpp>
#include <imgui/imgui.h>
#include <tracy/TracyC.h>
#include <vulkan/vulkan.hpp>
@@ -18,6 +21,7 @@
#include <stdexcept>
#include <thread>
#include "engine/debug/drawers.hpp"
#include "engine/literals/size.hpp"
namespace fgl::engine
@@ -94,6 +98,12 @@ namespace fgl::engine
TracyVkZone( info.tracy_ctx, command_buffer, "Render game object" );
if ( obj.model == nullptr ) continue;
const BoundingBox model_bounding_box { obj.model->getBoundingBox( obj.transform.mat4() ) };
debug::world::drawBoundingBox( model_bounding_box, info.camera );
if ( !model_bounding_box.isInFrustum( info.camera_frustum ) ) continue;
for ( const auto& primitive : obj.model->m_primitives )
{
ZoneScopedN( "Queue Primitive" );
@@ -157,6 +167,13 @@ namespace fgl::engine
}
}
if ( draw_pairs.empty() )
{
std::cout << "Nothing to draw!" << std::endl;
command_buffer.nextSubpass( vk::SubpassContents::eInline );
return;
}
std::vector< vk::DrawIndexedIndirectCommand > draw_commands;
std::vector< ModelMatrixInfo > model_matrices;
@@ -172,8 +189,6 @@ namespace fgl::engine
}
TracyCZoneEnd( filter_zone_TRACY );
assert( draw_commands.size() > 0 && "No draw commands to render" );
TracyCZoneN( draw_zone_TRACY, "Submit draw data", true );
auto& draw_parameter_buffer { m_draw_parameter_buffers[ info.frame_idx ] };

View File

@@ -11,8 +11,8 @@
#include "engine/Device.hpp"
#include "engine/FrameInfo.hpp"
#include "engine/GameObject.hpp"
#include "engine/Model.hpp"
#include "engine/SwapChain.hpp"
#include "engine/model/Model.hpp"
#include "engine/pipeline/PipelineT.hpp"
namespace fgl::engine