feat: asset baking
Only supported .png textures at the moment
This commit is contained in:
		
							parent
							
								
									71d08cbe9f
								
							
						
					
					
						commit
						38997b3908
					
				
					 23 changed files with 594 additions and 393 deletions
				
			
		
							
								
								
									
										
											BIN
										
									
								
								data/assets/textures/awesomeface.asset
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/assets/textures/awesomeface.asset
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								data/engine/icons/asset/dir.asset
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/engine/icons/asset/dir.asset
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								data/engine/icons/asset/img.asset
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/engine/icons/asset/img.asset
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								data/engine/icons/asset/scene.asset
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/engine/icons/asset/scene.asset
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								data/engine/icons/asset/txt.asset
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								data/engine/icons/asset/txt.asset
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							|  | @ -5,6 +5,7 @@ Layout | ||||||
| {version}              | 4 bytes, ie. uint32_t | {version}              | 4 bytes, ie. uint32_t | ||||||
| {general metadata}     | sizeof(AssetMetadata) | {general metadata}     | sizeof(AssetMetadata) | ||||||
| {specialized metadata} | sizeof(XXXAssetMetadata), eg. TextureAssetMetadata | {specialized metadata} | sizeof(XXXAssetMetadata), eg. TextureAssetMetadata | ||||||
|  | {n}                    | 4 bytes, ie. uint32_t | ||||||
| {blob_0...n metadata}  | n * sizeof(BlobMetadata) | {blob_0...n metadata}  | n * sizeof(BlobMetadata) | ||||||
| {blob_0...n data}      | variable size based on actual data | {blob_0...n data}      | variable size based on actual data | ||||||
| {end marker}           | 8 byte, ie size_t for marking the END | {end marker}           | 8 byte, ie size_t for marking the END | ||||||
|  | @ -13,7 +14,8 @@ Sections | ||||||
| --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ||||||
| version              -> The version of the asset for forward compatibility | version              -> The version of the asset for forward compatibility | ||||||
| general metadata     -> Common asset metadata such as file-path, asset-type, creator, etc. | general metadata     -> Common asset metadata such as file-path, asset-type, creator, etc. | ||||||
| specialized metadata -> Metadata specific to the asset, eg. texture dimensions for Textures | specialized metadata -> Metadata specific to the asset, eg. texture dimensions for Textures. | ||||||
|  | n                    -> The number of blobs. | ||||||
| blob_0...n metadata  -> Metadata specifying how the actual data is packed, required for unpacking. | blob_0...n metadata  -> Metadata specifying how the actual data is packed, required for unpacking. | ||||||
| blob_0...n data      -> The actual data, packed and compressed to be reacdy for direct engine consumption. | blob_0...n data      -> The actual data, packed and compressed to be reacdy for direct engine consumption. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										4
									
								
								docs/architecture/resource.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								docs/architecture/resource.rst
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | ||||||
|  | Resource Management | ||||||
|  | 
 | ||||||
|  | =================================================================================================== | ||||||
|  | 
 | ||||||
|  | @ -6,4 +6,5 @@ target_link_libraries( | ||||||
|     asset_baker |     asset_baker | ||||||
|     PRIVATE asset_parser |     PRIVATE asset_parser | ||||||
|     PRIVATE stb::stb |     PRIVATE stb::stb | ||||||
|  |     PRIVATE logger | ||||||
| ) | ) | ||||||
|  |  | ||||||
							
								
								
									
										120
									
								
								modules/asset_baker/include/asset_baker/bakers.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								modules/asset_baker/include/asset_baker/bakers.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,120 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <asset_parser/assets/texture.hpp> | ||||||
|  | #include <filesystem> | ||||||
|  | #include <logger/logger.hpp> | ||||||
|  | #include <string_view> | ||||||
|  | #include <unordered_set> | ||||||
|  | 
 | ||||||
|  | #define STB_IMAGE_IMPLEMENTATION | ||||||
|  | #include <stb_image.h> | ||||||
|  | 
 | ||||||
|  | namespace lt { | ||||||
|  | 
 | ||||||
|  | class Loader | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	[[nodiscard]] virtual auto get_name() const -> std::string_view = 0; | ||||||
|  | 
 | ||||||
|  | 	Loader() = default; | ||||||
|  | 
 | ||||||
|  | 	Loader(Loader &&) = default; | ||||||
|  | 
 | ||||||
|  | 	Loader(const Loader &) = delete; | ||||||
|  | 
 | ||||||
|  | 	auto operator=(Loader &&) -> Loader & = default; | ||||||
|  | 
 | ||||||
|  | 	auto operator=(const Loader &) -> Loader & = delete; | ||||||
|  | 
 | ||||||
|  | 	virtual ~Loader() = default; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class TextureLoader: public Loader | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	TextureLoader() = default; | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] virtual auto load(std::filesystem::path file_path) const | ||||||
|  | 	    -> Assets::TextureAsset::PackageData | ||||||
|  | 	    = 0; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class StbLoader: public TextureLoader | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	StbLoader() = default; | ||||||
|  | 
 | ||||||
