Get textureless rendering mostly working

This commit is contained in:
2024-05-24 14:09:24 -04:00
parent 8856f33704
commit 68d20153da
59 changed files with 1149 additions and 208 deletions

View File

@@ -1 +1 @@
add_subdirectory(${CMAKE_SOURCE_DIR}/dependencies/spdlog)
add_subdirectory(${CMAKE_SOURCE_DIR}/dependencies/spdlog ${CMAKE_BINARY_DIR}/bin)

View File

@@ -108,9 +108,9 @@
set(FGL_CONFIG "-std=c++23 -fmax-errors=3 -fconcepts-diagnostics-depth=8 -march=native -flto -ftree-vectorize")
if (DEFINED USE_WERROR)
set(FGL_CONFIG "${FGL_CONFIG} -Werror")
endif ()
#if (DEFINED USE_WERROR)
#set(FGL_CONFIG "${FGL_CONFIG} -Werror")
#endif ()
# Safe for debug
# TODO: Figure out LTO with Alaestor's retarded compiler

1
dependencies/spdlog vendored Submodule

Submodule dependencies/spdlog added at c3aed4b683

View File

@@ -48,8 +48,4 @@ void main()
out_albedo = tex_value;
out_position.a = linearDepth(out_position.z);
//out_color = vec4(0.0);
//out_color = vec4(in_tex_coord, 0.0f, 0.0f);
//out_color = texture(tex[0], in_tex_coord);
}

View File

@@ -0,0 +1,41 @@
#version 450
#extension GL_EXT_nonuniform_qualifier: enable
#extension GL_EXT_debug_printf: enable
layout (location = 0) in vec3 in_normal;
layout (location = 1) in vec2 in_tex_coord;
layout (location = 2) in vec3 in_world_pos;
layout (location = 3) in vec3 in_color;
layout (location = 0) out vec4 out_color;
layout (location = 1) out vec4 out_position;
layout (location = 2) out vec4 out_normal;
layout (location = 3) out vec4 out_albedo;
layout (set = 0, binding = 0) uniform CameraInfo {
mat4 projection;
mat4 view;
mat4 inverse_view;
} ubo;
#define NEAR_PLANE 0.01f
#define FAR_PLANE 1000.0f
float linearDepth(float depth)
{
float z = depth * 2.0f - 1.0f;
return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE));
}
void main()
{
out_position = vec4(in_world_pos, 1.0f);
vec3 N = normalize(in_normal);
out_normal = vec4(N, 1.0);
out_position.a = linearDepth(out_position.z);
out_albedo = vec4(in_color, 1.0);
}

View File

@@ -0,0 +1,36 @@
#version 450
#extension GL_EXT_debug_printf: enable
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 color;
layout (location = 2) in vec3 normal;
layout (location = 3) in vec2 uv;
layout (location = 4) in mat4 instance_model_matrix;// 4, 5, 6, 7
layout (location = 0) out vec3 out_normal;
layout (location = 1) out vec2 out_tex_coord;
layout (location = 2) out vec3 out_world_pos;
layout (location = 3) out vec3 out_color;
layout (set = 0, binding = 0) uniform CameraInfo {
mat4 projection;
mat4 view;
mat4 inverse_view;
} ubo;
void main() {
vec4 position_world = instance_model_matrix * vec4(position, 1.0);
gl_Position = ubo.projection * ubo.view * position_world;
out_world_pos = vec3(gl_Position);
mat3 normal_matrix = transpose(inverse(mat3(instance_model_matrix)));
out_normal = normalize(normal_matrix * normal);
out_tex_coord = uv;
out_color = color;
}

View File

@@ -1,5 +1,4 @@
add_executable(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}/main.cpp")
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${FGL_FLAGS}")
target_link_libraries(${PROJECT_NAME} PRIVATE Tracy::TracyClient FGLEngine)

View File

@@ -5,9 +5,12 @@
#include <iostream>
#include "engine/EngineContext.hpp"
#include "engine/logging.hpp"
int main()
{
spdlog::set_level( spdlog::level::debug );
fgl::engine::EngineContext engine_ctx {};
engine_ctx.run();

View File

@@ -25,6 +25,7 @@ target_precompile_headers(FGLEngine PRIVATE
<glm/gtc/matrix_transform.hpp>
<glm/gtc/constants.hpp>
<glm/vec3.hpp>
<glm/vec2.hpp>
<glm/mat4x4.hpp>
<imgui/imgui.h>
@@ -32,7 +33,9 @@ target_precompile_headers(FGLEngine PRIVATE
target_compile_definitions(FGLEngine PUBLIC VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC)
target_link_libraries(FGLEngine PUBLIC Vulkan::Vulkan glfw glm FGLImGui Tracy::TracyClient VMA FGLLoader)
include(dependencies/spdlog)
target_link_libraries(FGLEngine PUBLIC Vulkan::Vulkan glfw glm FGLImGui Tracy::TracyClient VMA FGLLoader spdlog)
target_include_directories(FGLEngine PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..)
set_target_properties(FGLEngine PROPERTIES COMPILE_FLAGS ${FGL_FLAGS})
target_compile_features(FGLEngine PRIVATE cxx_std_23)

View File

@@ -7,20 +7,9 @@
#include <glm/glm.hpp>
#include <tracy/TracyVulkan.hpp>
#include <array>
#include <chrono>
#include <iostream>
#include "KeyboardMovementController.hpp"
#include "engine/Average.hpp"
#include "engine/buffers/UniqueFrameSuballocation.hpp"
#include "engine/debug/drawers.hpp"
#include "engine/descriptors/DescriptorPool.hpp"
#include "engine/literals/size.hpp"
#include "engine/model/prebuilt/terrainModel.hpp"
#include "engine/pipeline/PipelineT.hpp"
#include "engine/systems/EntityRendererSystem.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wold-style-cast"
@@ -32,6 +21,17 @@
#include "imgui/imgui_internal.h"
#pragma GCC diagnostic pop
#include "KeyboardMovementController.hpp"
#include "engine/Average.hpp"
#include "engine/buffers/UniqueFrameSuballocation.hpp"
#include "engine/debug/drawers.hpp"
#include "engine/descriptors/DescriptorPool.hpp"
#include "engine/literals/size.hpp"
#include "engine/model/prebuilt/terrainModel.hpp"
#include "engine/pipeline/PipelineT.hpp"
#include "engine/systems/EntityRendererSystem.hpp"
#include "model/builders/SceneBuilder.hpp"
namespace fgl::engine
{
constexpr float MAX_DELTA_TIME { 0.5 };
@@ -289,6 +289,27 @@ namespace fgl::engine
}
}*/
{
std::vector< std::shared_ptr< Model > > models { Model::createModelsFromScene(
Device::getInstance(),
"models/PhysicsTest.glb",
m_entity_renderer.getVertexBuffer(),
m_entity_renderer.getIndexBuffer() ) };
for ( auto& model : models )
{
GameObject object { GameObject::createGameObject() };
object.m_model = std::move( model );
object.m_transform.translation = WorldCoordinate( 0.0f );
object.object_flags |= IS_VISIBLE | IS_ENTITY;
assert( object.m_model );
object.m_model->syncBuffers( command_buffer );
m_game_objects_root.addGameObject( std::move( object ) );
}
}
{
auto model {
generateTerrainModel( m_terrain_system.getVertexBuffer(), m_terrain_system.getIndexBuffer() )

View File

@@ -17,6 +17,8 @@ namespace fgl::engine
OrientedBoundingBox< CoordinateSpace::World > GameObject::getBoundingBox() const
{
assert( this->m_transform.translation.vec() != constants::DEFAULT_VEC3 );
assert( this->m_transform.scale != constants::DEFAULT_VEC3 );
return this->m_transform.mat() * this->m_model->getBoundingBox();
}

View File

@@ -29,6 +29,13 @@ namespace fgl::engine
MASK_DEFAULT = IS_VISIBLE,
};
enum GameObjectFilterOptions
{
NONE = 0,
//! Only find objects with no texture
TEXTURELESS = 1 << 0,
};
class GameObject
{
public:
@@ -48,9 +55,9 @@ namespace fgl::engine
GameObject( ID obj_id ) : m_id( obj_id ) {}
public:
GameObject() = delete;
GameObject() {}
public:
GameObject( const GameObject& other ) = delete;
GameObject& operator=( const GameObject& other ) = delete;

View File

@@ -2,6 +2,10 @@
// Created by kj16609 on 3/11/24.
//
#include <tracy/Tracy.hpp>
#include <cstddef>
#include <cstdlib>
#if TRACY_ENABLE
void* operator new( std::size_t count )

View File

@@ -6,6 +6,7 @@
#include "BufferVector.hpp"
#include "HostVector.hpp"
#include "engine/logging.hpp"
namespace fgl::engine
{
@@ -20,6 +21,7 @@ namespace fgl::engine
DeviceVector( Buffer& buffer, const std::uint32_t count = 1 ) : BufferVector( buffer, count, sizeof( T ) )
{
spdlog::debug( "Creating DeviceVector of size {}", count );
assert( count != 0 && "BufferSuballocationVector::BufferSuballocationVector() called with count == 0" );
}

View File

@@ -4,6 +4,8 @@
#pragma once
#include <memory>
namespace fgl::engine
{
class ImageView;

View File

@@ -8,7 +8,15 @@
#include "engine/primitives/boxes/AxisAlignedBoundingBox.hpp"
#include "engine/primitives/boxes/AxisAlignedBoundingCube.hpp"
#include "engine/primitives/boxes/OrientedBoundingBox.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Weffc++"
#include "imgui/imgui.h"
#pragma GCC diagnostic pop
#include <tracy/Tracy.hpp>
#include "tracy_colors.hpp"
#if ENABLE_IMGUI_DRAWERS

View File

@@ -5,6 +5,7 @@
#pragma once
#include <cstdint>
#include <iostream>
#include "engine/concepts/is_valid_pipeline_input.hpp"

13
src/engine/logging.hpp Normal file
View File

@@ -0,0 +1,13 @@
//
// Created by kj16609 on 5/22/24.
//
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#include <spdlog/spdlog.h>
#pragma GCC diagnostic pop

View File

@@ -4,6 +4,9 @@
#include "generator.hpp"
#include <glm/geometric.hpp>
#include <algorithm>
#include <random>
namespace fgl::engine

View File

@@ -3,7 +3,10 @@
//
#pragma once
#include <bits/stdint-uintn.h>
#include <glm/vec2.hpp>
#include <vector>
namespace fgl::engine
{

View File

@@ -5,19 +5,13 @@
#include "Model.hpp"
#include <cassert>
#include <cstring>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/hash.hpp>
#include <iostream>
#include <unordered_map>
#include "builders/ModelBuilder.hpp"
#include "builders/SceneBuilder.hpp"
#include "engine/buffers/Buffer.hpp"
#include "engine/buffers/SuballocationView.hpp"
#include "engine/descriptors/DescriptorSet.hpp"
#include "engine/image/ImageView.hpp"
#include "engine/image/Sampler.hpp"
namespace fgl::engine
{
@@ -73,15 +67,22 @@ namespace fgl::engine
Model::Model(
Device& device, ModelBuilder& builder, const OrientedBoundingBox< CoordinateSpace::Model > bounding_box ) :
Model( device, std::move( builder.m_primitives ), bounding_box )
{}
Model::Model(
Device& device,
std::vector< Primitive >&& primitives,
const OrientedBoundingBox< CoordinateSpace::Model > bounding_box ) :
m_device( device ),
m_draw_parameters( buildParameters( builder.m_primitives ) ),
m_draw_parameters( buildParameters( primitives ) ),
m_bounding_box( bounding_box )
{
assert( bounding_box.middle.vec() != constants::DEFAULT_VEC3 );
m_primitives = std::move( builder.m_primitives );
m_primitives = std::move( primitives );
}
std::unique_ptr< Model > Model::
std::shared_ptr< Model > Model::
createModel( Device& device, const std::filesystem::path& path, Buffer& vertex_buffer, Buffer& index_buffer )
{
std::cout << "Creating model: " << path << std::endl;
@@ -91,13 +92,25 @@ namespace fgl::engine
//Calculate bounding box
OrientedBoundingBox bounding_box { buildBoundingBox( builder.m_primitives ) };
auto model_ptr { std::make_unique< Model >( device, builder, bounding_box ) };
auto model_ptr { std::make_shared< Model >( device, builder, bounding_box ) };
std::cout << "Finished making model: " << path << std::endl;
return model_ptr;
}
std::unique_ptr< Model > Model::createModelFromVerts(
std::vector< std::shared_ptr< Model > > Model::createModelsFromScene(
Device& device, const std::filesystem::path& path, Buffer& vertex_buffer, Buffer& index_buffer )
{
std::cout << "Loading scene: " << path << std::endl;
SceneBuilder builder { vertex_buffer, index_buffer };
builder.loadScene( path );
std::cout << "Finished loading scene: " << path << std::endl;
return builder.getModels();
}
std::shared_ptr< Model > Model::createModelFromVerts(
Device& device,
std::vector< Vertex > verts,
std::vector< std::uint32_t > indicies,
@@ -109,13 +122,14 @@ namespace fgl::engine
OrientedBoundingBox bounding_box { buildBoundingBox( builder.m_primitives ) };
auto model_ptr { std::make_unique< Model >( device, builder, bounding_box ) };
auto model_ptr { std::make_shared< Model >( device, builder, bounding_box ) };
return model_ptr;
}
void Model::syncBuffers( vk::CommandBuffer& cmd_buffer )
{
assert( !m_primitives.empty() );
for ( auto& primitive : m_primitives )
{
primitive.m_vertex_buffer.stage( cmd_buffer );
@@ -128,27 +142,4 @@ namespace fgl::engine
}
}
void ModelBuilder::loadModel( const std::filesystem::path& filepath )
{
if ( filepath.extension() == ".obj" )
{
loadObj( filepath );
}
else if ( filepath.extension() == ".gltf" )
{
loadGltf( filepath );
}
else
throw std::runtime_error( "Unknown model file extension" );
}
void ModelBuilder::loadVerts( std::vector< Vertex > verts, std::vector< std::uint32_t > indicies )
{
VertexBufferSuballocation vertex_suballoc { this->m_vertex_buffer, verts };
IndexBufferSuballocation index_suballoc { this->m_index_buffer, std::move( indicies ) };
this->m_primitives.emplace_back(
std::move( vertex_suballoc ), std::move( index_suballoc ), generateBoundingFromVerts( verts ) );
}
} // namespace fgl::engine

View File

@@ -17,6 +17,7 @@
namespace fgl::engine
{
struct ModelBuilder;
struct ModelMatrixInfo
{
@@ -24,26 +25,6 @@ namespace fgl::engine
std::uint32_t texture_idx;
};
struct ModelBuilder
{
Buffer& m_vertex_buffer;
Buffer& m_index_buffer;
std::vector< 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 );
void loadVerts( std::vector< Vertex > verts, std::vector< std::uint32_t > indicies );
};
class Model
{
Device& m_device;
@@ -69,16 +50,20 @@ namespace fgl::engine
std::vector< vk::DrawIndexedIndirectCommand > getDrawCommand( const std::uint32_t index ) const;
static std::unique_ptr< Model > createModel(
//TODO: Switch to using shared_ptr instead of unique_ptr
static std::shared_ptr< Model > createModel(
Device& device, const std::filesystem::path& path, Buffer& vertex_buffer, Buffer& index_buffer );
static std::unique_ptr< Model > createModelFromVerts(
static std::shared_ptr< Model > createModelFromVerts(
Device& device,
std::vector< Vertex > verts,
std::vector< std::uint32_t > indicies,
Buffer& vertex_buffer,
Buffer& index_buffer );
static std::vector< std::shared_ptr< Model > > createModelsFromScene(
Device& device, const std::filesystem::path& path, Buffer& vertex_buffer, Buffer& index_buffer );
void syncBuffers( vk::CommandBuffer& cmd_buffer );
const std::string& getName() const { return m_name; }
@@ -86,6 +71,11 @@ namespace fgl::engine
Model(
Device& device, ModelBuilder& builder, const OrientedBoundingBox< CoordinateSpace::Model > bounding_box );
Model(
Device& device,
std::vector< Primitive >&& primitives,
const OrientedBoundingBox< CoordinateSpace::Model > bounding_box );
~Model() = default;
Model( const Model& model ) = delete;

View File

@@ -0,0 +1,32 @@
//
// Created by kj16609 on 5/23/24.
//
#include "Primitive.hpp"
namespace fgl::engine
{
Primitive Primitive::fromVerts(
const std::vector< Vertex >&& verts,
const PrimitiveMode mode,
const std::vector< std::uint32_t >&& indicies,
Buffer& vertex_buffer,
Buffer& index_buffer )
{
const auto bounds { generateBoundingFromVerts( verts ) };
VertexBufferSuballocation vertex_buffer_suballoc { vertex_buffer, std::move( verts ) };
IndexBufferSuballocation index_buffer_suballoc { index_buffer, std::move( indicies ) };
return { std::move( vertex_buffer_suballoc ), std::move( index_buffer_suballoc ), bounds, mode };
}
TextureID Primitive::getTextureID() const
{
if ( m_texture )
return m_texture->getID();
else
return std::numeric_limits< TextureID >::max();
}
} // namespace fgl::engine

View File

@@ -12,43 +12,74 @@
#include "engine/primitives/boxes/OrientedBoundingBox.hpp"
#include "engine/texture/Texture.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Weffc++"
#include "objectloaders/tiny_gltf.h"
#pragma GCC diagnostic pop
namespace fgl::engine
{
using VertexBufferSuballocation = DeviceVector< Vertex >;
using IndexBufferSuballocation = DeviceVector< std::uint32_t >;
enum PrimitiveMode
{
POINTS = TINYGLTF_MODE_POINTS,
LINE = TINYGLTF_MODE_LINE,
LINE_LOOP = TINYGLTF_MODE_LINE_LOOP,
LINE_STRIP = TINYGLTF_MODE_LINE_STRIP,
TRIS = TINYGLTF_MODE_TRIANGLES,
TRI_STRIP = TINYGLTF_MODE_TRIANGLE_STRIP,
TRI_FAN = TINYGLTF_MODE_TRIANGLE_FAN
};
struct Primitive
{
VertexBufferSuballocation m_vertex_buffer;
IndexBufferSuballocation m_index_buffer;
OrientedBoundingBox< CoordinateSpace::Model > m_bounding_box;
PrimitiveMode m_mode;
std::optional< Texture > m_texture { std::nullopt };
Primitive(
VertexBufferSuballocation&& vertex_buffer,
IndexBufferSuballocation&& index_buffer,
const OrientedBoundingBox< CoordinateSpace::Model >& bounding_box ) :
const OrientedBoundingBox< CoordinateSpace::Model >& bounding_box,
const PrimitiveMode mode ) :
m_vertex_buffer( std::move( vertex_buffer ) ),
m_index_buffer( std::move( index_buffer ) ),
m_bounding_box( bounding_box )
m_bounding_box( bounding_box ),
m_mode( mode )
{}
Primitive(
VertexBufferSuballocation&& vertex_buffer,
IndexBufferSuballocation&& index_buffer,
const OrientedBoundingBox< CoordinateSpace::Model >& bounding_box,
Texture&& texture ) :
Texture&& texture,
const PrimitiveMode mode ) :
m_vertex_buffer( std::move( vertex_buffer ) ),
m_index_buffer( std::move( index_buffer ) ),
m_bounding_box( bounding_box ),
m_mode( mode ),
m_texture( std::move( texture ) )
{}
Primitive() = delete;
Primitive( const Primitive& other ) = delete;
Primitive( Primitive&& other ) = default;
static Primitive fromVerts(
const std::vector< Vertex >&& verts,
const PrimitiveMode mode,
const std::vector< std::uint32_t >&& indicies,
Buffer& vertex_buffer,
Buffer& index_buffer );
TextureID getTextureID() const;
};
} // namespace fgl::engine

View File

@@ -0,0 +1,38 @@
//
// Created by kj16609 on 5/18/24.
//
#include "ModelBuilder.hpp"
#include "engine/model/Primitive.hpp"
namespace fgl::engine
{
void ModelBuilder::loadModel( const std::filesystem::path& filepath )
{
if ( filepath.extension() == ".obj" )
{
loadObj( filepath );
}
else if ( filepath.extension() == ".gltf" )
{
loadGltf( filepath );
}
else
throw std::runtime_error( "Unknown model file extension" );
}
void ModelBuilder::loadVerts( std::vector< Vertex > verts, std::vector< std::uint32_t > indicies )
{
VertexBufferSuballocation vertex_suballoc { this->m_vertex_buffer, verts };
IndexBufferSuballocation index_suballoc { this->m_index_buffer, std::move( indicies ) };
this->m_primitives.emplace_back(
std::move( vertex_suballoc ),
std::move( index_suballoc ),
generateBoundingFromVerts( verts ),
PrimitiveMode::TRIS );
}
} // namespace fgl::engine

View File

@@ -0,0 +1,36 @@
//
// Created by kj16609 on 5/18/24.
//
#pragma once
#include <filesystem>
#include <vector>
namespace fgl ::engine
{
struct Vertex;
struct Primitive;
class Buffer;
struct ModelBuilder
{
Buffer& m_vertex_buffer;
Buffer& m_index_buffer;
std::vector< 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 );
void loadVerts( std::vector< Vertex > verts, std::vector< std::uint32_t > indicies );
};
} // namespace fgl::engine

View File

@@ -0,0 +1,386 @@
//
// Created by kj16609 on 5/18/24.
//
#include "SceneBuilder.hpp"
#include "engine/model/Model.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Weffc++"
#include "objectloaders/tiny_gltf.h"
#pragma GCC diagnostic pop
#include <engine/logging.hpp>
namespace fgl::engine
{
SceneBuilder::SceneBuilder( Buffer& vertex_buffer, Buffer& index_buffer ) :
m_vertex_buffer( vertex_buffer ),
m_index_buffer( index_buffer )
{}
int SceneBuilder::getTexcoordCount( const tinygltf::Primitive& prim ) const
{
int counter { 0 };
for ( const auto& [ key, value ] : prim.attributes )
{
if ( key.starts_with( "TEXCOORD" ) ) ++counter;
}
return counter;
}
template < typename T >
std::vector< T > extractData( const tinygltf::Model& model, const tinygltf::Accessor& accessor )
{
if ( accessor.sparse.isSparse )
{
//Sparse loading required
throw std::runtime_error( "Sparse loading not implemeneted" );
}
const auto& buffer_view { model.bufferViews.at( accessor.bufferView ) };
const auto& buffer { model.buffers.at( buffer_view.buffer ) };
std::vector< T > data {};
data.reserve( accessor.count );
std::uint16_t copy_size { 0 };
switch ( accessor.componentType )
{
default:
throw std::runtime_error( "Unhandled access size" );
case TINYGLTF_COMPONENT_TYPE_FLOAT:
copy_size = 32 / 8;
break;
case TINYGLTF_COMPONENT_TYPE_BYTE:
copy_size = 8 / 8;
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
copy_size = 32 / 8;
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
copy_size = 16 / 8;
break;
}
switch ( accessor.type )
{
default:
throw std::runtime_error( "Unhandled access type" );
case TINYGLTF_TYPE_VEC3:
copy_size *= 3;
break;
case TINYGLTF_TYPE_VEC2:
copy_size *= 2;
break;
case TINYGLTF_TYPE_SCALAR:
copy_size *= 1;
break;
}
constexpr auto T_SIZE { sizeof( T ) };
if ( T_SIZE != copy_size )
throw std::runtime_error(
std::string( "Accessor copy values not matching sizeof(T): sizeof(" )
+ std::string( typeid( T ).name() ) + ") == " + std::to_string( T_SIZE )
+ " vs copy_size = " + std::to_string( copy_size ) );
const auto real_size { copy_size * accessor.count };
data.resize( accessor.count );
std::memcpy( data.data(), buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset, real_size );
return data;
}
std::vector< std::uint32_t > SceneBuilder::
extractIndicies( const tinygltf::Primitive& prim, const tinygltf::Model& model )
{
const auto& indicies_accessor { model.accessors.at( prim.indices ) };
if ( indicies_accessor.componentType == TINYGLTF_COMPONENT_TYPE_INT )
{
return extractData< std::uint32_t >( model, indicies_accessor );
}
else
{
//TODO: Figure out any time we can use a smaller indicies value instead of a 32 bit number all the time
std::vector< std::uint32_t > indicies {};
const auto tmp { extractData< std::uint16_t >( model, indicies_accessor ) };
indicies.reserve( tmp.size() );
for ( const auto val : tmp ) indicies.emplace_back( val );
return indicies;
}
}
const tinygltf::Accessor& SceneBuilder::getAccessorForAttribute(
const tinygltf::Primitive& prim, const tinygltf::Model& root, const std::string attrib ) const
{
return root.accessors.at( prim.attributes.at( attrib ) );
}
Texture SceneBuilder::loadTexture( const tinygltf::Primitive& prim, const tinygltf::Model& root )
{
const auto mat_idx { prim.material };
if ( mat_idx == -1 )
{
//There is no matrial for this
throw std::runtime_error( "No material for primitive. One was expected" );
}
const auto& material { root.materials[ mat_idx ] };
for ( const auto& [ key, value ] : material.values )
{
spdlog::debug( "Parsing texture for key {}", key );
}
//TODO:
throw std::runtime_error( "No material loader implemented" );
}
std::vector< std::shared_ptr< Model > > SceneBuilder::getModels()
{
std::vector< std::shared_ptr< Model > > new_models { std::move( models ) };
return new_models;
}
std::vector< glm::vec3 > SceneBuilder::
extractPositionInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root )
{
const tinygltf::Accessor& accessor { getAccessorForAttribute( prim, root, "POSITION" ) };
return extractData< glm::vec3 >( root, accessor );
}
std::vector< glm::vec3 > SceneBuilder::
extractNormalInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root )
{
if ( !hasAttribute( prim, "NORMAL" ) ) return {};
const tinygltf::Accessor& accessor { getAccessorForAttribute( prim, root, "NORMAL" ) };
return extractData< glm::vec3 >( root, accessor );
}
std::vector< glm::vec2 > SceneBuilder::extractUVInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root )
{
spdlog::debug( "Extracting UV info" );
//TODO: Figure out how I can use multiple textures for various things.
if ( !hasAttribute( prim, "TEXCOORD_0" ) ) return {};
const tinygltf::Accessor& accessor { getAccessorForAttribute( prim, root, "TEXCOORD_0" ) };
return extractData< glm::vec2 >( root, accessor );
}
bool SceneBuilder::hasAttribute( const tinygltf::Primitive& prim, const std::string_view str )
{
return prim.attributes.contains( std::string( str ) );
}
std::vector< Vertex > SceneBuilder::
extractVertexInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root )
{
spdlog::debug( "Extracting vert info" );
const auto pos { extractPositionInfo( prim, root ) };
std::vector< Vertex > verts {};
verts.reserve( pos.size() );
const std::vector< glm::vec3 > normals { extractNormalInfo( prim, root ) };
//TODO: If we don't have normals we likely will need to compute them ourselves.
// I have no idea if this is actually going to be needed for us. But I might wanna implement it
// anyways, Just in case.
const bool has_normals { !normals.empty() };
const std::vector< glm::vec2 > uvs { extractUVInfo( prim, root ) };
const bool has_uv { !uvs.empty() };
for ( std::size_t i = 0; i < pos.size(); ++i )
{
Vertex vert {};
vert.m_position = pos[ i ];
vert.m_normal = has_normals ? normals[ i ] : glm::vec3();
vert.m_uv = has_uv ? uvs[ i ] : glm::vec2();
vert.m_color = glm::vec3( 0.1f );
verts.emplace_back( vert );
}
spdlog::debug(
"Found {} verts.\n\t- Has UV info: {}\n\t- Has normals: {}",
verts.size(),
has_uv ? "Yes" : "No",
has_normals ? "Yes" : "No" );
return verts;
}
Primitive SceneBuilder::loadPrimitive( const tinygltf::Primitive& prim, const tinygltf::Model& root )
{
std::string att_str;
for ( const auto& attrib : prim.attributes )
{
att_str += "Attribute: " + attrib.first + "\n";
}
spdlog::debug( "Attributes for primitive:\n{}", att_str );
const bool has_normal { hasAttribute( prim, "NORMAL" ) };
const bool has_position { hasAttribute( prim, "POSITION" ) };
const bool has_texcoord { hasAttribute( prim, "TEXCOORD_0" ) };
const int texcoord_count { has_texcoord ? getTexcoordCount( prim ) : 0 };
if ( !has_position ) throw std::runtime_error( "Failed to load model. Missing expected POSITION attribute" );
switch ( static_cast< PrimitiveMode >( prim.mode ) )
{
case POINTS:
[[fallthrough]];
case LINE:
[[fallthrough]];
case LINE_LOOP:
[[fallthrough]];
case LINE_STRIP:
[[fallthrough]];
case TRIS:
[[fallthrough]];
case TRI_STRIP:
[[fallthrough]];
case TRI_FAN:
{
std::vector< Vertex > verts { extractVertexInfo( prim, root ) };
std::vector< std::uint32_t > indicies { extractIndicies( prim, root ) };
Primitive primitive_mesh { Primitive::fromVerts(
std::move( verts ),
static_cast< PrimitiveMode >( prim.mode ),
std::move( indicies ),
m_vertex_buffer,
m_index_buffer ) };
if ( !has_texcoord ) return primitive_mesh;
primitive_mesh.m_texture = loadTexture( prim, root );
return primitive_mesh;
}
default:
{
spdlog::error( "Unsupported mode for primtiive loading: {}", prim.mode );
throw std::runtime_error( "Unsupported mode for primitive loading" );
}
}
std::unreachable();
}
OrientedBoundingBox< CoordinateSpace::Model > createModelBoundingBox( const std::vector< Primitive >& primitives )
{
if ( primitives.size() <= 0 ) return {};
OrientedBoundingBox< CoordinateSpace::Model > box { primitives.at( 0 ).m_bounding_box };
for ( std::uint64_t i = 1; i < primitives.size(); i++ ) box = box.combine( primitives[ i ].m_bounding_box );
return box;
}
std::shared_ptr< Model > SceneBuilder::loadModel( const int mesh_idx, const tinygltf::Model& root )
{
const auto mesh { root.meshes[ mesh_idx ] };
const auto& primitives { mesh.primitives };
spdlog::debug( "Mesh idx {} has {} primitives", mesh_idx, primitives.size() );
std::vector< Primitive > finished_primitives {};
for ( const auto& prim : primitives )
{
Primitive primitive { loadPrimitive( prim, root ) };
finished_primitives.emplace_back( std::move( primitive ) );
}
spdlog::debug( "Finished loading model with {} primitives", finished_primitives.size() );
const auto bounding_box { createModelBoundingBox( finished_primitives ) };
return std::make_shared< Model >( Device::getInstance(), std::move( finished_primitives ), bounding_box );
}
void SceneBuilder::handleNode( const int node_idx, const tinygltf::Model& root )
{
const auto& node { root.nodes[ node_idx ] };
spdlog::debug( "Handling node: Index:{} Name:\"{}\"", node_idx, node.name );
const auto mesh_idx { node.mesh };
const auto skin_idx { node.skin };
spdlog::debug( "Mesh IDX: {}", mesh_idx );
spdlog::debug( "Skin IDX: {}", skin_idx );
std::shared_ptr< Model > model { loadModel( mesh_idx, root ) };
assert( model );
//TODO: Material.
this->models.emplace_back( std::move( model ) );
}
void SceneBuilder::handleScene( const tinygltf::Scene& scene, const tinygltf::Model& root )
{
spdlog::debug( "Handling scene: ", scene.name );
spdlog::debug( "Scene has {} nodes", scene.nodes.size() );
for ( const auto node_idx : scene.nodes )
{
handleNode( node_idx, root );
}
}
void SceneBuilder::loadScene( const std::filesystem::path path )
{
if ( !std::filesystem::exists( path ) ) throw std::runtime_error( "Failed to find scene at filepath" );
tinygltf::TinyGLTF loader {};
tinygltf::Model gltf_model {};
std::string err;
std::string warn;
if ( !loader.LoadBinaryFromFile( &gltf_model, &err, &warn, path ) )
{
throw std::runtime_error( "Failed to load binary model" );
}
if ( !err.empty() )
{
spdlog::error( "Error loading model {}: \"{}\"", path.string(), err );
throw std::runtime_error( err );
}
if ( !warn.empty() )
{
spdlog::warn( "Warning loading model {}: \"{}\"", path.string(), warn );
}
const auto scenes { gltf_model.scenes };
for ( const auto& scene : scenes )
{
handleScene( scene, gltf_model );
}
}
} // namespace fgl::engine

View File

@@ -0,0 +1,75 @@
//
// Created by kj16609 on 5/18/24.
//
#pragma once
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <filesystem>
#include <vector>
namespace fgl::engine
{
struct Vertex;
class Model;
struct Primitive;
class Texture;
class Buffer;
} // namespace fgl::engine
namespace tinygltf
{
struct Scene;
class Model;
struct Primitive;
struct Accessor;
} // namespace tinygltf
namespace fgl::engine
{
class SceneBuilder
{
Buffer& m_vertex_buffer;
Buffer& m_index_buffer;
std::vector< std::shared_ptr< Model > > models {};
void handleScene( const tinygltf::Scene& scene, const tinygltf::Model& root );
void handleNode( const int node_idx, const tinygltf::Model& root );
std::shared_ptr< Model > loadModel( const int mesh_idx, const tinygltf::Model& root );
Primitive loadPrimitive( const tinygltf::Primitive& prim, const tinygltf::Model& model );
int getTexcoordCount( const tinygltf::Primitive& prim ) const;
std::vector< std::uint32_t > extractIndicies( const tinygltf::Primitive& prim, const tinygltf::Model& model );
std::vector< Vertex > extractVertexInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root );
std::vector< glm::vec3 > extractPositionInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root );
//! Returns an empty vector if no normals could be extracted
std::vector< glm::vec3 > extractNormalInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root );
std::vector< glm::vec2 > extractUVInfo( const tinygltf::Primitive& prim, const tinygltf::Model& root );
bool hasAttribute( const tinygltf::Primitive& prim, const std::string_view str );
const tinygltf::Accessor& getAccessorForAttribute(
const tinygltf::Primitive& prim, const tinygltf::Model& root, const std::string attrib ) const;
Texture loadTexture( const tinygltf::Primitive& prim, const tinygltf::Model& root );
public:
std::vector< std::shared_ptr< Model > > getModels();
SceneBuilder() = delete;
SceneBuilder( Buffer& vertex_buffer, Buffer& index_buffer );
void loadScene( const std::filesystem::path path );
};
} // namespace fgl::engine

View File

@@ -1,89 +1,87 @@
//
// Created by kj16609 on 2/5/24.
// Created by kj16609 on 5/18/24.
//
#include "Model.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Weffc++"
#include "engine/image/Sampler.hpp"
#include "objectloaders/tiny_gltf.h"
#pragma GCC diagnostic pop
#include "ModelBuilder.hpp"
#include "engine/descriptors/DescriptorSet.hpp"
#include "engine/image/ImageView.hpp"
#include "engine/image/Sampler.hpp"
#include "engine/model/Primitive.hpp"
#include "engine/primitives/boxes/OrientedBoundingBox.hpp"
#include "engine/primitives/points/Coordinate.hpp"
namespace fgl::engine
{
template < typename T >
std::vector< T > extractData( const tinygltf::Model& model, const tinygltf::Accessor& accessor )
{
if ( accessor.sparse.isSparse )
{
//Sparse loading required
throw std::runtime_error( "Sparse loading not implemeneted" );
}
else
const auto& buffer_view { model.bufferViews.at( accessor.bufferView ) };
const auto& buffer { model.buffers.at( buffer_view.buffer ) };
std::vector< T > data {};
data.reserve( accessor.count );
std::uint16_t copy_size { 0 };
switch ( accessor.componentType )
{
const auto& buffer_view { model.bufferViews.at( accessor.bufferView ) };
const auto& buffer { model.buffers.at( buffer_view.buffer ) };
std::vector< T > data {};
data.reserve( accessor.count );
std::uint16_t copy_size { 0 };
switch ( accessor.componentType )
{
default:
throw std::runtime_error( "Unhandled access size" );
case TINYGLTF_COMPONENT_TYPE_FLOAT:
copy_size = 32 / 8;
break;
case TINYGLTF_COMPONENT_TYPE_BYTE:
copy_size = 8 / 8;
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
copy_size = 32 / 8;
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
copy_size = 16 / 8;
break;
}
switch ( accessor.type )
{
default:
throw std::runtime_error( "Unhandled access type" );
case TINYGLTF_TYPE_VEC3:
copy_size *= 3;
break;
case TINYGLTF_TYPE_VEC2:
copy_size *= 2;
break;
case TINYGLTF_TYPE_SCALAR:
copy_size *= 1;
break;
}
constexpr auto T_SIZE { sizeof( T ) };
if ( T_SIZE != copy_size )
throw std::runtime_error(
std::string( "Accessor copy values not matching sizeof(T): sizeof(" )
+ std::string( typeid( T ).name() ) + ") == " + std::to_string( T_SIZE )
+ " vs copy_size = " + std::to_string( copy_size ) );
const auto real_size { copy_size * accessor.count };
data.resize( accessor.count );
std::memcpy( data.data(), buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset, real_size );
return data;
default:
throw std::runtime_error( "Unhandled access size" );
case TINYGLTF_COMPONENT_TYPE_FLOAT:
copy_size = 32 / 8;
break;
case TINYGLTF_COMPONENT_TYPE_BYTE:
copy_size = 8 / 8;
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT:
copy_size = 32 / 8;
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
copy_size = 16 / 8;
break;
}
switch ( accessor.type )
{
default:
throw std::runtime_error( "Unhandled access type" );
case TINYGLTF_TYPE_VEC3:
copy_size *= 3;
break;
case TINYGLTF_TYPE_VEC2:
copy_size *= 2;
break;
case TINYGLTF_TYPE_SCALAR:
copy_size *= 1;
break;
}
constexpr auto T_SIZE { sizeof( T ) };
if ( T_SIZE != copy_size )
throw std::runtime_error(
std::string( "Accessor copy values not matching sizeof(T): sizeof(" )
+ std::string( typeid( T ).name() ) + ") == " + std::to_string( T_SIZE )
+ " vs copy_size = " + std::to_string( copy_size ) );
const auto real_size { copy_size * accessor.count };
data.resize( accessor.count );
std::memcpy( data.data(), buffer.data.data() + buffer_view.byteOffset + accessor.byteOffset, real_size );
return data;
}
void ModelBuilder::loadGltf( const std::filesystem::path& filepath )
@@ -125,14 +123,11 @@ namespace fgl::engine
}
else if ( indicies_accessor.componentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT )
{
auto tmp { extractData< std::uint16_t >( model, model.accessors.at( primitive.indices ) ) };
const auto tmp { extractData< std::uint16_t >( model, model.accessors.at( primitive.indices ) ) };
indicies_data.reserve( tmp.size() );
for ( auto& val : tmp )
{
indicies_data.emplace_back( val );
}
for ( auto& val : tmp ) indicies_data.emplace_back( val );
}
//Load positions
@@ -276,9 +271,11 @@ namespace fgl::engine
Device::getInstance().endSingleTimeCommands( cmd );
tex.dropStaging();
Primitive prim {
std::move( vertex_buffer ), std::move( index_buffer ), bounding_box, std::move( tex )
};
Primitive prim { std::move( vertex_buffer ),
std::move( index_buffer ),
bounding_box,
std::move( tex ),
PrimitiveMode::TRIS };
m_primitives.emplace_back( std::move( prim ) );
@@ -288,7 +285,9 @@ namespace fgl::engine
else
std::cout << "No material" << std::endl;
Primitive prim { std::move( vertex_buffer ), std::move( index_buffer ), bounding_box };
Primitive prim {
std::move( vertex_buffer ), std::move( index_buffer ), bounding_box, PrimitiveMode::TRIS
};
m_primitives.emplace_back( std::move( prim ) );
}
@@ -313,5 +312,4 @@ namespace fgl::engine
std::cout << "Finished loading model: " << filepath << std::endl;
}
} // namespace fgl::engine

