diff --git a/cmake_modules/dependencies/spdlog.cmake b/cmake_modules/dependencies/spdlog.cmake index 258ae0d..1c0c90e 100644 --- a/cmake_modules/dependencies/spdlog.cmake +++ b/cmake_modules/dependencies/spdlog.cmake @@ -1 +1 @@ -add_subdirectory(${CMAKE_SOURCE_DIR}/dependencies/spdlog) +add_subdirectory(${CMAKE_SOURCE_DIR}/dependencies/spdlog ${CMAKE_BINARY_DIR}/bin) diff --git a/cmake_modules/gcc.cmake b/cmake_modules/gcc.cmake index 8097ae2..adccf66 100644 --- a/cmake_modules/gcc.cmake +++ b/cmake_modules/gcc.cmake @@ -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 diff --git a/dependencies/spdlog b/dependencies/spdlog new file mode 160000 index 0000000..c3aed4b --- /dev/null +++ b/dependencies/spdlog @@ -0,0 +1 @@ +Subproject commit c3aed4b68373955e1cc94307683d44dca1515d2b diff --git a/shaders/gbuffer.frag b/shaders/textured-gbuffer.frag similarity index 90% rename from shaders/gbuffer.frag rename to shaders/textured-gbuffer.frag index 15337f4..c1b1057 100644 --- a/shaders/gbuffer.frag +++ b/shaders/textured-gbuffer.frag @@ -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); } \ No newline at end of file diff --git a/shaders/gbuffer.vert b/shaders/textured-gbuffer.vert similarity index 100% rename from shaders/gbuffer.vert rename to shaders/textured-gbuffer.vert diff --git a/shaders/textureless-gbuffer.frag b/shaders/textureless-gbuffer.frag new file mode 100644 index 0000000..9b9608f --- /dev/null +++ b/shaders/textureless-gbuffer.frag @@ -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); +} \ No newline at end of file diff --git a/shaders/textureless-gbuffer.vert b/shaders/textureless-gbuffer.vert new file mode 100644 index 0000000..df9f76c --- /dev/null +++ b/shaders/textureless-gbuffer.vert @@ -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; +} \ No newline at end of file diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2e3580c..7ffe2b5 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -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) \ No newline at end of file diff --git a/src/core/main.cpp b/src/core/main.cpp index beb3e0c..8fdf9e7 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -5,9 +5,12 @@ #include #include "engine/EngineContext.hpp" +#include "engine/logging.hpp" int main() { + spdlog::set_level( spdlog::level::debug ); + fgl::engine::EngineContext engine_ctx {}; engine_ctx.run(); diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index 924a25e..15e6394 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -25,6 +25,7 @@ target_precompile_headers(FGLEngine PRIVATE + @@ -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) diff --git a/src/engine/EngineContext.cpp b/src/engine/EngineContext.cpp index d670fae..36fea7d 100644 --- a/src/engine/EngineContext.cpp +++ b/src/engine/EngineContext.cpp @@ -7,20 +7,9 @@ #include #include -#include #include #include -#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() ) diff --git a/src/engine/GameObject.cpp b/src/engine/GameObject.cpp index e9e2ccf..e619b68 100644 --- a/src/engine/GameObject.cpp +++ b/src/engine/GameObject.cpp @@ -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(); } diff --git a/src/engine/GameObject.hpp b/src/engine/GameObject.hpp index 1cc0d02..8a9f05b 100644 --- a/src/engine/GameObject.hpp +++ b/src/engine/GameObject.hpp @@ -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; diff --git a/src/engine/allocators/globalAllocator.cpp b/src/engine/allocators/globalAllocator.cpp index 5cb00e4..9de3703 100644 --- a/src/engine/allocators/globalAllocator.cpp +++ b/src/engine/allocators/globalAllocator.cpp @@ -2,6 +2,10 @@ // Created by kj16609 on 3/11/24. // +#include + +#include +#include #if TRACY_ENABLE void* operator new( std::size_t count ) diff --git a/src/engine/buffers/vector/DeviceVector.hpp b/src/engine/buffers/vector/DeviceVector.hpp index 327c844..3e2b830 100644 --- a/src/engine/buffers/vector/DeviceVector.hpp +++ b/src/engine/buffers/vector/DeviceVector.hpp @@ -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" ); } diff --git a/src/engine/concepts/is_attachment.hpp b/src/engine/concepts/is_attachment.hpp index f43a60f..0c0d998 100644 --- a/src/engine/concepts/is_attachment.hpp +++ b/src/engine/concepts/is_attachment.hpp @@ -4,6 +4,8 @@ #pragma once +#include + namespace fgl::engine { class ImageView; diff --git a/src/engine/debug/drawers.cpp b/src/engine/debug/drawers.cpp index 2d33042..1e046ff 100644 --- a/src/engine/debug/drawers.cpp +++ b/src/engine/debug/drawers.cpp @@ -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 + #include "tracy_colors.hpp" #if ENABLE_IMGUI_DRAWERS diff --git a/src/engine/descriptors/createDescriptorSets.hpp b/src/engine/descriptors/createDescriptorSets.hpp index 05cc248..e14c636 100644 --- a/src/engine/descriptors/createDescriptorSets.hpp +++ b/src/engine/descriptors/createDescriptorSets.hpp @@ -5,6 +5,7 @@ #pragma once #include +#include #include "engine/concepts/is_valid_pipeline_input.hpp" diff --git a/src/engine/logging.hpp b/src/engine/logging.hpp new file mode 100644 index 0000000..78317e5 --- /dev/null +++ b/src/engine/logging.hpp @@ -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 +#pragma GCC diagnostic pop diff --git a/src/engine/math/noise/perlin/generator.cpp b/src/engine/math/noise/perlin/generator.cpp index 74bb430..975efba 100644 --- a/src/engine/math/noise/perlin/generator.cpp +++ b/src/engine/math/noise/perlin/generator.cpp @@ -4,6 +4,9 @@ #include "generator.hpp" +#include + +#include #include namespace fgl::engine diff --git a/src/engine/math/noise/perlin/generator.hpp b/src/engine/math/noise/perlin/generator.hpp index 6daccd9..c8f25d7 100644 --- a/src/engine/math/noise/perlin/generator.hpp +++ b/src/engine/math/noise/perlin/generator.hpp @@ -3,7 +3,10 @@ // #pragma once -#include + +#include + +#include namespace fgl::engine { diff --git a/src/engine/model/Model.cpp b/src/engine/model/Model.cpp index 712c891..8f51288 100644 --- a/src/engine/model/Model.cpp +++ b/src/engine/model/Model.cpp @@ -5,19 +5,13 @@ #include "Model.hpp" #include -#include - -#define GLM_ENABLE_EXPERIMENTAL -#include - #include -#include +#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 \ No newline at end of file diff --git a/src/engine/model/Model.hpp b/src/engine/model/Model.hpp index b80f267..7e2b6f5 100644 --- a/src/engine/model/Model.hpp +++ b/src/engine/model/Model.hpp @@ -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; diff --git a/src/engine/model/Primitive.cpp b/src/engine/model/Primitive.cpp new file mode 100644 index 0000000..e9af86a --- /dev/null +++ b/src/engine/model/Primitive.cpp @@ -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 diff --git a/src/engine/model/Primitive.hpp b/src/engine/model/Primitive.hpp index 81a7524..56da288 100644 --- a/src/engine/model/Primitive.hpp +++ b/src/engine/model/Primitive.hpp @@ -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 diff --git a/src/engine/model/builders/ModelBuilder.cpp b/src/engine/model/builders/ModelBuilder.cpp new file mode 100644 index 0000000..b02df99 --- /dev/null +++ b/src/engine/model/builders/ModelBuilder.cpp @@ -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 \ No newline at end of file diff --git a/src/engine/model/builders/ModelBuilder.hpp b/src/engine/model/builders/ModelBuilder.hpp new file mode 100644 index 0000000..3fb0a3f --- /dev/null +++ b/src/engine/model/builders/ModelBuilder.hpp @@ -0,0 +1,36 @@ +// +// Created by kj16609 on 5/18/24. +// + +#pragma once + +#include +#include + +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 \ No newline at end of file diff --git a/src/engine/model/builders/SceneBuilder.cpp b/src/engine/model/builders/SceneBuilder.cpp new file mode 100644 index 0000000..9a414bf --- /dev/null +++ b/src/engine/model/builders/SceneBuilder.cpp @@ -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 + +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 diff --git a/src/engine/model/builders/SceneBuilder.hpp b/src/engine/model/builders/SceneBuilder.hpp new file mode 100644 index 0000000..ffc1608 --- /dev/null +++ b/src/engine/model/builders/SceneBuilder.hpp @@ -0,0 +1,75 @@ +// +// Created by kj16609 on 5/18/24. +// + +#pragma once + +#include +#include + +#include +#include + +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 \ No newline at end of file diff --git a/src/engine/model/gltfLoading.cpp b/src/engine/model/builders/loadGltf.cpp similarity index 77% rename from src/engine/model/gltfLoading.cpp rename to src/engine/model/builders/loadGltf.cpp index c945348..2f91344 100644 --- a/src/engine/model/gltfLoading.cpp +++ b/src/engine/model/builders/loadGltf.cpp @@ -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 diff --git a/src/engine/model/objLoading.cpp b/src/engine/model/builders/loadObj.cpp similarity index 91% rename from src/engine/model/objLoading.cpp rename to src/engine/model/builders/loadObj.cpp index 68ac598..e39e069 100644 --- a/src/engine/model/objLoading.cpp +++ b/src/engine/model/builders/loadObj.cpp @@ -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 #pragma GCC diagnostic pop -#include "Vertex.hpp" +#include + +#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; } diff --git a/src/engine/pipeline/PipelineConfigInfo.cpp b/src/engine/pipeline/PipelineConfigInfo.cpp index a227abf..3c3b244 100644 --- a/src/engine/pipeline/PipelineConfigInfo.cpp +++ b/src/engine/pipeline/PipelineConfigInfo.cpp @@ -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; diff --git a/src/engine/pipeline/PipelineConfigInfo.hpp b/src/engine/pipeline/PipelineConfigInfo.hpp index c163c1c..bdee37b 100644 --- a/src/engine/pipeline/PipelineConfigInfo.hpp +++ b/src/engine/pipeline/PipelineConfigInfo.hpp @@ -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 \ No newline at end of file diff --git a/src/engine/pipeline/Shader.hpp b/src/engine/pipeline/Shader.hpp index 3442055..2134ed2 100644 --- a/src/engine/pipeline/Shader.hpp +++ b/src/engine/pipeline/Shader.hpp @@ -2,11 +2,12 @@ // Created by kj16609 on 3/13/24. // -#ifndef SHADER_HPP -#define SHADER_HPP +#pragma once #include +#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 diff --git a/src/engine/primitives/Rotation.hpp b/src/engine/primitives/Rotation.hpp index 145808c..776ed18 100644 --- a/src/engine/primitives/Rotation.hpp +++ b/src/engine/primitives/Rotation.hpp @@ -10,6 +10,7 @@ #include #pragma GCC diagnostic pop +#include #include #include "engine/primitives/matricies/RotationMatrix.hpp" diff --git a/src/engine/primitives/TransformComponent.hpp b/src/engine/primitives/TransformComponent.hpp index 1dee7a2..bf3d96d 100644 --- a/src/engine/primitives/TransformComponent.hpp +++ b/src/engine/primitives/TransformComponent.hpp @@ -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 }; diff --git a/src/engine/primitives/boxes/AxisAlignedBoundingBox.cpp b/src/engine/primitives/boxes/AxisAlignedBoundingBox.cpp index 017e76a..ca76bb3 100644 --- a/src/engine/primitives/boxes/AxisAlignedBoundingBox.cpp +++ b/src/engine/primitives/boxes/AxisAlignedBoundingBox.cpp @@ -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 > diff --git a/src/engine/primitives/boxes/OrientedBoundingBox.cpp b/src/engine/primitives/boxes/OrientedBoundingBox.cpp index 8a68c57..6ebf85e 100644 --- a/src/engine/primitives/boxes/OrientedBoundingBox.cpp +++ b/src/engine/primitives/boxes/OrientedBoundingBox.cpp @@ -4,8 +4,11 @@ #include "OrientedBoundingBox.hpp" +#include + #include +#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) diff --git a/src/engine/primitives/boxes/OrientedBoundingBox.hpp b/src/engine/primitives/boxes/OrientedBoundingBox.hpp index 0482823..4caf547 100644 --- a/src/engine/primitives/boxes/OrientedBoundingBox.hpp +++ b/src/engine/primitives/boxes/OrientedBoundingBox.hpp @@ -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 ); } diff --git a/src/engine/primitives/lines/LineBase.cpp b/src/engine/primitives/lines/LineBase.cpp index 7543178..b02ada0 100644 --- a/src/engine/primitives/lines/LineBase.cpp +++ b/src/engine/primitives/lines/LineBase.cpp @@ -4,6 +4,8 @@ #include "LineBase.hpp" +#include + namespace fgl::engine { diff --git a/src/engine/primitives/lines/LineBase.hpp b/src/engine/primitives/lines/LineBase.hpp index 1c165c6..ed6c195 100644 --- a/src/engine/primitives/lines/LineBase.hpp +++ b/src/engine/primitives/lines/LineBase.hpp @@ -4,6 +4,8 @@ #pragma once +#include + namespace fgl::engine { diff --git a/src/engine/primitives/points/Coordinate.hpp b/src/engine/primitives/points/Coordinate.hpp index 0b8d754..a38ed05 100644 --- a/src/engine/primitives/points/Coordinate.hpp +++ b/src/engine/primitives/points/Coordinate.hpp @@ -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 diff --git a/src/engine/primitives/vectors/NormalVector.hpp b/src/engine/primitives/vectors/NormalVector.hpp index ed45d6f..7724be8 100644 --- a/src/engine/primitives/vectors/NormalVector.hpp +++ b/src/engine/primitives/vectors/NormalVector.hpp @@ -4,6 +4,7 @@ #pragma once +#include #include #include "engine/primitives/CoordinateSpace.hpp" diff --git a/src/engine/rendering/Device.cpp b/src/engine/rendering/Device.cpp index 952a5c3..7631166 100644 --- a/src/engine/rendering/Device.cpp +++ b/src/engine/rendering/Device.cpp @@ -8,6 +8,8 @@ #include #include +#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 ) ) diff --git a/src/engine/systems/CompositionSystem.cpp b/src/engine/systems/CompositionSystem.cpp index 6795f67..7408343 100644 --- a/src/engine/systems/CompositionSystem.cpp +++ b/src/engine/systems/CompositionSystem.cpp @@ -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 ); diff --git a/src/engine/systems/CullingSystem.cpp b/src/engine/systems/CullingSystem.cpp index 348ad83..9e93ac3 100644 --- a/src/engine/systems/CullingSystem.cpp +++ b/src/engine/systems/CullingSystem.cpp @@ -4,6 +4,7 @@ #include "CullingSystem.hpp" +#include #include #include "engine/FrameInfo.hpp" diff --git a/src/engine/systems/DrawPair.cpp b/src/engine/systems/DrawPair.cpp index 897809b..abbeb77 100644 --- a/src/engine/systems/DrawPair.cpp +++ b/src/engine/systems/DrawPair.cpp @@ -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 ); diff --git a/src/engine/systems/DrawPair.hpp b/src/engine/systems/DrawPair.hpp index ee151fa..d14f414 100644 --- a/src/engine/systems/DrawPair.hpp +++ b/src/engine/systems/DrawPair.hpp @@ -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 diff --git a/src/engine/systems/EntityRendererSystem.cpp b/src/engine/systems/EntityRendererSystem.cpp index f9b9682..1cbdd14 100644 --- a/src/engine/systems/EntityRendererSystem.cpp +++ b/src/engine/systems/EntityRendererSystem.cpp @@ -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 diff --git a/src/engine/systems/EntityRendererSystem.hpp b/src/engine/systems/EntityRendererSystem.hpp index dce1cb9..b148bfc 100644 --- a/src/engine/systems/EntityRendererSystem.hpp +++ b/src/engine/systems/EntityRendererSystem.hpp @@ -5,13 +5,13 @@ #pragma once #include -#include -#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; diff --git a/src/engine/systems/concepts.hpp b/src/engine/systems/concepts.hpp index 4acbff4..50cf09c 100644 --- a/src/engine/systems/concepts.hpp +++ b/src/engine/systems/concepts.hpp @@ -2,8 +2,9 @@ // Created by kj16609 on 3/11/24. // -#ifndef GAME_CONCEPTS_HPP -#define GAME_CONCEPTS_HPP +#pragma once + +#include namespace vk { @@ -37,5 +38,3 @@ namespace fgl::engine }; } // namespace fgl::engine - -#endif //GAME_CONCEPTS_HPP diff --git a/src/engine/systems/modelRendering/StandardPipeline.hpp b/src/engine/systems/modelRendering/StandardPipeline.hpp new file mode 100644 index 0000000..3367738 --- /dev/null +++ b/src/engine/systems/modelRendering/StandardPipeline.hpp @@ -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 diff --git a/src/engine/systems/modelRendering/TexturedPipeline.hpp b/src/engine/systems/modelRendering/TexturedPipeline.hpp new file mode 100644 index 0000000..cb82e7c --- /dev/null +++ b/src/engine/systems/modelRendering/TexturedPipeline.hpp @@ -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 diff --git a/src/engine/systems/modelRendering/pipelines.md b/src/engine/systems/modelRendering/pipelines.md new file mode 100644 index 0000000..f66b1d3 --- /dev/null +++ b/src/engine/systems/modelRendering/pipelines.md @@ -0,0 +1,13 @@ +| Name | Textured | Normal Textured | +|------------------|----------|-----------------| +| StandardPipeline | [ ] | [ ] | +| TexturedPipeline | [x] | [ ] | + + + + + + + + + diff --git a/src/engine/texture/Texture.hpp b/src/engine/texture/Texture.hpp index 36c941f..f51a22c 100644 --- a/src/engine/texture/Texture.hpp +++ b/src/engine/texture/Texture.hpp @@ -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; diff --git a/src/engine/tree/octtree/OctTreeNode.cpp b/src/engine/tree/octtree/OctTreeNode.cpp index f3f1411..fdc682c 100644 --- a/src/engine/tree/octtree/OctTreeNode.cpp +++ b/src/engine/tree/octtree/OctTreeNode.cpp @@ -7,6 +7,7 @@ #define GLM_ENABLE_EXPERIMENTAL #include #include +#include #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; } } diff --git a/src/engine/tree/octtree/OctTreeNode.hpp b/src/engine/tree/octtree/OctTreeNode.hpp index ef838df..ab52973 100644 --- a/src/engine/tree/octtree/OctTreeNode.hpp +++ b/src/engine/tree/octtree/OctTreeNode.hpp @@ -4,6 +4,8 @@ #pragma once +#include + #include #include diff --git a/src/engine/tree/quadtree/QuadTree.hpp b/src/engine/tree/quadtree/QuadTree.hpp index d2368d0..4ac74b6 100644 --- a/src/engine/tree/quadtree/QuadTree.hpp +++ b/src/engine/tree/quadtree/QuadTree.hpp @@ -5,6 +5,7 @@ #pragma once #include "engine/GameObject.hpp" +#include namespace fgl::engine { diff --git a/src/imgui/imgui.h b/src/imgui/imgui.h index 948836d..74c92af 100644 --- a/src/imgui/imgui.h +++ b/src/imgui/imgui.h @@ -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