diff --git a/.gitmodules b/.gitmodules index 41bfa3b..3de9eb8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -40,3 +40,15 @@ [submodule "dependencies/imgui"] path = dependencies/imgui url = https://github.com/ocornut/imgui.git +[submodule "dependencies/shaderc"] + path = dependencies/shaderc + url = https://github.com/google/shaderc.git +[submodule "dependencies/SPIRV-Tools"] + path = dependencies/SPIRV-Tools + url = https://github.com/KhronosGroup/SPIRV-Tools.git +[submodule "dependencies/SPIRV-Headers"] + path = dependencies/SPIRV-Headers + url = https://github.com/KhronosGroup/SPIRV-Headers.git +[submodule "dependencies/glslang"] + path = dependencies/glslang + url = https://github.com/KhronosGroup/glslang.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 51d0349..5477086 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ include(dependencies/glm) include(cmake_modules/dependencies/tracy.cmake) include(dependencies/vulkan) include(dependencies/catch2) +include(dependencies/shaderc) add_subdirectory(src) diff --git a/cmake_modules/dependencies/shaderc.cmake b/cmake_modules/dependencies/shaderc.cmake new file mode 100644 index 0000000..7c659b9 --- /dev/null +++ b/cmake_modules/dependencies/shaderc.cmake @@ -0,0 +1,8 @@ +#set(SPIRV-Headers_SOURCE_DIR ${CMAKE_SOURCE_DIR}/dependencies/SPIRV-Headers) + +add_subdirectory(${CMAKE_SOURCE_DIR}/dependencies/SPIRV-Headers) +add_subdirectory(${CMAKE_SOURCE_DIR}/dependencies/SPIRV-Tools) +add_subdirectory(${CMAKE_SOURCE_DIR}/dependencies/glslang) + +set(SHADERC_SKIP_TESTS ON) +add_subdirectory(${CMAKE_SOURCE_DIR}/dependencies/shaderc) \ No newline at end of file diff --git a/dependencies/SPIRV-Headers b/dependencies/SPIRV-Headers new file mode 160000 index 0000000..f013f08 --- /dev/null +++ b/dependencies/SPIRV-Headers @@ -0,0 +1 @@ +Subproject commit f013f08e4455bcc1f0eed8e3dd5e2009682656d9 diff --git a/dependencies/SPIRV-Tools b/dependencies/SPIRV-Tools new file mode 160000 index 0000000..246daf2 --- /dev/null +++ b/dependencies/SPIRV-Tools @@ -0,0 +1 @@ +Subproject commit 246daf246bb17336afcf4482680bba434b1e5557 diff --git a/dependencies/glslang b/dependencies/glslang new file mode 160000 index 0000000..e40c14a --- /dev/null +++ b/dependencies/glslang @@ -0,0 +1 @@ +Subproject commit e40c14a3e007fac0e4f2e4164fdf14d1712355bd diff --git a/dependencies/shaderc b/dependencies/shaderc new file mode 160000 index 0000000..5d0f6ed --- /dev/null +++ b/dependencies/shaderc @@ -0,0 +1 @@ +Subproject commit 5d0f6ed6e46d3c0ccd23151c6a1486c2ec90c037 diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index a6cc6d7..886b60d 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -33,7 +33,7 @@ target_compile_definitions(FGLEngine PUBLIC VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC include(dependencies/spdlog) include(dependencies/imgui) -target_link_libraries(FGLEngine PUBLIC Vulkan::Vulkan glfw glm ImGui Tracy::TracyClient VMA FGLLoader spdlog) +target_link_libraries(FGLEngine PUBLIC Vulkan::Vulkan glfw glm ImGui Tracy::TracyClient VMA FGLLoader spdlog shaderc) 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/descriptors/DescriptorSet.cpp b/src/engine/descriptors/DescriptorSet.cpp index d2979d4..7fb85fb 100644 --- a/src/engine/descriptors/DescriptorSet.cpp +++ b/src/engine/descriptors/DescriptorSet.cpp @@ -100,8 +100,6 @@ namespace fgl::engine::descriptors m_infos[ binding_idx ] = tex.getImageView().descriptorInfo( tex.getImageView().getSampler().getVkSampler(), vk::ImageLayout::eShaderReadOnlyOptimal ); - log::info( "Bound texture {} to global texture array", tex.getID() ); - vk::WriteDescriptorSet write {}; write.dstSet = m_set; write.dstBinding = binding_idx; @@ -110,8 +108,6 @@ namespace fgl::engine::descriptors write.descriptorType = vk::DescriptorType::eCombinedImageSampler; write.pImageInfo = &( std::get< vk::DescriptorImageInfo >( m_infos.data()[ binding_idx ] ) ); - std::cout << "Bound texture: " << tex.getID() << std::endl; - descriptor_writes.push_back( write ); } diff --git a/src/engine/model/Model.hpp b/src/engine/model/Model.hpp index 1029cdc..8a24346 100644 --- a/src/engine/model/Model.hpp +++ b/src/engine/model/Model.hpp @@ -30,7 +30,9 @@ namespace fgl::engine struct ModelMatrixInfo { glm::mat4 model_matrix; - std::uint32_t texture_idx; + std::uint32_t albedo_id; + std::uint32_t normal_id; + std::uint32_t metallic_roughness; }; class Model diff --git a/src/engine/model/Primitive.cpp b/src/engine/model/Primitive.cpp index 4171392..a33a6f7 100644 --- a/src/engine/model/Primitive.cpp +++ b/src/engine/model/Primitive.cpp @@ -26,7 +26,15 @@ namespace fgl::engine if ( m_textures.albedo ) return m_textures.albedo->getID(); else - return std::numeric_limits< TextureID >::max(); + return INVALID_TEXTURE_ID; + } + + TextureID Primitive::getNormalTextureID() const + { + if ( m_textures.normal ) + return m_textures.normal->getID(); + else + return INVALID_TEXTURE_ID; } } // namespace fgl::engine diff --git a/src/engine/model/Primitive.hpp b/src/engine/model/Primitive.hpp index e9357df..26a19b8 100644 --- a/src/engine/model/Primitive.hpp +++ b/src/engine/model/Primitive.hpp @@ -40,6 +40,7 @@ namespace fgl::engine { std::shared_ptr< Texture > albedo { nullptr }; std::shared_ptr< Texture > normal { nullptr }; + std::shared_ptr< Texture > metallic_roughness { nullptr }; bool hasTextures() const { return albedo || normal; } @@ -55,6 +56,11 @@ namespace fgl::engine if ( !normal->ready() ) return false; } + if ( metallic_roughness ) + { + if ( !metallic_roughness->ready() ) return false; + } + return true; } }; @@ -112,6 +118,7 @@ namespace fgl::engine memory::Buffer& index_buffer ); TextureID getAlbedoTextureID() const; + TextureID getNormalTextureID() const; }; } // namespace fgl::engine diff --git a/src/engine/model/Vertex.cpp b/src/engine/model/Vertex.cpp index 747531c..7d92cfc 100644 --- a/src/engine/model/Vertex.cpp +++ b/src/engine/model/Vertex.cpp @@ -8,8 +8,8 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wduplicated-branches" -#include #include +#include #pragma GCC diagnostic pop #include "Model.hpp" @@ -50,8 +50,12 @@ namespace fgl::engine attribute_descriptions.emplace_back( 7, 1, vk::Format::eR32G32B32A32Sfloat, 3 * sizeof( glm::vec4 ) ); attribute_descriptions.emplace_back( 8, 1, vk::Format::eR32Uint, 4 * sizeof( glm::vec4 ) ); + attribute_descriptions.emplace_back( 9, 1, vk::Format::eR32Uint, 5 * sizeof( glm::vec4 ) ); + attribute_descriptions.emplace_back( 10, 1, vk::Format::eR32Uint, 6 * sizeof( glm::vec4 ) ); - static_assert( 4 * sizeof( glm::vec4 ) + sizeof( unsigned int ) == sizeof( ModelMatrixInfo ) ); + static_assert( + 4 * sizeof( glm::vec4 ) + sizeof( unsigned int ) + sizeof( unsigned int ) + sizeof( unsigned int ) + == sizeof( ModelMatrixInfo ) ); return attribute_descriptions; } diff --git a/src/engine/model/builders/SceneBuilder.cpp b/src/engine/model/builders/SceneBuilder.cpp index 2cc1825..c3ae4a6 100644 --- a/src/engine/model/builders/SceneBuilder.cpp +++ b/src/engine/model/builders/SceneBuilder.cpp @@ -179,11 +179,6 @@ namespace fgl::engine const tinygltf::Material& materials { root.materials[ mat_idx ] }; - for ( const auto& [ key, value ] : materials.values ) - { - log::debug( "Found key: {}", key ); - } - auto findParameter = [ &materials ]( const std::string name ) -> std::optional< tinygltf::Parameter > { const auto& itter { materials.values.find( name ) }; @@ -194,22 +189,41 @@ namespace fgl::engine return { itter->second }; }; - const auto albedo { findParameter( "baseColorTexture" ) }; - const auto normal { findParameter( "normalTexture" ) }; - const auto occlusion_texture { findParameter( "occlusionTexture" ) }; + std::string str; + + std::size_t counter { 0 }; + + for ( const auto& [ name, parameter ] : materials.values ) + { + str += name; + if ( counter + 1 != materials.values.size() ) str += ", "; + ++counter; + } + + log::debug( "Found materials: {}", str ); PrimitiveTextures textures {}; + const auto albedo { findParameter( "baseColorTexture" ) }; if ( albedo.has_value() ) { textures.albedo = getTextureForParameter( *albedo, root ); } + const auto normal { findParameter( "normalTexture" ) }; if ( normal.has_value() ) { textures.normal = getTextureForParameter( *normal, root ); } + const auto occlusion_texture { findParameter( "occlusionTexture" ) }; + + const auto mettalic_roughness_texture { findParameter( "mettalicRoughnessTexture" ) }; + if ( mettalic_roughness_texture.has_value() ) + { + textures.metallic_roughness = getTextureForParameter( *mettalic_roughness_texture, root ); + } + return textures; } @@ -290,7 +304,7 @@ namespace fgl::engine } log::debug( - "Found {} verts.\n\t- Has UV info: {}\n\t- Has normals: {}", + "Found {} verts. Has UV info: {}, Has normals: {}", verts.size(), has_uv ? "Yes" : "No", has_normals ? "Yes" : "No" ); @@ -301,12 +315,13 @@ namespace fgl::engine Primitive SceneBuilder::loadPrimitive( const tinygltf::Primitive& prim, const tinygltf::Model& root ) { ZoneScoped; - std::string att_str; + std::string att_str { "" }; for ( const auto& attrib : prim.attributes ) { - att_str += "Attribute: " + attrib.first + "\n"; + att_str += attrib.first + ", "; } - log::debug( "Attributes for primitive:\n{}", att_str ); + + log::debug( "Attributes for primitive: [{}]", att_str ); //TODO: Get normal colors from texture [[maybe_unused]] const bool has_normal { hasAttribute( prim, "NORMAL" ) }; diff --git a/src/engine/pipeline/Shader.cpp b/src/engine/pipeline/Shader.cpp index edf566a..4a8a6af 100644 --- a/src/engine/pipeline/Shader.cpp +++ b/src/engine/pipeline/Shader.cpp @@ -5,6 +5,7 @@ #include "Shader.hpp" #include "engine/rendering/Device.hpp" +#include "engine/shaders/Compiler.hpp" namespace fgl::engine { @@ -21,7 +22,9 @@ namespace fgl::engine ifs.read( reinterpret_cast< std::ifstream::char_type* >( data.data() ), data.size() ); - return data; + // We now need to compile the shader before we use it. + + return compileShader( path.filename().string(), data ); } else { @@ -40,7 +43,7 @@ namespace fgl::engine return module_info; } - ShaderHandle::ShaderHandle( const std::filesystem::path path, const vk::PipelineShaderStageCreateInfo info ) : + ShaderHandle::ShaderHandle( const std::filesystem::path& path, const vk::PipelineShaderStageCreateInfo& info ) : shader_data( loadData( path ) ), module_create_info( createModuleInfo() ), stage_info( info ), diff --git a/src/engine/pipeline/Shader.hpp b/src/engine/pipeline/Shader.hpp index 93b688e..9b0fe1e 100644 --- a/src/engine/pipeline/Shader.hpp +++ b/src/engine/pipeline/Shader.hpp @@ -42,7 +42,7 @@ namespace fgl::engine std::vector< std::byte > loadData( const std::filesystem::path& ); vk::ShaderModuleCreateInfo createModuleInfo(); - ShaderHandle( const std::filesystem::path path, const vk::PipelineShaderStageCreateInfo info ); + ShaderHandle( const std::filesystem::path& path, const vk::PipelineShaderStageCreateInfo& info ); ShaderHandle( const ShaderHandle& other ) = delete; diff --git a/src/engine/shaders/Compiler.cpp b/src/engine/shaders/Compiler.cpp index a1e60d6..165fd40 100644 --- a/src/engine/shaders/Compiler.cpp +++ b/src/engine/shaders/Compiler.cpp @@ -34,9 +34,12 @@ namespace fgl::engine throw std::runtime_error( "Unknown shader type!" ); } - std::vector< std::byte > compilerShader( const std::string_view input_name, std::vector< std::byte >& input ) + std::vector< std::byte > compileShader( const std::string_view input_name, const std::vector< std::byte >& input ) { shaderc::CompileOptions options; + + options.SetTargetEnvironment( shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_3 ); + #ifndef NDEBUG options.SetOptimizationLevel( shaderc_optimization_level_zero ); #else @@ -45,7 +48,7 @@ namespace fgl::engine const shaderc_shader_kind kind { getShaderKindFromName( input_name ) }; - const auto result { compiler->CompileGlslToSpvAssembly( + const auto result { getInstance().CompileGlslToSpv( reinterpret_cast< const char* >( input.data() ), input.size(), kind, input_name.data(), "main", options ) }; switch ( result.GetCompilationStatus() ) @@ -74,6 +77,8 @@ namespace fgl::engine break; } + log::debug( "Compiled shader {}", input_name ); + std::vector< std::byte > output {}; output.reserve( result.cend() - result.cbegin() ); @@ -87,6 +92,7 @@ namespace fgl::engine // Should be a multiple of 4 assert( output.size() % 4 == 0 ); + assert( output.size() > 0 ); return output; } diff --git a/src/engine/shaders/Compiler.hpp b/src/engine/shaders/Compiler.hpp index 2283411..ca09b15 100644 --- a/src/engine/shaders/Compiler.hpp +++ b/src/engine/shaders/Compiler.hpp @@ -11,6 +11,6 @@ namespace fgl::engine shaderc::Compiler& getInstance(); - std::vector< std::byte > compileShader( const std::string_view str, std::vector< std::byte >& input ); + std::vector< std::byte > compileShader( const std::string_view str, const std::vector< std::byte >& input ); } // namespace fgl::engine \ No newline at end of file diff --git a/src/engine/systems/CompositionSystem.hpp b/src/engine/systems/CompositionSystem.hpp index bf2dde9..666a22d 100644 --- a/src/engine/systems/CompositionSystem.hpp +++ b/src/engine/systems/CompositionSystem.hpp @@ -17,8 +17,8 @@ namespace fgl::engine { using DescriptorSets = descriptors::DescriptorSetCollection< GBufferDescriptorSet >; - using VertexShader = VertexShaderT< "shaders/fullscreen.vert.spv" >; - using FragmentShader = FragmentShaderT< "shaders/composition.frag.spv" >; + using VertexShader = VertexShaderT< "shaders/fullscreen.vert" >; + using FragmentShader = FragmentShaderT< "shaders/composition.frag" >; using Shaders = ShaderCollection< VertexShader, FragmentShader >; diff --git a/src/engine/systems/DrawPair.cpp b/src/engine/systems/DrawPair.cpp index 112d08c..4711761 100644 --- a/src/engine/systems/DrawPair.cpp +++ b/src/engine/systems/DrawPair.cpp @@ -51,7 +51,8 @@ namespace fgl::engine //assert( primitive.m_texture ); const ModelMatrixInfo matrix_info { .model_matrix = obj.getTransform().mat4(), - .texture_idx = primitive.getAlbedoTextureID() }; + .albedo_id = primitive.getAlbedoTextureID(), + .normal_id = primitive.getNormalTextureID() }; // If the textureless flag is on and we have a texture then skip the primitive.c if ( tree_flags & IS_TEXTURELESS ) @@ -65,7 +66,7 @@ namespace fgl::engine } const auto key { - std::make_pair( matrix_info.texture_idx, primitive.m_index_buffer.getOffset() ) + std::make_pair( matrix_info.albedo_id, primitive.m_index_buffer.getOffset() ) }; assert( primitive.m_index_buffer.size() > 0 ); diff --git a/src/engine/systems/GuiSystem.hpp b/src/engine/systems/GuiSystem.hpp index e09c5ad..bb2ab00 100644 --- a/src/engine/systems/GuiSystem.hpp +++ b/src/engine/systems/GuiSystem.hpp @@ -21,8 +21,8 @@ namespace fgl::engine // Attachment 0 will be the composited image using CompositeDescriptorSets = descriptors::DescriptorSetCollection< GuiInputDescriptorSet >; - using VertexShader = VertexShaderT< "shaders/fullscreen.vert.spv" >; - using FragmentShader = FragmentShaderT< "shaders/gui-compose.frag.spv" >; + using VertexShader = VertexShaderT< "shaders/fullscreen.vert" >; + using FragmentShader = FragmentShaderT< "shaders/gui-compose.frag" >; using Shaders = ShaderCollection< VertexShader, FragmentShader >; using Pipeline = PipelineT< Shaders, CompositeDescriptorSets >; diff --git a/src/engine/systems/modelRendering/StandardPipeline.hpp b/src/engine/systems/modelRendering/StandardPipeline.hpp index 689c52e..da48a01 100644 --- a/src/engine/systems/modelRendering/StandardPipeline.hpp +++ b/src/engine/systems/modelRendering/StandardPipeline.hpp @@ -12,8 +12,8 @@ namespace fgl::engine { - using StandardPipelineVertexShader = VertexShaderT< "shaders/textureless-gbuffer.vert.spv" >; - using StandardPipelineFragShader = FragmentShaderT< "shaders/textureless-gbuffer.frag.spv" >; + using StandardPipelineVertexShader = VertexShaderT< "shaders/textureless-gbuffer.vert" >; + using StandardPipelineFragShader = FragmentShaderT< "shaders/textureless-gbuffer.frag" >; using StandardPipelineShaders = ShaderCollection< StandardPipelineVertexShader, StandardPipelineFragShader >; // using StandardPipelineDescriptorSets = descriptors::DescriptorSetCollection< GlobalDescriptorSet >; diff --git a/src/engine/systems/modelRendering/TexturedPipeline.hpp b/src/engine/systems/modelRendering/TexturedPipeline.hpp index 94c0fe9..ca464c7 100644 --- a/src/engine/systems/modelRendering/TexturedPipeline.hpp +++ b/src/engine/systems/modelRendering/TexturedPipeline.hpp @@ -11,8 +11,8 @@ namespace fgl::engine { - using TexturedPipelineVertexShader = VertexShaderT< "shaders/textured-gbuffer.vert.spv" >; - using TexturedPipelineFragShader = FragmentShaderT< "shaders/textured-gbuffer.frag.spv" >; + using TexturedPipelineVertexShader = VertexShaderT< "shaders/textured-gbuffer.vert" >; + using TexturedPipelineFragShader = FragmentShaderT< "shaders/textured-gbuffer.frag" >; using TexturedPipelineShaders = ShaderCollection< TexturedPipelineVertexShader, TexturedPipelineFragShader >; //using TexturedPipelineDescriptorSets = diff --git a/src/engine/texture/Texture.cpp b/src/engine/texture/Texture.cpp index ca009e8..880fe82 100644 --- a/src/engine/texture/Texture.cpp +++ b/src/engine/texture/Texture.cpp @@ -24,12 +24,12 @@ namespace fgl::engine { - using TextureID = std::uint32_t; + static std::queue< TextureID > unused_ids {}; TextureID getNextID() { - static TextureID id { 0 }; + static TextureID id { 1 }; if ( unused_ids.size() > 0 ) { @@ -40,10 +40,8 @@ namespace fgl::engine return pulled_id; } - else - { - return id++; - } + + return id++; } std::tuple< std::vector< std::byte >, int, int, vk::Format > diff --git a/src/engine/texture/Texture.hpp b/src/engine/texture/Texture.hpp index 938ede6..bafb0da 100644 --- a/src/engine/texture/Texture.hpp +++ b/src/engine/texture/Texture.hpp @@ -31,12 +31,13 @@ namespace fgl::engine class TextureHandle; - using TextureID = std::uint32_t; - class Texture; using TextureStore = AssetStore< Texture >; + using TextureID = std::uint32_t; + constexpr TextureID INVALID_TEXTURE_ID { 0 }; + //TODO: Implement texture handle map to avoid loading the same texture multiple times class Texture final : public AssetInterface< Texture > {