View File

@@ -1,20 +1,22 @@
//
// Created by kj16609 on 2/5/24.
// Created by kj16609 on 5/18/24.
//
#include "Model.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Weffc++"
#include "objectloaders/tiny_obj_loader.h"
#include <objectloaders/tiny_obj_loader.h>
#pragma GCC diagnostic pop
#include "Vertex.hpp"
#include <unordered_map>
#include "ModelBuilder.hpp"
#include "engine/model/Primitive.hpp"
#include "engine/model/Vertex.hpp"
#include "engine/primitives/boxes/OrientedBoundingBox.hpp"
namespace fgl::engine
{
void ModelBuilder::loadObj( const std::filesystem::path& filepath )
{
m_primitives.clear();
@@ -99,7 +101,8 @@ namespace fgl::engine
[[maybe_unused]] auto& itter = m_primitives.emplace_back(
VertexBufferSuballocation( m_vertex_buffer, std::move( verts ) ),
IndexBufferSuballocation( m_index_buffer, std::move( indicies ) ),
bounding_box );
bounding_box,
PrimitiveMode::TRIS );
std::cout << unique_verts.size() << " unique verts" << std::endl;
}

View File

@@ -38,7 +38,7 @@ namespace fgl::engine
info.rasterization_info.rasterizerDiscardEnable = VK_FALSE;
info.rasterization_info.polygonMode = vk::PolygonMode::eFill;
info.rasterization_info.cullMode = vk::CullModeFlagBits::eBack;
info.rasterization_info.frontFace = vk::FrontFace::eClockwise;
info.rasterization_info.frontFace = vk::FrontFace::eCounterClockwise;
info.rasterization_info.depthBiasEnable = VK_FALSE;
info.rasterization_info.depthBiasConstantFactor = 0.0f;
info.rasterization_info.depthBiasClamp = 0.0f;
@@ -122,6 +122,11 @@ namespace fgl::engine
info.color_blend_info.attachmentCount = static_cast< std::uint32_t >( info.color_blend_attachment.size() );
}
void PipelineConfigInfo::disableCulling( PipelineConfigInfo& info )
{
info.rasterization_info.cullMode = vk::CullModeFlagBits::eNone;
}
PipelineConfigInfo::PipelineConfigInfo( vk::RenderPass pass )
{
render_pass = pass;

View File

@@ -46,6 +46,7 @@ namespace fgl::engine
static void defaultConfig( PipelineConfigInfo& info );
static void enableAlphaBlending( PipelineConfigInfo& config );
static void addColorAttachmentConfig( PipelineConfigInfo& info );
static void disableCulling( PipelineConfigInfo& info );
};
} // namespace fgl::engine

View File

@@ -2,11 +2,12 @@
// Created by kj16609 on 3/13/24.
//
#ifndef SHADER_HPP
#define SHADER_HPP
#pragma once
#include <fstream>
#include "engine/logging.hpp"
namespace fgl::engine
{
@@ -60,7 +61,10 @@ namespace fgl::engine
stage_info.module = shader_module;
}
else
{
spdlog::critical( "Failed to load shader module {}. Path not found", path.string() );
throw std::runtime_error( "Failed to load shader module. Path not found" );
}
}
ShaderHandle( const ShaderHandle& other ) = delete;
@@ -152,5 +156,3 @@ namespace fgl::engine
};
} // namespace fgl::engine
#endif //SHADER_HPP

View File

@@ -10,6 +10,7 @@
#include <glm/gtc/quaternion.hpp>
#pragma GCC diagnostic pop
#include <numbers>
#include <utility>
#include "engine/primitives/matricies/RotationMatrix.hpp"

View File

@@ -15,7 +15,7 @@ namespace fgl::engine
//TransformComponent is always in world space
struct TransformComponent
{
WorldCoordinate translation { constants::DEFAULT_VEC3 };
WorldCoordinate translation { constants::WORLD_CENTER };
glm::vec3 scale { 1.0f, 1.0f, 1.0f };
Rotation rotation { 0.0f, 0.0f, 0.0f };

View File

@@ -118,8 +118,14 @@ namespace fgl::engine
{
if ( oobb.rotation == Rotation() ) // If default rotation then we can simply just take it as the box is
{
assert( oobb.topRightForward().vec() != constants::DEFAULT_VEC3 );
assert( oobb.bottomLeftBack().vec() != -constants::DEFAULT_VEC3 );
m_top_right_forward = oobb.topRightForward();
m_bottom_left_back = oobb.bottomLeftBack();
assert( m_top_right_forward.vec() != constants::DEFAULT_VEC3 );
assert( m_bottom_left_back.vec() != -constants::DEFAULT_VEC3 );
}
else
{
@@ -134,9 +140,10 @@ namespace fgl::engine
m_bottom_left_back.y = std::min( m_bottom_left_back.y, point.y );
m_bottom_left_back.z = std::min( m_bottom_left_back.z, point.z );
}
assert( m_top_right_forward.vec() != constants::DEFAULT_VEC3 );
assert( m_bottom_left_back.vec() != -constants::DEFAULT_VEC3 );
}
assert( m_top_right_forward.vec() != constants::DEFAULT_VEC3 );
assert( m_bottom_left_back.vec() != -constants::DEFAULT_VEC3 );
}
template < CoordinateSpace CType >