|  | 	void load(std::filesystem::path path); | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] static auto get_supported_extensions() -> std::unordered_set<std::string_view> | ||||||
|  | 	{ | ||||||
|  | 		return { ".png" }; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto get_name() const -> std::string_view override | ||||||
|  | 	{ | ||||||
|  | 		return "StbLoader"; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto load(std::filesystem::path file_path) const | ||||||
|  | 	    -> Assets::TextureAsset::PackageData override | ||||||
|  | 	{ | ||||||
|  | 		auto width = int {}; | ||||||
|  | 		auto height = int {}; | ||||||
|  | 		auto channels = int {}; | ||||||
|  | 
 | ||||||
|  | 		auto *pixels = stbi_load(file_path.string().c_str(), &width, &height, &channels, 4); | ||||||
|  | 		if (!pixels) | ||||||
|  | 		{ | ||||||
|  | 			throw std::runtime_error { | ||||||
|  | 				std::format("Failed to load image file at: {} using stbi_load", file_path.string()), | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		const auto metadata = Assets::Asset::Metadata { | ||||||
|  | 			.type = Assets::Asset::Type::Texture, | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		const auto texture_metadata = Assets::TextureAsset::Metadata { | ||||||
|  |             .format = Assets::TextureAsset::Format::RGBA8, | ||||||
|  |             .num_components = static_cast<uint32_t>(channels), | ||||||
|  |             .pixel_size = { | ||||||
|  |                 static_cast<uint32_t>(width), | ||||||
|  |                 static_cast<uint32_t>(height), | ||||||
|  |                 {}, | ||||||
|  |             }, | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  | 		auto pixels_blob = Assets::Blob {}; | ||||||
|  | 		pixels_blob.resize(static_cast<size_t>(width) * height * channels); | ||||||
|  | 
 | ||||||
|  | 		// TODO(Light): figure out if it's possible to directly populate a blob with stbi functions
 | ||||||
|  | 		memcpy(pixels_blob.data(), pixels, pixels_blob.size()); | ||||||
|  | 		stbi_image_free(pixels); | ||||||
|  | 
 | ||||||
|  | 		return Assets::TextureAsset::PackageData { | ||||||
|  | 			.metadata = metadata, | ||||||
|  | 			.texture_metadata = texture_metadata, | ||||||
|  | 			.pixels = std::move(pixels_blob), | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class TextureLoaderFactory | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	static auto create(std::string_view file_extension) -> std::unique_ptr<TextureLoader> | ||||||
|  | 	{ | ||||||
|  | 		if (StbLoader::get_supported_extensions().contains(file_extension)) | ||||||
|  | 		{ | ||||||
|  | 			return std::make_unique<StbLoader>(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return {}; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace lt
 | ||||||
|  | @ -1,85 +1,70 @@ | ||||||
|  | #include <asset_baker/bakers.hpp> | ||||||
| #include <asset_parser/assets/texture.hpp> | #include <asset_parser/assets/texture.hpp> | ||||||
| #include <asset_parser/parser.hpp> | #include <asset_parser/parser.hpp> | ||||||
| #include <filesystem> | #include <filesystem> | ||||||
| #include <iostream> | #include <logger/logger.hpp> | ||||||
| 
 | 
 | ||||||
| #define STB_IMAGE_IMPLEMENTATION | void try_packing_texture( | ||||||
| #include <stb_image.h> |     const std::filesystem::path &in_path, | ||||||
| 
 |     const std::filesystem::path &out_path | ||||||
| #define ASSERT(x, ...)    \ | ) | ||||||
| 	if (!(x))             \ |  | ||||||
| 	{                     \ |  | ||||||
| 		log(__VA_ARGS__); \ |  | ||||||
| 		return -1;        \ |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| template<typename... Args> |  | ||||||
| void log(Args &&...args) |  | ||||||
| { | { | ||||||
| 	(std::cout << ... << args); | 	auto texture_loader = lt::TextureLoaderFactory::create(in_path.extension().string()); | ||||||
| 	std::cout << '\n'; | 	if (!texture_loader) | ||||||
| } |  | ||||||
| 
 |  | ||||||
| auto convert_image(const std::filesystem::path &input, const std::filesystem::path &output) -> bool |  | ||||||
| { |  | ||||||
| 	auto width = int {}; |  | ||||||
| 	auto height = int {}; |  | ||||||
| 	auto channels = int {}; |  | ||||||
| 
 |  | ||||||
| 	auto *pixels = stbi_load(input.string().c_str(), &width, &height, &channels, 4); |  | ||||||
| 
 |  | ||||||
| 	if (!pixels) |  | ||||||
| 		return false; |  | ||||||
| 
 |  | ||||||
| 	auto texture_info = Assets::TextureInfo { |  | ||||||
| 		.size       = static_cast<size_t>(width * height * 4), |  | ||||||
| 		.format     = Assets::TextureFormat::RGBA8, |  | ||||||
| 		.pixel_size = { |  | ||||||
| 		    static_cast<uint32_t>(width), |  | ||||||
| 		    static_cast<uint32_t>(height), |  | ||||||
| 		    0ul, |  | ||||||
| 		}, |  | ||||||
| 		.original_file = input.string(), |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	auto file = Assets::pack_texture(&texture_info, pixels); |  | ||||||
| 
 |  | ||||||
| 	stbi_image_free(pixels); |  | ||||||
| 
 |  | ||||||
| 	Assets::save_binary_file(output.string().c_str(), file); |  | ||||||
| 
 |  | ||||||
| 	return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main(int argc, char *argv[]) |  | ||||||
| { |  | ||||||
| 	std::ios_base::sync_with_stdio(false); |  | ||||||
| 
 |  | ||||||
| 	ASSERT( |  | ||||||
| 	    argc == 3, |  | ||||||
| 	    "Argc MUST be 3, 1: execution-path(implicit), 2: input-directory, 3: output-directory" |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	for (const auto &p : std::filesystem::directory_iterator(argv[1])) |  | ||||||
| 	{ | 	{ | ||||||
| 		if (p.path().extension() == ".png") | 		// Don't log anything; this is expected.
 | ||||||
| 		{ | 		return; | ||||||
| 			log("Found a texture: ", p); |  | ||||||
| 
 |  | ||||||
| 			auto newp = p.path(); |  | ||||||
| 			newp.replace_extension(".asset_texture"); |  | ||||||
| 			convert_image(p.path(), newp); |  | ||||||
| 		} |  | ||||||
| 		else if (p.path().extension() == ".obj") |  | ||||||
| 		{ |  | ||||||
| 			log("Found a mesh -> ", p, " (unsupported)"); |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			log("Unknown -> ", p); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	try | ||||||
|  | 	{ | ||||||
|  | 		Assets::TextureAsset::pack(texture_loader->load(in_path), out_path); | ||||||
|  | 
 | ||||||
|  | 		log_inf("Packed a texture:"); | ||||||
|  | 		log_inf("\tloader  : {}", texture_loader->get_name()); | ||||||
|  | 		log_inf("\tin  path: {}", in_path.string()); | ||||||
|  | 		log_inf("\tout path: {}", out_path.string()); | ||||||
|  | 	} | ||||||
|  | 	catch (const std::exception &exp) | ||||||
|  | 	{ | ||||||
|  | 		log_err("Failed to pack texture:"); | ||||||
|  | 		log_err("\tloader  : {}", texture_loader->get_name()); | ||||||
|  | 		log_err("\tin path : {}", in_path.string()); | ||||||
|  | 		log_err("\tout path: {}", out_path.string()); | ||||||
|  | 		log_err("\texp.what: {}", exp.what()); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | auto main(int argc, char *argv[]) -> int32_t | ||||||
|  | try | ||||||
|  | { | ||||||
|  | 	if (argc != 2) | ||||||
|  | 	{ | ||||||
|  | 		throw std::logic_error("Argc should be 2 -- exe dir (implicit) and target dir"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (const auto &directory_iterator : | ||||||
|  | 	     std::filesystem::recursive_directory_iterator(argv[1])) // NOLINT
 | ||||||
|  | 	{ | ||||||
|  | 		if (directory_iterator.is_directory()) | ||||||
|  | 		{ | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		const auto &in_path = directory_iterator.path(); | ||||||
|  | 
 | ||||||
|  | 		auto out_path = in_path; | ||||||
|  | 		out_path.replace_extension(".asset"); | ||||||
|  | 
 | ||||||
|  | 		try_packing_texture(in_path, out_path); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return EXIT_SUCCESS; | ||||||
|  | } | ||||||
|  | catch (const std::exception &exp) | ||||||
|  | { | ||||||
|  | 	log_crt("Terminating due to uncaught exception:"); | ||||||
|  | 	log_crt("\texception.what: {}:", exp.what()); | ||||||
|  | 
 | ||||||
|  | 	return EXIT_FAILURE; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -7,4 +7,5 @@ target_link_libraries( | ||||||
|     asset_parser |     asset_parser | ||||||
|     PRIVATE LZ4::lz4_static  |     PRIVATE LZ4::lz4_static  | ||||||
|     PRIVATE nlohmann_json::nlohmann_json  |     PRIVATE nlohmann_json::nlohmann_json  | ||||||
|  |     PRIVATE logger | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | @ -1,34 +0,0 @@ | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <array> |  | ||||||
| #include <asset_parser/parser.hpp> |  | ||||||
| 
 |  | ||||||
| namespace Assets { |  | ||||||
| 
 |  | ||||||
| enum class TextureFormat : uint8_t |  | ||||||
| { |  | ||||||
| 	None = 0, |  | ||||||
| 	RGBA8, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct TextureInfo |  | ||||||
| { |  | ||||||
| 	size_t size; |  | ||||||
| 	CompressionMode compression_mode; |  | ||||||
| 	TextureFormat format; |  | ||||||
| 	std::array<uint32_t, 3> pixel_size; |  | ||||||
| 	std::string original_file; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| auto read_texture_info(AssetFile *file) -> TextureInfo; |  | ||||||
| 
 |  | ||||||
| void unpack_texture( |  | ||||||
|     TextureInfo *info, |  | ||||||
|     const void *source_buffer, |  | ||||||
|     size_t source_size, |  | ||||||
|     void *destination |  | ||||||
| ); |  | ||||||
| 
 |  | ||||||
| auto pack_texture(TextureInfo *info, void *pixel_data) -> AssetFile; |  | ||||||
| 
 |  | ||||||
| } // namespace Assets
 |  | ||||||
|  | @ -1,34 +1,276 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <compressors/compressors.hpp> | ||||||
| #include <cstdint> | #include <cstdint> | ||||||
| #include <string> | #include <filesystem> | ||||||
|  | #include <fstream> | ||||||
|  | #include <logger/logger.hpp> | ||||||
|  | #include <utility> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
| namespace Assets { | namespace Assets { | ||||||
| 
 | 
 | ||||||
| struct AssetFile | constexpr auto current_version = uint32_t { 1 }; | ||||||
| { |  | ||||||
| 	uint32_t version; |  | ||||||
| 
 | 
 | ||||||
|  | struct BlobMetadata | ||||||
|  | { | ||||||
|  | 	enum class Tag : uint8_t | ||||||
|  | 	{ | ||||||
|  | 		color, | ||||||
|  | 		depth, | ||||||
|  | 		vertices, | ||||||
|  | 		indices, | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	Tag tag; | ||||||
|  | 
 | ||||||
|  | 	size_t offset; | ||||||
|  | 
 | ||||||
|  | 	CompressionType compression_type; | ||||||
|  | 
 | ||||||
|  | 	size_t compressed_size; | ||||||
|  | 
 | ||||||
|  | 	size_t uncompressed_size; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | using Blob = std::vector<std::byte>; | ||||||
|  | 
 | ||||||
|  | class Asset | ||||||
|  | { | ||||||
|  | public: | ||||||
| 	enum class Type : uint32_t // NOLINT(performance-enum-size)
 | 	enum class Type : uint32_t // NOLINT(performance-enum-size)
 | ||||||
| 	{ | 	{ | ||||||
| 		Texture, | 		Texture, | ||||||
| 		Mesh, | 		Mesh, | ||||||
| 		Material, | 		Material, | ||||||
| 	} type; | 	}; | ||||||
| 
 | 
 | ||||||
| 	std::string json; | 	struct Metadata | ||||||
| 	std::vector<uint8_t> blob; | 	{ | ||||||
|  | 		Type type; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	Asset() = default; | ||||||
|  | 
 | ||||||
|  | 	Asset(Metadata metadata, std::filesystem::path path, std::ifstream stream) | ||||||
|  | 	    : m_metadata(metadata) | ||||||
|  | 	    , m_file_path(std::move(path)) | ||||||
|  | 	    , m_stream(std::move(stream)) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** Directly unpacks from disk to the destination.
 | ||||||
|  | 	 * | ||||||
|  | 	 * @note The destination MUST have at least blob_metadata.unpacked_size bytes available for | ||||||
|  | 	 * writing, otherwise segfault could occur! | ||||||
|  | 	 */ | ||||||
|  | 	void unpack_blob(BlobMetadata::Tag blob_tag, std::byte *destination); | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto get_metadata() const -> const Metadata & | ||||||
|  | 	{ | ||||||
|  | 		return m_metadata; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto get_file_path() const -> std::filesystem::path | ||||||
|  | 	{ | ||||||
|  | 		return m_file_path; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	Metadata m_metadata; | ||||||
|  | 
 | ||||||
|  | 	std::filesystem::path m_file_path; | ||||||
|  | 
 | ||||||
|  | 	std::ifstream m_stream; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum class CompressionMode : uint32_t // NOLINT(performance-enum-size)
 | class TextureAsset: public Asset | ||||||
| { | { | ||||||
| 	None, | public: | ||||||
| 	LZ4, | 	enum class Format : uint32_t // NOLINT(performance-enum-size)
 | ||||||
| 	LZ4HC, | 	{ | ||||||
| }; | 		None = 0, | ||||||
|  | 		RGBA8, | ||||||
|  | 	}; | ||||||
| 
 | 
 | ||||||
| auto save_binary_file(const char *path, const AssetFile &in_file) -> bool; | 	struct Metadata | ||||||
| auto load_binary_file(const char *path, AssetFile &out_file) -> bool; | 	{ | ||||||
|  | 		Format format; | ||||||
|  | 
 | ||||||
|  | 		uint32_t num_components; | ||||||
|  | 
 | ||||||
|  | 		std::array<uint32_t, 3> pixel_size; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	/** Data required to pack a texture */ | ||||||
|  | 	struct PackageData | ||||||
|  | 	{ | ||||||
|  | 		Asset::Metadata metadata; | ||||||
|  | 
 | ||||||
|  | 		Metadata texture_metadata; | ||||||
|  | 
 | ||||||
|  | 		Blob pixels; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	TextureAsset(const std::filesystem::path &path) | ||||||
|  | 	{ | ||||||
|  | 		m_stream = std::ifstream { path, std::ios::binary }; | ||||||
|  | 		if (!m_stream.is_open()) | ||||||
|  | 		{ | ||||||
|  | 			throw std::runtime_error { std::format( | ||||||
|  | 				"Failed to open ifm_stream for loading texture asset at: {}", | ||||||
|  | 				path.string() | ||||||
|  | 			) }; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
 | ||||||
|  | 		m_stream.read((char *)&version, sizeof(version)); | ||||||
|  | 		m_stream.read((char *)&m_asset_metadata, sizeof(m_asset_metadata)); | ||||||
|  | 		m_stream.read((char *)&m_metadata, sizeof(m_metadata)); | ||||||
|  | 
 | ||||||
|  | 		auto num_blobs = uint32_t {}; | ||||||
|  | 		m_stream.read((char *)&num_blobs, sizeof(num_blobs)); | ||||||
|  | 		if (num_blobs != 1) | ||||||
|  | 		{ | ||||||
|  | 			throw std::runtime_error { | ||||||
|  | 				std::format("Failed to load texture asset: invalid number of blobs: {}", num_blobs) | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		m_stream.read((char *)&m_pixel_blob_metadata, sizeof(m_pixel_blob_metadata)); | ||||||
|  | 		if (m_pixel_blob_metadata.tag != BlobMetadata::Tag::color) | ||||||
|  | 		{ | ||||||
|  | 			throw std::runtime_error { | ||||||
|  | 				std::format( | ||||||
|  | 				    "Failed to load texture asset: invalid blob tag, expected {}, got {}", | ||||||
|  | 				    std::to_underlying(BlobMetadata::Tag::color), | ||||||
|  | 				    std::to_underlying(m_pixel_blob_metadata.tag) | ||||||
|  | 				), | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 		// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast)
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void unpack_blob(BlobMetadata::Tag tag, std::byte *destination, size_t destination_capacity) | ||||||
|  | 	{ | ||||||
|  | 		if (tag != BlobMetadata::Tag::color) | ||||||
|  | 		{ | ||||||
|  | 			throw std::runtime_error { std::format( | ||||||
|  | 				"Invalid tag for unpack_blob of TextureAsset: {}", | ||||||
|  | 				std::to_underlying(tag) | ||||||
|  | 			) }; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		m_stream.seekg(static_cast<long>(m_pixel_blob_metadata.offset)); | ||||||
|  | 		switch (m_pixel_blob_metadata.compression_type) | ||||||
|  | 		{ | ||||||
|  | 		case Assets::CompressionType::None: | ||||||
|  | 			if (m_pixel_blob_metadata.uncompressed_size != m_pixel_blob_metadata.compressed_size) | ||||||
|  | 			{ | ||||||
|  | 				throw std::runtime_error("Failed to unpack blob from TextureAsset: " | ||||||
|  | 				                         "compressed/uncompressed size mismatch for no compression " | ||||||
|  | 				                         "type"); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (m_pixel_blob_metadata.uncompressed_size > destination_capacity) | ||||||
|  | 			{ | ||||||
|  | 				throw std::runtime_error("Failed to unpack blob from TextureAsset: " | ||||||
|  | 				                         "uncompressed_size > destination_capacity, unpacking " | ||||||
|  | 				                         "would result in segfault"); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (!m_stream.is_open()) | ||||||
|  | 			{ | ||||||
|  | 				throw std::runtime_error("Failed to unpack blob from TextureAsset: ifstream is " | ||||||
|  | 				                         "closed"); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			m_stream.read( | ||||||
|  | 			    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
 | ||||||
|  | 			    (char *)destination, | ||||||
|  | 			    static_cast<long>(m_pixel_blob_metadata.uncompressed_size) | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			return; | ||||||
|  | 
 | ||||||
|  | 		default: | ||||||
|  | 			throw std::runtime_error(std::format( | ||||||
|  | 			    "Failed to unpack blob from TextureAsset: unsupported " | ||||||
|  | 			    "compression type: {}", | ||||||
|  | 			    std::to_underlying(m_pixel_blob_metadata.compression_type) | ||||||
|  | 			)); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	static void pack(const PackageData &data, const std::filesystem::path &out_path) | ||||||
|  | 	{ | ||||||
|  | 		const auto &[metadata, texture_metadata, pixels] = data; | ||||||
|  | 
 | ||||||
|  | 		auto stream = std::ofstream { out_path, std::ios::binary | std::ios::trunc }; | ||||||
|  | 		if (!stream.is_open()) | ||||||
|  | 		{ | ||||||
|  | 			throw std::runtime_error { | ||||||
|  | 				std::format("Failed to open ofstream for packing texture at: {}", out_path.string()) | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 		stream.seekp(0); | ||||||
|  | 
 | ||||||
|  | 		// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
 | ||||||
|  | 		stream.write((char *)¤t_version, sizeof(current_version)); | ||||||
|  | 
 | ||||||
|  | 		stream.write((char *)&metadata, sizeof(metadata)); | ||||||
|  | 		stream.write((char *)&texture_metadata, sizeof(texture_metadata)); | ||||||
|  | 
 | ||||||
|  | 		constexpr auto number_of_blobs = uint32_t { 1 }; | ||||||
|  | 		stream.write((char *)&number_of_blobs, sizeof(number_of_blobs)); | ||||||
|  | 
 | ||||||
|  | 		auto pixels_metadata = BlobMetadata { | ||||||
|  | 			.tag = BlobMetadata::Tag::color, | ||||||
|  | 			.offset = static_cast<size_t>(stream.tellp()), | ||||||
|  | 			.compression_type = CompressionType::None, | ||||||
|  | 			.compressed_size = pixels.size(), | ||||||
|  | 			.uncompressed_size = pixels.size(), | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		stream.write((char *)&pixels_metadata, sizeof(pixels_metadata)); | ||||||
|  | 		stream.write((char *)&pixels[0], static_cast<long>(pixels.size())); | ||||||
|  | 		// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast)
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto get_asset_metadata() const -> const Asset::Metadata & | ||||||
|  | 	{ | ||||||
|  | 		return m_asset_metadata; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto get_metadata() const -> const Metadata & | ||||||
|  | 	{ | ||||||
|  | 		return m_metadata; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto get_blob_metadata(BlobMetadata::Tag tag) const -> const BlobMetadata & | ||||||
|  | 	{ | ||||||
|  | 		if (tag != BlobMetadata::Tag::color) | ||||||
|  | 		{ | ||||||
|  | 			throw std::runtime_error { std::format( | ||||||
|  | 				"Invalid tag for get_blob_metadata of TextureAsset: {}", | ||||||
|  | 				std::to_underlying(tag) | ||||||
|  | 			) }; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return m_pixel_blob_metadata; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	Asset::Metadata m_asset_metadata {}; | ||||||
|  | 
 | ||||||
|  | 	Metadata m_metadata {}; | ||||||
|  | 
 | ||||||
|  | 	BlobMetadata m_pixel_blob_metadata {}; | ||||||
|  | 
 | ||||||
|  | 	uint32_t version {}; | ||||||
|  | 
 | ||||||
|  | 	std::ifstream m_stream; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Assets
 | } // namespace Assets
 | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								modules/asset_parser/include/compressors/compressors.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								modules/asset_parser/include/compressors/compressors.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <cstdint> | ||||||
|  | 
 | ||||||
|  | namespace Assets { | ||||||
|  | 
 | ||||||
|  | enum class CompressionType : uint32_t // NOLINT(performance-enum-size)
 | ||||||
|  | { | ||||||
|  | 	None, | ||||||
|  | 	LZ4, | ||||||
|  | 	LZ4HC, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -2,79 +2,11 @@ | ||||||
| #include <lz4.h> | #include <lz4.h> | ||||||
| #include <nlohmann/json.hpp> | #include <nlohmann/json.hpp> | ||||||
| 
 | 
 | ||||||
|  | // [version], [type] --
 | ||||||
|  | // [asset_metadata], [blob_metadata] --
 | ||||||
|  | // [blob] --
 | ||||||
|  | 
 | ||||||
| namespace Assets { | namespace Assets { | ||||||
| 
 | 
 | ||||||
| using namespace nlohmann; |  | ||||||
| 
 |  | ||||||
| auto read_texture_info(AssetFile *file) -> TextureInfo |  | ||||||
| { |  | ||||||
| 	json texture_meta_data = json::parse(file->json); |  | ||||||
| 
 |  | ||||||
| 	return TextureInfo { |  | ||||||
| 		.size            = texture_meta_data["bufferSize"], |  | ||||||
| 		.compression_mode = texture_meta_data["compression"], |  | ||||||
| 		.format          = texture_meta_data["format"], |  | ||||||
| 		.pixel_size      = { |  | ||||||
| 		         texture_meta_data["width"], |  | ||||||
| 		         texture_meta_data["height"], |  | ||||||
| 		         0, |  | ||||||
|         }, |  | ||||||
| 		.original_file = texture_meta_data["originalFile"], |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void unpack_texture( |  | ||||||
|     TextureInfo *info, |  | ||||||
|     const void *source_buffer, |  | ||||||
|     size_t source_size, |  | ||||||
|     void *destination |  | ||||||
| ) |  | ||||||
| { |  | ||||||
| 	if (info->compression_mode == CompressionMode::LZ4) |  | ||||||
| 	{ |  | ||||||
| 		LZ4_decompress_safe( |  | ||||||
| 		    (const char *)source_buffer, |  | ||||||
| 		    (char *)destination, |  | ||||||
| 		    source_size, |  | ||||||
| 		    info->size |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		memcpy(destination, source_buffer, source_size); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| auto pack_texture(TextureInfo *info, void *pixel_data) -> AssetFile |  | ||||||
| { |  | ||||||
| 	json metadata; |  | ||||||
| 	metadata["format"] = info->format; |  | ||||||
| 	metadata["width"] = info->pixel_size[0]; |  | ||||||
| 	metadata["height"] = info->pixel_size[1]; |  | ||||||
| 	metadata["bufferSize"] = info->size; |  | ||||||
| 	metadata["originalFile"] = info->original_file; |  | ||||||
| 	metadata["compression"] = CompressionMode::LZ4; |  | ||||||
| 
 |  | ||||||
| 	AssetFile file; |  | ||||||
| 	file.type = AssetFile::Type::Texture; |  | ||||||
| 	file.version = 1u; |  | ||||||
| 
 |  | ||||||
| 	const int compress_staging = LZ4_compressBound(info->size); |  | ||||||
| 	file.blob.resize(compress_staging); |  | ||||||
| 	const int compression_size = LZ4_compress_default( |  | ||||||
| 	    (const char *)pixel_data, |  | ||||||
| 	    (char *)file.blob.data(), |  | ||||||
| 	    info->size, |  | ||||||
| 	    compress_staging |  | ||||||
| 	); |  | ||||||
| 	file.blob.resize(compression_size); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	metadata["compression"] = CompressionMode::LZ4; |  | ||||||
| 
 |  | ||||||
| 	file.json = metadata.dump(); |  | ||||||
| 
 |  | ||||||
| 	return file; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| } // namespace Assets
 | } // namespace Assets
 | ||||||
|  |  | ||||||
|  | @ -1,56 +1,62 @@ | ||||||
| #include <asset_parser/parser.hpp> | #include <asset_parser/parser.hpp> | ||||||
|  | #include <format> | ||||||
| #include <fstream> | #include <fstream> | ||||||
| #include <istream> | #include <utility> | ||||||
| #include <ostream> |  | ||||||
| 
 | 
 | ||||||
| namespace Assets { | namespace Assets { | ||||||
| 
 | 
 | ||||||
| auto save_binary_file(const char *path, const AssetFile &file) -> bool | // void Asset::unpack(std::byte *destination)
 | ||||||
| { | // {
 | ||||||
| 	std::ofstream outstream(path, std::ios::binary | std::ios::out); | // 	if (!m_stream.is_open())
 | ||||||
| 
 | // 	{
 | ||||||
| 	outstream.write((const char *)&file.version, sizeof(uint32_t)); | // 		throw std::logic_error {
 | ||||||
| 	outstream.write((const char *)&file.type, sizeof(AssetFile::Type)); | // 			"Failed to unpack asset: "
 | ||||||
| 
 | // 			"ifstream is closed",
 | ||||||
| 	uint32_t json_size = file.json.size(); | // 		};
 | ||||||
| 	uint32_t blob_size = file.blob.size(); | // 	}
 | ||||||
| 	outstream.write((const char *)&json_size, sizeof(uint32_t)); | //
 | ||||||
| 	outstream.write((const char *)&blob_size, sizeof(uint32_t)); | // 	switch (m_metadata.blob_compression_type)
 | ||||||
| 
 | // 	{
 | ||||||
| 	outstream.write(file.json.c_str(), json_size); | // 	case CompressionType::None:
 | ||||||
| 	outstream.write((const char *)file.blob.data(), blob_size); | // 		if (m_metadata.packed_size != m_metadata.unpacked_size)
 | ||||||
| 
 | // 		{
 | ||||||
| 	outstream.close(); | // 			throw std::logic_error {
 | ||||||
| 
 | // 				"Failed to unpack asset: "
 | ||||||
| 	outstream.close(); | // 				"compression type set to none but packed/unpacked sizes differ",
 | ||||||
| 
 | // 			};
 | ||||||
| 	return true; | // 		}
 | ||||||
| } | //
 | ||||||
| 
 | // 		m_stream.read(
 | ||||||
| auto load_binary_file(const char *path, AssetFile &out_file) -> bool | // 		    std::bit_cast<char *>(destination),
 | ||||||
| { | // 		    static_cast<long>(m_metadata.packed_size)
 | ||||||
| 	std::ifstream instream(path, std::ios::binary); | // 		);
 | ||||||
| 	instream.seekg(0ull); | // 		m_stream.close();
 | ||||||
| 
 | //
 | ||||||
| 	if (!instream.is_open()) | // 	case CompressionType::LZ4:
 | ||||||
| 		return false; | // 		m_stream.close();
 | ||||||
| 
 | // 		throw std::logic_error {
 | ||||||
| 	instream.read((char *)&out_file.version, sizeof(uint32_t)); | // 			"Failed to unpack asset: "
 | ||||||
| 	instream.read((char *)&out_file.type, sizeof(AssetFile::Type)); | // 			"LZ4 compression is not implemented yet",
 | ||||||
| 
 | // 		};
 | ||||||
| 	uint32_t json_size; | //
 | ||||||
| 	uint32_t blob_size; | //
 | ||||||
| 	instream.read((char *)&json_size, sizeof(uint32_t)); | // 	case CompressionType::LZ4HC:
 | ||||||
| 	instream.read((char *)&blob_size, sizeof(uint32_t)); | // 		m_stream.close();
 | ||||||
| 
 | // 		throw std::logic_error {
 | ||||||
| 	out_file.json.resize(json_size); | // 			"Failed to unpack asset: "
 | ||||||
| 	out_file.blob.resize(blob_size); | // 			"LZ4HC compression is not implemented yet",
 | ||||||
| 	instream.read((char *)out_file.json.data(), json_size); | // 		};
 | ||||||
| 	instream.read((char *)out_file.blob.data(), blob_size); | //
 | ||||||
| 
 | // 	default:
 | ||||||
| 	instream.close(); | // 		m_stream.close();
 | ||||||
| 
 | // 		throw std::logic_error {
 | ||||||
| 	return true; | // 			std::format(
 | ||||||
| } | // 			    "Failed to unpack asset: "
 | ||||||
|  | // 			    "Compression type was not recognized: {}",
 | ||||||
|  | // 			    std::to_underlying(m_metadata.blob_compression_type)
 | ||||||
|  | // 			),
 | ||||||
|  | // 		};
 | ||||||
|  | // 	}
 | ||||||
|  | // }
 | ||||||
| 
 | 
 | ||||||
| } // namespace Assets
 | } // namespace Assets
 | ||||||
|  |  | ||||||
|  | @ -104,7 +104,7 @@ target_link_libraries( | ||||||
|   PUBLIC opengl::opengl |   PUBLIC opengl::opengl | ||||||
|   PUBLIC glfw |   PUBLIC glfw | ||||||
|   PUBLIC imgui |   PUBLIC imgui | ||||||
|   PUBLIC stb::stb |   PUBLIC asset_parser | ||||||
|   PUBLIC yaml-cpp::yaml-cpp |   PUBLIC yaml-cpp::yaml-cpp | ||||||
|   PUBLIC EnTT::EnTT |   PUBLIC EnTT::EnTT | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ namespace Light { | ||||||
| class BasicFileHandle | class BasicFileHandle | ||||||
| { | { | ||||||
| public: | public: | ||||||
| virtual ~BasicFileHandle() = default; | 	virtual ~BasicFileHandle() = default; | ||||||
| 	BasicFileHandle( | 	BasicFileHandle( | ||||||
| 	    uint8_t *data = nullptr, | 	    uint8_t *data = nullptr, | ||||||
| 	    uint32_t size = 0ull, | 	    uint32_t size = 0ull, | ||||||
|  | @ -58,13 +58,12 @@ virtual ~BasicFileHandle() = default; | ||||||
| 		return is_valid(); | 		return is_valid(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| protected: | private: | ||||||
| 	// made protected for custom free():
 | 	// made protected for custom free():
 | ||||||
| 	uint8_t *m_data; | 	uint8_t *m_data; | ||||||
| 
 | 
 | ||||||
| 	uint32_t m_size; | 	uint32_t m_size; | ||||||
| 
 | 
 | ||||||
| private: |  | ||||||
| 	const std::string m_path; | 	const std::string m_path; | ||||||
| 
 | 
 | ||||||
| 	const std::string m_name; | 	const std::string m_name; | ||||||
|  | @ -72,68 +71,10 @@ private: | ||||||
| 	const std::string m_extension; | 	const std::string m_extension; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class ImageFileHandle: public BasicFileHandle |  | ||||||
| { |  | ||||||
| public: |  | ||||||
| virtual ~ImageFileHandle() = default; |  | ||||||
| 	ImageFileHandle( |  | ||||||
| 	    uint8_t *data, |  | ||||||
| 	    uint32_t size, |  | ||||||
| 	    const std::string &path, |  | ||||||
| 	    const std::string &name, |  | ||||||
| 	    const std::string &extension, |  | ||||||
| 	    uint32_t width, |  | ||||||
| 	    uint32_t height, |  | ||||||
| 	    uint32_t components, |  | ||||||
| 	    uint32_t desiredComponents |  | ||||||
| 	) |  | ||||||
| 	    : BasicFileHandle(data, size, path, name, extension) |  | ||||||
| 	    , m_width(width) |  | ||||||
| 	    , m_height(height) |  | ||||||
| 	    , m_components(components) |  | ||||||
| 	    , m_desired_components(desiredComponents) |  | ||||||
| 	{ |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void release() override; |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_width() const -> uint32_t |  | ||||||
| 	{ |  | ||||||
| 		return m_width; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_height() const -> uint32_t |  | ||||||
| 	{ |  | ||||||
| 		return m_height; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_components() const -> uint32_t |  | ||||||
| 	{ |  | ||||||
| 		return m_components; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_desired_components() const -> uint32_t |  | ||||||
| 	{ |  | ||||||
| 		return m_desired_components; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
| 	uint32_t m_width; |  | ||||||
| 
 |  | ||||||
| 	uint32_t m_height; |  | ||||||
| 
 |  | ||||||
| 	uint32_t m_components; |  | ||||||
| 
 |  | ||||||
| 	uint32_t m_desired_components; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class FileManager | class FileManager | ||||||
| { | { | ||||||
| public: | public: | ||||||
| 	static auto read_text_file(const std::string &path) -> BasicFileHandle; | 	static auto read_text_file(const std::string &path) -> BasicFileHandle; | ||||||
| 
 |  | ||||||
| 	static auto read_image_file(const std::string &path, int32_t desiredComponents) |  | ||||||
| 	    -> ImageFileHandle; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Light
 | } // namespace Light
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <engine/base/base.hpp> | #include <engine/base/base.hpp> | ||||||
|  | #include <filesystem> | ||||||
| 
 | 
 | ||||||
| namespace Light { | namespace Light { | ||||||
| 
 | 
 | ||||||
|  | @ -26,13 +27,9 @@ public: | ||||||
| 		instance().load_shader_impl(name, vertexPath, pixelPath); | 		instance().load_shader_impl(name, vertexPath, pixelPath); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	static void load_texture( | 	static void load_texture(const std::string &name, const std::string &path) | ||||||
| 	    const std::string &name, |  | ||||||
| 	    const std::string &path, |  | ||||||
| 	    unsigned int desiredComponents = 4u |  | ||||||
| 	) |  | ||||||
| 	{ | 	{ | ||||||
| 		instance().load_texture_impl(name, path, desiredComponents); | 		instance().load_texture_impl(name, path); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	static void release_texture(const std::string &name) | 	static void release_texture(const std::string &name) | ||||||
|  | @ -59,11 +56,7 @@ private: | ||||||
| 	    const std::string &pixelPath | 	    const std::string &pixelPath | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	void load_texture_impl( | 	void load_texture_impl(const std::string &name, const std::filesystem::path &path); | ||||||
| 	    const std::string &name, |  | ||||||
| 	    const std::string &path, |  | ||||||
| 	    unsigned int desiredComponents = 4u |  | ||||||
| 	); |  | ||||||
| 
 | 
 | ||||||
| 	void release_texture_impl(const std::string &name); | 	void release_texture_impl(const std::string &name); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,5 @@ | ||||||
| #define STB_IMAGE_IMPLEMENTATION |  | ||||||
| #include <engine/utils/file_manager.hpp> | #include <engine/utils/file_manager.hpp> | ||||||
| #include <utility> | #include <utility> | ||||||
| #include <stb_image.h> |  | ||||||
| 
 | 
 | ||||||
| namespace Light { | namespace Light { | ||||||
| 
 | 
 | ||||||
|  | @ -27,7 +25,6 @@ void BasicFileHandle::release() | ||||||
| 	m_size = 0ull; | 	m_size = 0ull; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| auto FileManager::read_text_file(const std::string &path) -> BasicFileHandle | auto FileManager::read_text_file(const std::string &path) -> BasicFileHandle | ||||||
| { | { | ||||||
| 	// parse path info
 | 	// parse path info
 | ||||||
|  | @ -63,52 +60,52 @@ auto FileManager::read_text_file(const std::string &path) -> BasicFileHandle | ||||||
| 	return { data, static_cast<unsigned int>(size), path, name, extension }; | 	return { data, static_cast<unsigned int>(size), path, name, extension }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| auto FileManager::read_image_file(const std::string &path, int32_t desiredComponents) | // auto FileManager::read_image_file(const std::string &path, int32_t desiredComponents)
 | ||||||
|     -> ImageFileHandle | //     -> ImageFileHandle
 | ||||||
| { | // {
 | ||||||
| 	// parse path info
 | // 	// parse path info
 | ||||||
| 	auto name = path.substr(0, path.find('.') + -1); | // 	auto name = path.substr(0, path.find('.') + -1);
 | ||||||
| 	auto extension = path.substr(path.find('.') + 1); | // 	auto extension = path.substr(path.find('.') + 1);
 | ||||||
|  | //
 | ||||||
|  | // 	// load image
 | ||||||
|  | // 	auto width = 0;
 | ||||||
|  | // 	auto height = 0;
 | ||||||
|  | // 	auto fetchedComponents = 0;
 | ||||||
|  | // 	auto *pixels = stbi_load(path.c_str(), &width, &height, &fetchedComponents, desiredComponents);
 | ||||||
|  | //
 | ||||||
|  | // 	// check
 | ||||||
|  | // 	if (!pixels)
 | ||||||
|  | // 	{
 | ||||||
|  | // 		log_wrn("Failed to load image file: <{}>", path);
 | ||||||
|  | // 	}
 | ||||||
|  | // 	else if (fetchedComponents != desiredComponents)
 | ||||||
|  | // 	{
 | ||||||
|  | // 		log_wrn(
 | ||||||
|  | // 		    "Mismatch of fetched/desired components: <{}> ({}/{})",
 | ||||||
|  | // 		    name + '.' + extension,
 | ||||||
|  | // 		    fetchedComponents,
 | ||||||
|  | // 		    desiredComponents
 | ||||||
|  | // 		);
 | ||||||
|  | // 	}
 | ||||||
|  | //
 | ||||||
|  | // 	return ImageFileHandle(
 | ||||||
|  | // 	    pixels,
 | ||||||
|  | // 	    width * height,
 | ||||||
|  | // 	    path,
 | ||||||
|  | // 	    name,
 | ||||||
|  | // 	    extension,
 | ||||||
|  | // 	    width,
 | ||||||
|  | // 	    height,
 | ||||||
|  | // 	    fetchedComponents,
 | ||||||
|  | // 	    desiredComponents
 | ||||||
|  | // 	);
 | ||||||
|  | // }
 | ||||||
| 
 | 
 | ||||||
| 	// load image
 | // void ImageFileHandle::release()
 | ||||||
| 	auto width = 0; | // {
 | ||||||
| 	auto height = 0; | // 	stbi_image_free(reinterpret_cast<void *>(m_data));
 | ||||||
| 	auto fetchedComponents = 0; | // 	m_data = nullptr;
 | ||||||
| 	auto *pixels = stbi_load(path.c_str(), &width, &height, &fetchedComponents, desiredComponents); | // 	m_size = 0ull;
 | ||||||
| 
 | // }
 | ||||||
| 	// check
 |  | ||||||
| 	if (!pixels) |  | ||||||
| 	{ |  | ||||||
| 		log_wrn("Failed to load image file: <{}>", path); |  | ||||||
| 	} |  | ||||||
| 	else if (fetchedComponents != desiredComponents) |  | ||||||
| 	{ |  | ||||||
| 		log_wrn( |  | ||||||
| 		    "Mismatch of fetched/desired components: <{}> ({}/{})", |  | ||||||
| 		    name + '.' + extension, |  | ||||||
| 		    fetchedComponents, |  | ||||||
| 		    desiredComponents |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return ImageFileHandle( |  | ||||||
| 	    pixels, |  | ||||||
| 	    width * height, |  | ||||||
| 	    path, |  | ||||||
| 	    name, |  | ||||||
| 	    extension, |  | ||||||
| 	    width, |  | ||||||
| 	    height, |  | ||||||
| 	    fetchedComponents, |  | ||||||
| 	    desiredComponents |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ImageFileHandle::release() |  | ||||||
| { |  | ||||||
| 	stbi_image_free(reinterpret_cast<void *>(m_data)); |  | ||||||
| 	m_data = nullptr; |  | ||||||
| 	m_size = 0ull; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| } // namespace Light
 | } // namespace Light
 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,5 @@ | ||||||
|  | #include <asset_parser/assets/texture.hpp> | ||||||
|  | #include <asset_parser/parser.hpp> | ||||||
| #include <engine/graphics/graphics_context.hpp> | #include <engine/graphics/graphics_context.hpp> | ||||||
| #include <engine/graphics/shader.hpp> | #include <engine/graphics/shader.hpp> | ||||||
| #include <engine/graphics/texture.hpp> | #include <engine/graphics/texture.hpp> | ||||||
|  | @ -12,49 +14,44 @@ void ResourceManager::load_shader_impl( | ||||||
|     const std::string &pixelPath |     const std::string &pixelPath | ||||||
| ) | ) | ||||||
| { | { | ||||||
| 	// check
 |  | ||||||
| 	lt_assert(!vertexPath.empty(), "Empty 'vertexPath'"); | 	lt_assert(!vertexPath.empty(), "Empty 'vertexPath'"); | ||||||
| 	lt_assert(!pixelPath.empty(), "Empty 'pixelPath'"); | 	lt_assert(!pixelPath.empty(), "Empty 'pixelPath'"); | ||||||
| 
 | 
 | ||||||
| 	// load files
 |  | ||||||
| 	auto vertexFile = FileManager::read_text_file(vertexPath); | 	auto vertexFile = FileManager::read_text_file(vertexPath); | ||||||
| 	auto pixelFile = FileManager::read_text_file(pixelPath); | 	auto pixelFile = FileManager::read_text_file(pixelPath); | ||||||
| 
 | 
 | ||||||
| 	// check
 |  | ||||||
| 	lt_assert(vertexFile.is_valid(), "Failed to read vertex file: {}", vertexPath); | 	lt_assert(vertexFile.is_valid(), "Failed to read vertex file: {}", vertexPath); | ||||||
| 	lt_assert(pixelFile.is_valid(), "Failed to read vertex file: {}", pixelPath); | 	lt_assert(pixelFile.is_valid(), "Failed to read vertex file: {}", pixelPath); | ||||||
| 
 | 
 | ||||||
| 	// create shader
 |  | ||||||
| 	m_shaders[name] = Ref<Shader>( | 	m_shaders[name] = Ref<Shader>( | ||||||
| 	    Shader::create(vertexFile, pixelFile, GraphicsContext::get_shared_context()) | 	    Shader::create(vertexFile, pixelFile, GraphicsContext::get_shared_context()) | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	// free file
 |  | ||||||
| 	vertexFile.release(); | 	vertexFile.release(); | ||||||
| 	pixelFile.release(); | 	pixelFile.release(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ResourceManager::load_texture_impl( | void ResourceManager::load_texture_impl(const std::string &name, const std::filesystem::path &path) | ||||||
|     const std::string &name, |  | ||||||
|     const std::string &path, |  | ||||||
|     unsigned int desiredComponents /* = 4u */ |  | ||||||
| ) |  | ||||||
| { | { | ||||||
| 	// load file
 | 	log_trc("Loading texture:"); | ||||||
| 	auto imgFile = FileManager::read_image_file(path, desiredComponents); | 	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<std::byte>(blob_metadata.uncompressed_size); | ||||||
|  | 	asset.unpack_blob(blob_metadata.tag, blob.data(), blob.size()); | ||||||
| 
 | 
 | ||||||
| 	// create texture
 |  | ||||||
| 	m_textures[name] = Ref<Texture>(Texture::create( | 	m_textures[name] = Ref<Texture>(Texture::create( | ||||||
| 	    imgFile.get_width(), | 	    metadata.pixel_size[0], | ||||||
| 	    imgFile.get_height(), | 	    metadata.pixel_size[1], | ||||||
| 	    imgFile.get_components(), | 	    metadata.num_components, | ||||||
| 	    imgFile.get_data(), | 	    std::bit_cast<unsigned char *>(blob.data()), | ||||||
| 	    GraphicsContext::get_shared_context(), | 	    GraphicsContext::get_shared_context(), | ||||||
| 	    path | 	    path | ||||||
| 	)); | 	)); | ||||||
| 
 |  | ||||||
| 	// free file
 |  | ||||||
| 	imgFile.release(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ResourceManager::release_texture_impl(const std::string &name) | void ResourceManager::release_texture_impl(const std::string &name) | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ EditorLayer::EditorLayer(const std::string &name) | ||||||
| 		m_camera_entity = m_scene->create_entity("Camera"); | 		m_camera_entity = m_scene->create_entity("Camera"); | ||||||
| 		m_camera_entity.add_component<CameraComponent>(SceneCamera(), true); | 		m_camera_entity.add_component<CameraComponent>(SceneCamera(), true); | ||||||
| 
 | 
 | ||||||
| 		ResourceManager::load_texture("Awesomeface", "data/assets/textures/awesomeface.png"); | 		ResourceManager::load_texture("Awesomeface", "data/assets/textures/awesomeface.asset"); | ||||||
| 
 | 
 | ||||||
| 		auto entity = Entity { m_scene->create_entity("Awesomeface", {}) }; | 		auto entity = Entity { m_scene->create_entity("Awesomeface", {}) }; | ||||||
| 		entity.add_component<SpriteRendererComponent>( | 		entity.add_component<SpriteRendererComponent>( | ||||||
|  |  | ||||||
|  | @ -10,10 +10,10 @@ AssetBrowserPanel::AssetBrowserPanel(Ref<Scene> active_scene) | ||||||
|     , m_assets_path("./data/assets") |     , m_assets_path("./data/assets") | ||||||
|     , m_active_scene(std::move(active_scene)) |     , m_active_scene(std::move(active_scene)) | ||||||
| { | { | ||||||
| 	ResourceManager::load_texture("_Assets_Directory", "data/engine/icons/asset/dir.png"); | 	ResourceManager::load_texture("_Assets_Directory", "data/engine/icons/asset/dir.asset"); | ||||||
| 	ResourceManager::load_texture("_Assets_Scene", "data/engine/icons/asset/scene.png"); | 	ResourceManager::load_texture("_Assets_Scene", "data/engine/icons/asset/scene.asset"); | ||||||
| 	ResourceManager::load_texture("_Assets_Image", "data/engine/icons/asset/img.png"); | 	ResourceManager::load_texture("_Assets_Image", "data/engine/icons/asset/img.asset"); | ||||||
| 	ResourceManager::load_texture("_Assets_Text", "data/engine/icons/asset/txt.png"); | 	ResourceManager::load_texture("_Assets_Text", "data/engine/icons/asset/txt.asset"); | ||||||
| 
 | 
 | ||||||
| 	m_directory_texture = ResourceManager::get_texture("_Assets_Directory"); | 	m_directory_texture = ResourceManager::get_texture("_Assets_Directory"); | ||||||
| 	m_scene_texture = ResourceManager::get_texture("_Assets_Scene"); | 	m_scene_texture = ResourceManager::get_texture("_Assets_Scene"); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue