diff --git a/modules/asset_manager/include/asset_manager/asset_manager.hpp b/modules/asset_manager/include/asset_manager/asset_manager.hpp index 1c8e840..03bcba4 100644 --- a/modules/asset_manager/include/asset_manager/asset_manager.hpp +++ b/modules/asset_manager/include/asset_manager/asset_manager.hpp @@ -2,20 +2,29 @@ #include +namespace Assets { + +class TextAsset; + +class TextureAsset; + +} // namespace Assets + namespace Light { class Shader; class Texture; +/** + * Asset is the data on the disk. + * Resource is the data on the gpu/cpu + * + * eg. TextureAsset is the file on the disk + * eg. Texture is the representation of it in the GPU + */ class AssetManager { public: - static auto instance() -> AssetManager & - { - static auto instance = AssetManager {}; - return instance; - } - static void load_shader( const std::string &name, const std::filesystem::path &vertex_path, @@ -43,6 +52,8 @@ public: private: AssetManager() = default; + static auto instance() -> AssetManager &; + void load_shader_impl( const std::string &name, const std::filesystem::path &vertex_path, @@ -51,6 +62,14 @@ private: void load_texture_impl(const std::string &name, const std::filesystem::path &path); + auto get_or_load_text_asset(const std::filesystem::path &path) -> Ref; + + auto get_or_load_texture_asset(const std::filesystem::path &path) -> Ref; + + std::unordered_map> m_text_assets; + + std::unordered_map> m_texture_assets; + std::unordered_map> m_shaders; std::unordered_map> m_textures; diff --git a/modules/asset_manager/src/asset_manager.cpp b/modules/asset_manager/src/asset_manager.cpp index 3b23267..7d7d9a6 100644 --- a/modules/asset_manager/src/asset_manager.cpp +++ b/modules/asset_manager/src/asset_manager.cpp @@ -1,13 +1,19 @@ +#include #include #include +#include #include #include #include -#include -#include namespace Light { +/* static */ auto AssetManager::instance() -> AssetManager & +{ + static auto instance = AssetManager {}; + return instance; +} + void AssetManager::load_shader_impl( const std::string &name, const std::filesystem::path &vertex_path, @@ -21,21 +27,9 @@ void AssetManager::load_shader_impl( log_trc("\tvertex path: {}", vertex_path.string()); log_trc("\tpixel path : {}", pixel_path.string()); - auto vertex_asset = Assets::TextAsset { vertex_path }; - auto pixel_asset = Assets::TextAsset { pixel_path }; - - auto vertex_blob_metadata = vertex_asset.get_blob_metadata(Assets::BlobMetadata::Tag::text); - auto pixel_blob_metadata = pixel_asset.get_blob_metadata(Assets::BlobMetadata::Tag::text); - - auto vertex_blob = Assets::Blob(vertex_blob_metadata.uncompressed_size); - auto pixel_blob = Assets::Blob(pixel_blob_metadata.uncompressed_size); - - vertex_asset.unpack_blob(vertex_blob_metadata.tag, vertex_blob.data(), vertex_blob.size()); - pixel_asset.unpack_blob(pixel_blob_metadata.tag, pixel_blob.data(), pixel_blob.size()); - m_shaders[name] = Ref(Shader::create( - std::move(vertex_blob), - std::move(pixel_blob), + get_or_load_text_asset(vertex_path.string()), + get_or_load_text_asset(pixel_path), GraphicsContext::get_shared_context() )); } @@ -57,21 +51,9 @@ void AssetManager::load_texture_impl(const std::string &name, const std::filesys log_trc("\tname: {}", name); log_trc("\tpath: {}", path.string()); - auto asset = Assets::TextureAsset { path }; - const auto metadata = asset.get_metadata(); - const auto blob_metadata = asset.get_blob_metadata(Assets::BlobMetadata::Tag::color); - - auto blob = std::vector(blob_metadata.uncompressed_size); - asset.unpack_blob(blob_metadata.tag, blob.data(), blob.size()); - - m_textures[name] = Ref(Texture::create( - metadata.pixel_size[0], - metadata.pixel_size[1], - metadata.num_components, - std::bit_cast(blob.data()), - GraphicsContext::get_shared_context(), - path - )); + m_textures[name] = Ref( + Texture::create(get_or_load_texture_asset(path), GraphicsContext::get_shared_context()) + ); } catch (const std::exception &exp) { @@ -82,4 +64,29 @@ void AssetManager::load_texture_impl(const std::string &name, const std::filesys } } +auto AssetManager::get_or_load_text_asset(const std::filesystem::path &path) + -> Ref +{ + const auto key = std::filesystem::canonical(path).string(); + if (!m_text_assets.contains(key)) + { + m_text_assets.emplace(key, create_ref(path)); + } + + return m_text_assets[key]; +} + +auto AssetManager::get_or_load_texture_asset(const std::filesystem::path &path) + -> Ref +{ + const auto key = std::filesystem::canonical(path).string(); + if (!m_texture_assets.contains(key)) + { + m_texture_assets.emplace(key, create_ref(path)); + } + + return m_texture_assets[key]; +} + + } // namespace Light diff --git a/modules/asset_parser/include/asset_parser/assets/text.hpp b/modules/asset_parser/include/asset_parser/assets/text.hpp index 5bb240d..75b2f39 100644 --- a/modules/asset_parser/include/asset_parser/assets/text.hpp +++ b/modules/asset_parser/include/asset_parser/assets/text.hpp @@ -31,7 +31,8 @@ public: TextAsset(const std::filesystem::path &path); - void unpack_blob(BlobMetadata::Tag tag, std::byte *destination, size_t destination_capacity); + void unpack_blob(BlobMetadata::Tag tag, std::byte *destination, size_t destination_capacity) + const; [[nodiscard]] auto get_asset_metadata() const -> const Asset::Metadata &; @@ -48,7 +49,7 @@ private: BlobMetadata m_text_blob_metadata {}; - std::ifstream m_stream; + mutable std::ifstream m_stream; }; } // namespace Assets diff --git a/modules/asset_parser/src/assets/text.cpp b/modules/asset_parser/src/assets/text.cpp index 5bae4e9..a457f48 100644 --- a/modules/asset_parser/src/assets/text.cpp +++ b/modules/asset_parser/src/assets/text.cpp @@ -80,7 +80,7 @@ void TextAsset::unpack_blob( BlobMetadata::Tag tag, std::byte *destination, size_t destination_capacity -) +) const { if (tag != BlobMetadata::Tag::text) { diff --git a/modules/engine/include/engine/scene/components/sprite_renderer.hpp b/modules/engine/include/engine/scene/components/sprite_renderer.hpp index bb74463..c7b69b1 100644 --- a/modules/engine/include/engine/scene/components/sprite_renderer.hpp +++ b/modules/engine/include/engine/scene/components/sprite_renderer.hpp @@ -3,7 +3,6 @@ #include #include -#include namespace Light { @@ -31,7 +30,7 @@ struct SpriteRendererComponent Ref texture; - glm::vec4 tint{}; + glm::vec4 tint {}; }; } // namespace Light diff --git a/modules/engine/src/utils/serializer.cpp b/modules/engine/src/utils/serializer.cpp index 6249d37..db2a268 100644 --- a/modules/engine/src/utils/serializer.cpp +++ b/modules/engine/src/utils/serializer.cpp @@ -269,16 +269,17 @@ void SceneSerializer::serialize_entity(YAML::Emitter &out, Entity entity) if (entity.has_component()) { - out << YAML::Key << "SpriteRendererComponent"; - out << YAML::BeginMap; // sprite renderer component; + // TODO(Light): get scene serialization/de-serialization working. + // out << YAML::Key << "SpriteRendererComponent"; + // out << YAML::BeginMap; // sprite renderer component; - auto &spriteRendererComponent = entity.get_component(); + // auto &spriteRendererComponent = entity.get_component(); - out << YAML::Key << "Texture" << YAML::Value - << spriteRendererComponent.texture->GetFilePath(); - out << YAML::Key << "Tint" << YAML::Value << spriteRendererComponent.tint; + // out << YAML::Key << "Texture" << YAML::Value + // << spriteRendererComponent.texture->GetFilePath(); + // out << YAML::Key << "Tint" << YAML::Value << spriteRendererComponent.tint; - out << YAML::EndMap; // sprite renderer component + // out << YAML::EndMap; // sprite renderer component } // #todo: diff --git a/modules/renderer/include/renderer/gl/shader.hpp b/modules/renderer/include/renderer/gl/shader.hpp index 3791081..9b4b3bb 100644 --- a/modules/renderer/include/renderer/gl/shader.hpp +++ b/modules/renderer/include/renderer/gl/shader.hpp @@ -1,6 +1,5 @@ #pragma once - #include namespace Light { @@ -8,7 +7,7 @@ namespace Light { class glShader: public Shader { public: - glShader(Assets::Blob vertex_blob, Assets::Blob pixel_blob); + glShader(const Ref &vertex_asset, const Ref &pixel_asset); ~glShader() override; diff --git a/modules/renderer/include/renderer/gl/texture.hpp b/modules/renderer/include/renderer/gl/texture.hpp index c8f8b72..5132426 100644 --- a/modules/renderer/include/renderer/gl/texture.hpp +++ b/modules/renderer/include/renderer/gl/texture.hpp @@ -1,6 +1,5 @@ #pragma once - #include namespace Light { @@ -8,13 +7,7 @@ namespace Light { class glTexture: public Texture { public: - glTexture( - unsigned int width, - unsigned int height, - unsigned int components, - unsigned char *pixels, - const std::string &filePath - ); + glTexture(const Ref &asset); ~glTexture() override; @@ -23,7 +16,11 @@ public: auto get_texture() -> void * override; private: - unsigned int m_texture_id; + [[nodiscard]] auto map_num_components_to_format(uint32_t num_components) const -> int; + + [[nodiscard]] auto map_num_components_to_internal_format(uint32_t num_components) const -> int; + + uint32_t m_texture_id {}; }; } // namespace Light diff --git a/modules/renderer/include/renderer/shader.hpp b/modules/renderer/include/renderer/shader.hpp index 8e43e5f..998834b 100644 --- a/modules/renderer/include/renderer/shader.hpp +++ b/modules/renderer/include/renderer/shader.hpp @@ -1,9 +1,13 @@ #pragma once -#include - #include +namespace Assets { + +class TextAsset; + +} // namespace Assets + namespace Light { class SharedContext; @@ -11,7 +15,7 @@ class SharedContext; class Shader { public: - enum Stage + enum Stage : uint8_t { none = 0, @@ -21,8 +25,8 @@ public: }; static auto create( - Assets::Blob vertex_blob, - Assets::Blob pixel_blob, + Ref vertex_asset, + Ref pixel_asset, const Ref &shared_context ) -> Ref; diff --git a/modules/renderer/include/renderer/texture.hpp b/modules/renderer/include/renderer/texture.hpp index 83d7e87..5bed79f 100644 --- a/modules/renderer/include/renderer/texture.hpp +++ b/modules/renderer/include/renderer/texture.hpp @@ -1,6 +1,10 @@ #pragma once +namespace Assets { +class TextureAsset; + +} namespace Light { @@ -10,33 +14,26 @@ class Texture { public: static Ref create( - unsigned int width, - unsigned int height, - unsigned int components, - unsigned char *pixels, - const Ref& sharedContext, - const std::string &filePath + Ref asset, + const Ref &shared_context ); + virtual ~Texture() = default; + + Texture(Texture &&) = default; + + auto operator=(Texture &&) -> Texture & = default; + Texture(const Texture &) = delete; auto operator=(const Texture &) -> Texture & = delete; - virtual ~Texture() = default; - virtual void bind(unsigned int slot = 0) = 0; virtual auto get_texture() -> void * = 0; - [[nodiscard]] auto GetFilePath() const -> const std::string & - { - return m_file_path; - } - protected: - std::string m_file_path; - - Texture(std::string filePath); + Texture() = default; }; } // namespace Light diff --git a/modules/renderer/src/gl/shader.cpp b/modules/renderer/src/gl/shader.cpp index 7b0b8b5..9ded529 100644 --- a/modules/renderer/src/gl/shader.cpp +++ b/modules/renderer/src/gl/shader.cpp @@ -1,14 +1,27 @@ -#include +#include #include #include #include #include +#include namespace Light { -glShader::glShader(Assets::Blob vertex_blob, Assets::Blob pixel_blob) +glShader::glShader( + const Ref &vertex_asset, + const Ref &pixel_asset +) : m_shader_id(glCreateProgram()) { + auto vertex_blob_metadata = vertex_asset->get_blob_metadata(Assets::BlobMetadata::Tag::text); + auto pixel_blob_metadata = pixel_asset->get_blob_metadata(Assets::BlobMetadata::Tag::text); + + auto vertex_blob = Assets::Blob(vertex_blob_metadata.uncompressed_size); + auto pixel_blob = Assets::Blob(pixel_blob_metadata.uncompressed_size); + + vertex_asset->unpack_blob(vertex_blob_metadata.tag, vertex_blob.data(), vertex_blob.size()); + pixel_asset->unpack_blob(pixel_blob_metadata.tag, pixel_blob.data(), pixel_blob.size()); + auto vertex_source = std::string { vertex_blob.data(), vertex_blob.data() + vertex_blob.size(), // NOLINT diff --git a/modules/renderer/src/gl/texture.cpp b/modules/renderer/src/gl/texture.cpp index bbfdf01..29f6a67 100644 --- a/modules/renderer/src/gl/texture.cpp +++ b/modules/renderer/src/gl/texture.cpp @@ -1,58 +1,35 @@ -#include +#include #include +#include #include namespace Light { -glTexture::glTexture( - unsigned int width, - unsigned int height, - unsigned int components, - unsigned char *pixels, - const std::string &filePath -) - : Texture(filePath) - , m_texture_id(NULL) +glTexture::glTexture(const Ref &asset) { - // create texture - glCreateTextures(GL_TEXTURE_2D, 1, &m_texture_id); + const auto metadata = asset->get_metadata(); + const auto blob_metadata = asset->get_blob_metadata(Assets::BlobMetadata::Tag::color); - // set texture parameters + glCreateTextures(GL_TEXTURE_2D, 1, &m_texture_id); glTextureParameteri(m_texture_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTextureParameteri(m_texture_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTextureParameteri(m_texture_id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTextureParameteri(m_texture_id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // determine formats - auto format = components == 4u ? GL_RGBA : - components == 3u ? GL_RGB : - components == 2u ? GL_RG : - components == 1u ? GL_RED : - NULL; + auto blob = std::vector(blob_metadata.uncompressed_size); + asset->unpack_blob(blob_metadata.tag, blob.data(), blob.size()); - auto internalFormat = format == GL_RGBA ? GL_RGBA8 : - format == GL_RGB ? GL_RGB8 : - format == GL_RG ? GL_RG8 : - format == GL_RED ? GL_R8 : - NULL; - - // check - lt_assert(format, "Invalid number of components: {}", components); - - - // #todo: isn't there something like glTextureImage2D ??? - // create texture and mipsmaps bind(); glTexImage2D( GL_TEXTURE_2D, 0, - internalFormat, - width, - height, + map_num_components_to_internal_format(metadata.num_components), + static_cast(metadata.pixel_size[0]), + static_cast(metadata.pixel_size[1]), 0, - format, + map_num_components_to_format(metadata.num_components), GL_UNSIGNED_BYTE, - pixels + std::bit_cast(blob.data()) ); glGenerateMipmap(GL_TEXTURE_2D); } @@ -73,4 +50,33 @@ auto glTexture::get_texture() -> void * return (void *)(intptr_t)m_texture_id; } +[[nodiscard]] auto glTexture::map_num_components_to_format(uint32_t num_components) const -> int +{ + switch (num_components) + { + case 4u: return GL_RGBA; + case 3u: return GL_RGB; + case 2u: return GL_RG; + case 1u: return GL_RED; + default: lt_assert(false, "Invalid number of components: {}", num_components); + } + + return {}; +} + +[[nodiscard]] auto glTexture::map_num_components_to_internal_format(uint32_t num_components) const + -> int +{ + switch (num_components) + { + case 4u: return GL_RGBA8; + case 3u: return GL_RGB8; + case 2u: return GL_RG8; + case 1u: return GL_R8; + default: lt_assert(false, "Invalid number of components: {}", num_components); + } + + return {}; +} + } // namespace Light diff --git a/modules/renderer/src/shader.cpp b/modules/renderer/src/shader.cpp index 4b257e6..a23703e 100644 --- a/modules/renderer/src/shader.cpp +++ b/modules/renderer/src/shader.cpp @@ -1,5 +1,6 @@ -#include +#include #include +#include #ifdef LIGHT_PLATFORM_WINDOWS #include @@ -10,9 +11,9 @@ namespace Light { -auto Shader::create( - Assets::Blob vertex_blob, - Assets::Blob pixel_blob, +/* static */ auto Shader::create( + Ref vertex_asset, + Ref pixel_asset, const Ref &shared_context ) -> Ref { @@ -22,12 +23,12 @@ auto Shader::create( switch (GraphicsContext::get_graphics_api()) { case GraphicsAPI::OpenGL: - return create_ref(std::move(vertex_blob), std::move(pixel_blob)); + return create_ref(std::move(vertex_asset), std::move(pixel_asset)); case GraphicsAPI::DirectX: lt_win(return create_ref( - vertexFile, - pixelFile, + vertex_asset, + pixel_asset, std::static_pointer_cast(sharedContext) );); diff --git a/modules/renderer/src/texture.cpp b/modules/renderer/src/texture.cpp index 03b48f3..28ef964 100644 --- a/modules/renderer/src/texture.cpp +++ b/modules/renderer/src/texture.cpp @@ -8,23 +8,17 @@ #endif #include -#include namespace Light { -auto Texture::create( - unsigned int width, - unsigned int height, - unsigned int components, - unsigned char *pixels, - const Ref & /*sharedContext*/, - const std::string &filePath +/* static */ auto Texture::create( + Ref asset, + const Ref &shared_context ) -> Ref { switch (GraphicsContext::get_graphics_api()) { - case GraphicsAPI::OpenGL: - return create_ref(width, height, components, pixels, filePath); + case GraphicsAPI::OpenGL: return create_ref(std::move(asset)); case GraphicsAPI::DirectX: lt_win(return create_ref( @@ -46,8 +40,4 @@ auto Texture::create( } } -Texture::Texture(std::string filePath): m_file_path(std::move(filePath)) -{ -} - } // namespace Light