View File

@@ -4,8 +4,11 @@
#include "OrientedBoundingBox.hpp"
#include <tracy/Tracy.hpp>
#include <array>
#include "engine/logging.hpp"
#include "engine/model/Vertex.hpp"
#include "engine/primitives/lines/LineSegment.hpp"
#include "engine/primitives/points/Coordinate.hpp"
@@ -235,6 +238,7 @@ namespace fgl::engine
OrientedBoundingBox< CoordinateSpace::Model > generateBoundingFromVerts( const std::vector< Vertex >& verts )
{
spdlog::debug( "Generating bounding box for {} verts", verts.size() );
// neg (min)
glm::vec3 top_right_forward { verts[ 0 ].m_position };
// pos (max)

View File

@@ -39,7 +39,10 @@ namespace fgl::engine
middle( pos ),
scale( inital_scale ),
rotation( inital_rotation )
{}
{
assert( pos.vec() != constants::DEFAULT_VEC3 );
assert( inital_scale != constants::DEFAULT_VEC3 );
}
public:
@@ -70,10 +73,14 @@ namespace fgl::engine
OrientedBoundingBox< EvolvedType< MType >() >
operator*( const Matrix< MType > matrix, const OrientedBoundingBox< CType > bounding_box )
{
assert( bounding_box.middle.vec() != constants::DEFAULT_VEC3 );
assert( bounding_box.scale != glm::vec3( 0.0f ) );
const Coordinate< EvolvedType< MType >() > new_middle { matrix * bounding_box.middle };
const glm::vec3 new_scale { matrix * glm::vec4( bounding_box.scale, 0.0f ) };
//TODO: Fix this stupid rot shit
const Rotation new_rot { bounding_box.rotation };
return OrientedBoundingBox< EvolvedType< MType >() >( new_middle, new_scale, new_rot );
}

View File

@@ -4,6 +4,8 @@
#include "LineBase.hpp"
#include <glm/geometric.hpp>
namespace fgl::engine
{

View File

@@ -4,6 +4,8 @@
#pragma once
#include <glm/vec3.hpp>
namespace fgl::engine
{

View File

@@ -41,21 +41,21 @@ namespace fgl::engine
explicit Coordinate( const Vector vector );
float& up() { return z; }
inline float& up() { return z; }
float up() const { return z; }
inline float up() const { return z; }
float& right() { return x; }
inline float& right() { return x; }
float right() const { return x; }
inline float right() const { return x; }
float& forward() { return y; }
inline float& forward() { return y; }
float forward() const { return y; }
inline float forward() const { return y; }
glm::vec3& vec() { return static_cast< glm::vec3& >( *this ); }
inline glm::vec3& vec() { return static_cast< glm::vec3& >( *this ); }
const glm::vec3& vec() const { return static_cast< const glm::vec3& >( *this ); }
inline const glm::vec3& vec() const { return static_cast< const glm::vec3& >( *this ); }
Coordinate operator+( const Vector other ) const;
Coordinate operator-( const Vector other ) const;
@@ -82,10 +82,16 @@ namespace fgl::engine
static_assert( sizeof( glm::vec3 ) == sizeof( ModelCoordinate ) );
template < fgl::engine::CoordinateSpace CType >
::std::ostream& operator<<( ::std::ostream& os, const fgl::engine::Coordinate< CType > coordinate )
template < CoordinateSpace CType >
inline ::std::ostream& operator<<( ::std::ostream& os, const Coordinate< CType > coordinate )
{
return os << "(" << coordinate.x << ", " << coordinate.y << ", " << coordinate.z << ")";
}
template < CoordinateSpace CType >
inline double distance( const Coordinate< CType >& p1, const Coordinate< CType >& p2 )
{
return length( p1.vec() - p2.vec() );
}
} // namespace fgl::engine

View File

@@ -4,6 +4,7 @@
#pragma once
#include <glm/geometric.hpp>
#include <glm/vec3.hpp>
#include "engine/primitives/CoordinateSpace.hpp"

View File

@@ -8,6 +8,8 @@
#include <set>
#include <unordered_set>
#include "engine/logging.hpp"
PFN_vkCreateDebugUtilsMessengerEXT pfnVkCreateDebugUtilsMessengerEXT { nullptr };
PFN_vkDestroyDebugUtilsMessengerEXT pfnVkDestroyDebugUtilsMessengerEXT { nullptr };
PFN_vkSetDebugUtilsObjectNameEXT pfnVkSetDebugUtilsObjectNameEXT { nullptr };
@@ -19,6 +21,22 @@ static VKAPI_ATTR vk::Bool32 VKAPI_CALL debugCallback(
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
[[maybe_unused]] void* pUserData )
{
using Bits = VkDebugUtilsMessageSeverityFlagBitsEXT;
if ( pCallbackData->flags & Bits::VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT )
{
spdlog::info( pCallbackData->pMessage );
}
if ( pCallbackData->flags & Bits::VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT )
{
spdlog::warn( pCallbackData->pMessage );
}
if ( pCallbackData->flags & Bits::VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT )
{
spdlog::error( pCallbackData->pMessage );
std::abort();
}
if ( pCallbackData->flags
& ( VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
| VkDebugUtilsMessageSeverityFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT ) )

View File

@@ -14,6 +14,7 @@ namespace fgl::engine
PipelineConfigInfo composition_info { render_pass };
PipelineConfigInfo::addColorAttachmentConfig( composition_info );
PipelineConfigInfo::disableVertexInput( composition_info );
PipelineConfigInfo::disableCulling( composition_info );
composition_info.subpass = 1;
m_pipeline = std::make_unique< CompositionPipeline >( Device::getInstance(), composition_info );

View File

@@ -4,6 +4,7 @@
#include "CullingSystem.hpp"
#include <imgui/imgui.h>
#include <tracy/TracyC.h>
#include "engine/FrameInfo.hpp"

View File

@@ -16,7 +16,10 @@ namespace fgl::engine
{
std::pair< std::vector< vk::DrawIndexedIndirectCommand >, std::vector< ModelMatrixInfo > > getDrawCallsFromTree(
OctTreeNode& root, const Frustum< CoordinateSpace::World >& frustum, const GameObjectFlagType flags )
OctTreeNode& root,
const Frustum< CoordinateSpace::World >& frustum,
const GameObjectFlagType flags,
const GameObjectFilterOptions options )
{
ZoneScoped;
std::unordered_map< DrawKey, DrawPair > draw_pairs {};
@@ -34,15 +37,24 @@ namespace fgl::engine
// debug::world::drawBoundingBox( obj.getBoundingBox() );
for ( const auto& primitive : obj.m_model->m_primitives )
for ( const Primitive& primitive : obj.m_model->m_primitives )
{
assert( primitive.m_texture );
//assert( primitive.m_texture );
const ModelMatrixInfo matrix_info { .model_matrix = obj.m_transform.mat4(),
.texture_idx = primitive.m_texture->getID() };
.texture_idx = primitive.getTextureID() };
const auto key {
std::make_pair( primitive.m_texture->getID(), primitive.m_index_buffer.getOffset() )
};
// If the textureless flag is on and we have a texture then skip the primitive.c
if ( options & TEXTURELESS )
{
if ( primitive.m_texture.has_value() ) continue;
}
else
{
// Flag is not present
if ( !primitive.m_texture.has_value() ) continue;
}
const auto key { std::make_pair( matrix_info.texture_idx, primitive.m_index_buffer.getOffset() ) };
assert( primitive.m_index_buffer.size() > 0 );

View File

@@ -28,7 +28,10 @@ namespace fgl::engine
}
std::pair< std::vector< vk::DrawIndexedIndirectCommand >, std::vector< ModelMatrixInfo > > getDrawCallsFromTree(
OctTreeNode& root, const Frustum< CoordinateSpace::World >& frustum, const GameObjectFlagType flags );
OctTreeNode& root,
const Frustum< CoordinateSpace::World >& frustum,
const GameObjectFlagType flags,
const GameObjectFilterOptions options = NONE );
} // namespace fgl::engine

View File

@@ -36,8 +36,14 @@ namespace fgl::engine
info.subpass = 0;
m_pipeline = std::make_unique< Pipeline >( m_device, info );
m_pipeline->setDebugName( "Entity pipeline" );
//m_pipeline = std::make_unique< Pipeline >( m_device, info );
//m_pipeline->setDebugName( "Entity pipeline" );
m_standard_pipeline = std::make_unique< StandardPipeline >( m_device, info );
m_textured_pipeline = std::make_unique< TexturedPipeline >( m_device, info );
m_standard_pipeline->setDebugName( "Standard entity pipeline" );
m_textured_pipeline->setDebugName( "Textured entity pipeline" );
using namespace fgl::literals::size_literals;
@@ -49,10 +55,14 @@ namespace fgl::engine
vk::CommandBuffer& EntityRendererSystem::setupSystem( FrameInfo& info )
{
auto& command_buffer { info.command_buffer };
m_pipeline->bind( command_buffer );
m_pipeline->bindDescriptor( command_buffer, 0, info.global_descriptor_set );
m_pipeline->bindDescriptor( command_buffer, 1, Texture::getTextureDescriptorSet() );
//This function becomes a dummy since we have multiple pipelines.
//We will instead bind the pipeline and descriptors for each stage of this pass.
//m_pipeline->bind( command_buffer );
//m_pipeline->bindDescriptor( command_buffer, 0, info.global_descriptor_set );
//m_pipeline->bindDescriptor( command_buffer, 1, Texture::getTextureDescriptorSet() );
return command_buffer;
}
@@ -63,6 +73,10 @@ namespace fgl::engine
auto& command_buffer { setupSystem( info ) };
TracyVkZone( info.tracy_ctx, command_buffer, "Render entities" );
texturelessPass( info );
//texturedPass( info );
/*
auto [ draw_commands, model_matricies ] =
getDrawCallsFromTree( info.game_objects, info.camera_frustum, IS_VISIBLE | IS_ENTITY );
@@ -101,6 +115,51 @@ namespace fgl::engine
command_buffer.drawIndexedIndirect(
draw_params->getVkBuffer(), draw_params->getOffset(), draw_params->size(), draw_params->stride() );
*/
}
void EntityRendererSystem::texturelessPass( FrameInfo& info )
{
ZoneScopedN( "Textureless pass" );
auto& command_buffer { info.command_buffer };
TracyVkZone( info.tracy_ctx, command_buffer, "Render textureless entities" );
//Bind pipeline
m_standard_pipeline->bind( command_buffer );
//Bind only descriptor we need.
m_standard_pipeline
->bindDescriptor( command_buffer, GlobalDescriptorSet::m_set_idx, info.global_descriptor_set );
//Get all commands for drawing anything without a texture
auto [ draw_commands, model_matricies ] =
getDrawCallsFromTree( info.game_objects, info.camera_frustum, IS_VISIBLE | IS_ENTITY, TEXTURELESS );
//TODO: Filter Textureless models (#6)
if ( draw_commands.size() == 0 ) return;
auto& model_matrix_info_buffer { m_simple_model_matrix_info_buffers[ info.frame_idx ] };
model_matrix_info_buffer =
std::make_unique< ModelMatrixInfoBufferSuballocation >( info.model_matrix_info_buffer, model_matricies );
auto& draw_parameter_buffer { m_draw_simple_parameter_buffers[ info.frame_idx ] };
draw_parameter_buffer =
std::make_unique< DrawParameterBufferSuballocation >( info.draw_parameter_buffer, draw_commands );
const std::vector< vk::Buffer > vert_buffers { m_vertex_buffer->getVkBuffer(),
model_matrix_info_buffer->getVkBuffer() };
command_buffer.bindVertexBuffers( 0, vert_buffers, { 0, model_matrix_info_buffer->getOffset() } );
command_buffer.bindIndexBuffer( m_index_buffer->getVkBuffer(), 0, vk::IndexType::eUint32 );
command_buffer.drawIndexedIndirect(
draw_parameter_buffer->getVkBuffer(),
draw_parameter_buffer->getOffset(),
draw_parameter_buffer->size(),
draw_parameter_buffer->stride() );
}
} // namespace fgl::engine

View File

@@ -5,13 +5,13 @@
#pragma once
#include <memory>
#include <vector>
#include "engine/GameObject.hpp"
#include "engine/descriptors/DescriptorSetCollection.hpp"
#include "engine/model/Model.hpp"
#include "engine/pipeline/PipelineT.hpp"
#include "engine/rendering/SwapChain.hpp"
#include "engine/systems/modelRendering/StandardPipeline.hpp"
#include "engine/systems/modelRendering/TexturedPipeline.hpp"
namespace fgl::engine
{
@@ -23,6 +23,7 @@ namespace fgl::engine
{
Device& m_device;
/*
using VertexShader = VertexShaderT< "shaders/gbuffer.vert.spv" >;
using FragmentShader = FragmentShaderT< "shaders/gbuffer.frag.spv" >;
using Shaders = ShaderCollection< VertexShader, FragmentShader >;
@@ -32,6 +33,13 @@ namespace fgl::engine
using Pipeline = PipelineT< Shaders, DescriptorSets >;
std::unique_ptr< Pipeline > m_pipeline {};
*/
//! Standard pipeline for textureless models
std::unique_ptr< StandardPipeline > m_standard_pipeline {};
//! Pipeline for basic textured models (Single texture)
std::unique_ptr< TexturedPipeline > m_textured_pipeline {};
std::unique_ptr< Buffer > m_vertex_buffer { nullptr };
std::unique_ptr< Buffer > m_index_buffer { nullptr };
@@ -40,11 +48,16 @@ namespace fgl::engine
using ModelMatrixInfoBufferSuballocation = HostVector< ModelMatrixInfo >;
std::array< std::unique_ptr< DrawParameterBufferSuballocation >, SwapChain::MAX_FRAMES_IN_FLIGHT >
m_draw_parameter_buffers {};
template < typename T >
using PerFrameArray = std::array< T, SwapChain::MAX_FRAMES_IN_FLIGHT >;
std::array< std::unique_ptr< ModelMatrixInfoBufferSuballocation >, SwapChain::MAX_FRAMES_IN_FLIGHT >
m_model_matrix_info_buffers {};
// Simple parameter buffers
PerFrameArray< std::unique_ptr< DrawParameterBufferSuballocation > > m_draw_simple_parameter_buffers {};
PerFrameArray< std::unique_ptr< ModelMatrixInfoBufferSuballocation > > m_simple_model_matrix_info_buffers {};
// Textured parameter buffers
PerFrameArray< std::unique_ptr< DrawParameterBufferSuballocation > > m_draw_textured_parameter_buffers {};
PerFrameArray< std::unique_ptr< ModelMatrixInfoBufferSuballocation > > m_textured_model_matrix_info_buffers {};
void initVertexBuffer( std::uint32_t size )
{
@@ -71,6 +84,8 @@ namespace fgl::engine
Buffer& getIndexBuffer() { return *m_index_buffer; }
void pass( FrameInfo& info );
void texturelessPass( FrameInfo& info );
void texturedPass( FrameInfo& info );
EntityRendererSystem( Device& device, VkRenderPass render_pass );
~EntityRendererSystem() = default;

View File

@@ -2,8 +2,9 @@
// Created by kj16609 on 3/11/24.
//
#ifndef GAME_CONCEPTS_HPP
#define GAME_CONCEPTS_HPP
#pragma once
#include <concepts>
namespace vk
{
@@ -37,5 +38,3 @@ namespace fgl::engine
};
} // namespace fgl::engine
#endif //GAME_CONCEPTS_HPP

View File

@@ -0,0 +1,23 @@
//
// Created by kj16609 on 5/24/24.
//
#pragma once
#include "engine/FrameInfo.hpp"
#include "engine/descriptors/DescriptorSetCollection.hpp"
#include "engine/pipeline/PipelineT.hpp"
#include "engine/pipeline/Shader.hpp"
namespace fgl::engine
{
using StandardPipelineVertexShader = VertexShaderT< "shaders/textureless-gbuffer.vert.spv" >;
using StandardPipelineFragShader = FragmentShaderT< "shaders/textureless-gbuffer.frag.spv" >;
using StandardPipelineShaders = ShaderCollection< StandardPipelineVertexShader, StandardPipelineFragShader >;
using StandardPipelineDescriptorSets = DescriptorSetCollection< GlobalDescriptorSet >;
//! The standard pipeline is used for models without any form of texturing. They instead rely on Vertex coloring. A UV map is **NOT** expected
using StandardPipeline = PipelineT< StandardPipelineShaders, StandardPipelineDescriptorSets >;
} // namespace fgl::engine

View File

@@ -0,0 +1,23 @@
//
// Created by kj16609 on 5/24/24.
//
#pragma once
#include "engine/FrameInfo.hpp"
#include "engine/descriptors/DescriptorSetCollection.hpp"
#include "engine/pipeline/PipelineT.hpp"
#include "engine/pipeline/Shader.hpp"
namespace fgl::engine
{
using TexturedPipelineVertexShader = VertexShaderT< "shaders/textured-gbuffer.vert.spv" >;
using TexturedPipelineFragShader = FragmentShaderT< "shaders/textured-gbuffer.frag.spv" >;
using TexturedPipelineShaders = ShaderCollection< TexturedPipelineVertexShader, TexturedPipelineFragShader >;
using TexturedPipelineDescriptorSets = DescriptorSetCollection< GlobalDescriptorSet, TextureDescriptorSet >;
//! The standard pipeline is used for models without any form of texturing. They instead rely on Vertex coloring. A UV map is **NOT** expected
using TexturedPipeline = PipelineT< TexturedPipelineShaders, TexturedPipelineDescriptorSets >;
} // namespace fgl::engine

View File

@@ -0,0 +1,13 @@
| Name | Textured | Normal Textured |
|------------------|----------|-----------------|
| StandardPipeline | [ ] | [ ] |
| TexturedPipeline | [x] | [ ] |

View File

@@ -30,7 +30,7 @@ namespace fgl::engine
[[nodiscard]] Texture( const std::vector< std::byte >& data, const int x, const int y, const int channels );
[[nodiscard]] Texture( const std::vector< std::byte >& data, const vk::Extent2D extent, const int channels );
Texture( const Texture& ) = delete;
Texture( const Texture& ) = default;
Texture& operator=( const Texture& ) = delete;
Texture( Texture&& other ) = default;

View File

@@ -7,6 +7,7 @@
#define GLM_ENABLE_EXPERIMENTAL
#include <engine/FrameInfo.hpp>
#include <glm/gtx/string_cast.hpp>
#include <imgui/imgui.h>
#include "engine/debug/drawers.hpp"
#include "engine/model/Model.hpp"
@@ -208,6 +209,7 @@ namespace fgl::engine
else
{
objects.emplace_back( std::move( obj ) );
spdlog::info( "Added object" );
return this;
}
}

View File

@@ -4,6 +4,8 @@
#pragma once
#include <tracy/Tracy.hpp>
#include <bitset>
#include <functional>

View File

@@ -5,6 +5,7 @@
#pragma once
#include "engine/GameObject.hpp"
#include <vector>
namespace fgl::engine
{

View File

@@ -48,6 +48,10 @@ Index of this file:
*/
#pragma once
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wconversion"
// Configuration file with compile-time options
// (edit imconfig.h or '#define IMGUI_USER_CONFIG "myfilename.h" from your build system)
@@ -5346,3 +5350,5 @@ enum ImGuiModFlags_
#endif
#endif // #ifndef IMGUI_DISABLE
#pragma GCC diagnostic pop