feat: asset baking

Only supported .png textures at the moment
This commit is contained in:
light7734 2025-07-09 15:30:54 +03:30
parent 71d08cbe9f
commit 38997b3908
Signed by: light7734
GPG key ID: 8C30176798F1A6BA
23 changed files with 594 additions and 393 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -5,6 +5,7 @@ Layout
{version} | 4 bytes, ie. uint32_t
{general metadata} | sizeof(AssetMetadata)
{specialized metadata} | sizeof(XXXAssetMetadata), eg. TextureAssetMetadata
{n} | 4 bytes, ie. uint32_t
{blob_0...n metadata} | n * sizeof(BlobMetadata)
{blob_0...n data} | variable size based on actual data
{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
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 data -> The actual data, packed and compressed to be reacdy for direct engine consumption.

View file

@ -0,0 +1,4 @@
Resource Management
===================================================================================================

View file

@ -6,4 +6,5 @@ target_link_libraries(
asset_baker
PRIVATE asset_parser
PRIVATE stb::stb
PRIVATE logger
)

View 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

View file

@ -1,85 +1,70 @@
#include <asset_baker/bakers.hpp>
#include <asset_parser/assets/texture.hpp>
#include <asset_parser/parser.hpp>
#include <filesystem>
#include <iostream>
#include <logger/logger.hpp>
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#define ASSERT(x, ...) \
if (!(x)) \
{ \
log(__VA_ARGS__); \
return -1; \
}
template<typename... Args>
void log(Args &&...args)
void try_packing_texture(
const std::filesystem::path &in_path,
const std::filesystem::path &out_path
)
{
(std::cout << ... << args);
std::cout << '\n';
}
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]))
auto texture_loader = lt::TextureLoaderFactory::create(in_path.extension().string());
if (!texture_loader)
{
if (p.path().extension() == ".png")
{
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);
}
// Don't log anything; this is expected.
return;
}
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;
}

View file

@ -7,4 +7,5 @@ target_link_libraries(
asset_parser
PRIVATE LZ4::lz4_static
PRIVATE nlohmann_json::nlohmann_json
PRIVATE logger
)

View file

@ -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

View file

@ -1,34 +1,276 @@
#pragma once
#include <compressors/compressors.hpp>
#include <cstdint>
#include <string>
#include <filesystem>
#include <fstream>
#include <logger/logger.hpp>
#include <utility>
#include <vector>
namespace Assets {
struct AssetFile
{
uint32_t version;
constexpr auto current_version = uint32_t { 1 };
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)
{
Texture,
Mesh,
Material,
} type;
};
std::string json;
std::vector<uint8_t> blob;
struct Metadata
{
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,
LZ4,
LZ4HC,
};
public:
enum class Format : uint32_t // NOLINT(performance-enum-size)
{
None = 0,
RGBA8,
};
auto save_binary_file(const char *path, const AssetFile &in_file) -> bool;
auto load_binary_file(const char *path, AssetFile &out_file) -> bool;
struct Metadata
{
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 *)&current_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

View file

@ -0,0 +1,14 @@
#pragma once
#include <cstdint>
namespace Assets {
enum class CompressionType : uint32_t // NOLINT(performance-enum-size)
{
None,
LZ4,
LZ4HC,
};
}

View file

@ -2,79 +2,11 @@
#include <lz4.h>
#include <nlohmann/json.hpp>
// [version], [type] --
// [asset_metadata], [blob_metadata] --
// [blob] --
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

View file

@ -1,56 +1,62 @@
#include <asset_parser/parser.hpp>
#include <format>
#include <fstream>
#include <istream>
#include <ostream>
#include <utility>
namespace Assets {
auto save_binary_file(const char *path, const AssetFile &file) -> bool
{
std::ofstream outstream(path, std::ios::binary | std::ios::out);
outstream.write((const char *)&file.version, sizeof(uint32_t));
outstream.write((const char *)&file.type, sizeof(AssetFile::Type));
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));
outstream.write(file.json.c_str(), json_size);
outstream.write((const char *)file.blob.data(), blob_size);
outstream.close();
outstream.close();
return true;
}
auto load_binary_file(const char *path, AssetFile &out_file) -> bool
{
std::ifstream instream(path, std::ios::binary);
instream.seekg(0ull);
if (!instream.is_open())
return false;
instream.read((char *)&out_file.version, sizeof(uint32_t));
instream.read((char *)&out_file.type, sizeof(AssetFile::Type));
uint32_t json_size;
uint32_t blob_size;
instream.read((char *)&json_size, sizeof(uint32_t));
instream.read((char *)&blob_size, sizeof(uint32_t));
out_file.json.resize(json_size);
out_file.blob.resize(blob_size);
instream.read((char *)out_file.json.data(), json_size);
instream.read((char *)out_file.blob.data(), blob_size);
instream.close();
return true;
}
// void Asset::unpack(std::byte *destination)
// {
// if (!m_stream.is_open())
// {
// throw std::logic_error {
// "Failed to unpack asset: "
// "ifstream is closed",
// };
// }
//
// switch (m_metadata.blob_compression_type)
// {
// case CompressionType::None:
// if (m_metadata.packed_size != m_metadata.unpacked_size)
// {
// throw std::logic_error {
// "Failed to unpack asset: "
// "compression type set to none but packed/unpacked sizes differ",
// };
// }
//
// m_stream.read(
// std::bit_cast<char *>(destination),
// static_cast<long>(m_metadata.packed_size)
// );
// m_stream.close();
//
// case CompressionType::LZ4:
// m_stream.close();
// throw std::logic_error {
// "Failed to unpack asset: "
// "LZ4 compression is not implemented yet",
// };
//
//
// case CompressionType::LZ4HC:
// m_stream.close();
// throw std::logic_error {
// "Failed to unpack asset: "
// "LZ4HC compression is not implemented yet",
// };
//
// default:
// m_stream.close();
// throw std::logic_error {
// std::format(
// "Failed to unpack asset: "
// "Compression type was not recognized: {}",
// std::to_underlying(m_metadata.blob_compression_type)
// ),
// };
// }
// }
} // namespace Assets

View file

@ -104,7 +104,7 @@ target_link_libraries(
PUBLIC opengl::opengl
PUBLIC glfw
PUBLIC imgui
PUBLIC stb::stb
PUBLIC asset_parser
PUBLIC yaml-cpp::yaml-cpp
PUBLIC EnTT::EnTT
)

View file

@ -7,7 +7,7 @@ namespace Light {
class BasicFileHandle
{
public:
virtual ~BasicFileHandle() = default;
virtual ~BasicFileHandle() = default;
BasicFileHandle(
uint8_t *data = nullptr,
uint32_t size = 0ull,
@ -58,13 +58,12 @@ virtual ~BasicFileHandle() = default;
return is_valid();
}
protected:
private:
// made protected for custom free():
uint8_t *m_data;
uint32_t m_size;
private:
const std::string m_path;
const std::string m_name;
@ -72,68 +71,10 @@ private:
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
{
public:
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

View file

@ -1,6 +1,7 @@
#pragma once
#include <engine/base/base.hpp>
#include <filesystem>
namespace Light {
@ -26,13 +27,9 @@ public:
instance().load_shader_impl(name, vertexPath, pixelPath);
}
static void load_texture(
const std::string &name,
const std::string &path,
unsigned int desiredComponents = 4u
)
static void load_texture(const std::string &name, const std::string &path)
{
instance().load_texture_impl(name, path, desiredComponents);
instance().load_texture_impl(name, path);
}
static void release_texture(const std::string &name)
@ -59,11 +56,7 @@ private:
const std::string &pixelPath
);
void load_texture_impl(
const std::string &name,
const std::string &path,
unsigned int desiredComponents = 4u
);
void load_texture_impl(const std::string &name, const std::filesystem::path &path);
void release_texture_impl(const std::string &name);

View file

@ -1,7 +1,5 @@
#define STB_IMAGE_IMPLEMENTATION
#include <engine/utils/file_manager.hpp>
#include <utility>
#include <stb_image.h>
namespace Light {
@ -27,7 +25,6 @@ void BasicFileHandle::release()
m_size = 0ull;
}
auto FileManager::read_text_file(const std::string &path) -> BasicFileHandle
{
// 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 };
}
auto FileManager::read_image_file(const std::string &path, int32_t desiredComponents)
-> ImageFileHandle
{
// parse path info
auto name = path.substr(0, path.find('.') + -1);
auto extension = path.substr(path.find('.') + 1);
// auto FileManager::read_image_file(const std::string &path, int32_t desiredComponents)
// -> ImageFileHandle
// {
// // parse path info
// auto name = path.substr(0, 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
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
);
}
void ImageFileHandle::release()
{
stbi_image_free(reinterpret_cast<void *>(m_data));
m_data = nullptr;
m_size = 0ull;
}
// void ImageFileHandle::release()
// {
// stbi_image_free(reinterpret_cast<void *>(m_data));
// m_data = nullptr;
// m_size = 0ull;
// }
} // namespace Light

View file

@ -1,3 +1,5 @@
#include <asset_parser/assets/texture.hpp>
#include <asset_parser/parser.hpp>
#include <engine/graphics/graphics_context.hpp>
#include <engine/graphics/shader.hpp>
#include <engine/graphics/texture.hpp>
@ -12,49 +14,44 @@ void ResourceManager::load_shader_impl(
const std::string &pixelPath
)
{
// check
lt_assert(!vertexPath.empty(), "Empty 'vertexPath'");
lt_assert(!pixelPath.empty(), "Empty 'pixelPath'");
// load files
auto vertexFile = FileManager::read_text_file(vertexPath);
auto pixelFile = FileManager::read_text_file(pixelPath);
// check
lt_assert(vertexFile.is_valid(), "Failed to read vertex file: {}", vertexPath);
lt_assert(pixelFile.is_valid(), "Failed to read vertex file: {}", pixelPath);
// create shader
m_shaders[name] = Ref<Shader>(
Shader::create(vertexFile, pixelFile, GraphicsContext::get_shared_context())
);
// free file
vertexFile.release();
pixelFile.release();
}
void ResourceManager::load_texture_impl(
const std::string &name,
const std::string &path,
unsigned int desiredComponents /* = 4u */
)
void ResourceManager::load_texture_impl(const std::string &name, const std::filesystem::path &path)
{
// load file
auto imgFile = FileManager::read_image_file(path, desiredComponents);
log_trc("Loading texture:");
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(
imgFile.get_width(),
imgFile.get_height(),
imgFile.get_components(),
imgFile.get_data(),
metadata.pixel_size[0],
metadata.pixel_size[1],
metadata.num_components,
std::bit_cast<unsigned char *>(blob.data()),
GraphicsContext::get_shared_context(),
path
));
// free file
imgFile.release();
}
void ResourceManager::release_texture_impl(const std::string &name)

View file

@ -28,7 +28,7 @@ EditorLayer::EditorLayer(const std::string &name)
m_camera_entity = m_scene->create_entity("Camera");
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", {}) };
entity.add_component<SpriteRendererComponent>(

View file

@ -10,10 +10,10 @@ AssetBrowserPanel::AssetBrowserPanel(Ref<Scene> active_scene)
, m_assets_path("./data/assets")
, m_active_scene(std::move(active_scene))
{
ResourceManager::load_texture("_Assets_Directory", "data/engine/icons/asset/dir.png");
ResourceManager::load_texture("_Assets_Scene", "data/engine/icons/asset/scene.png");
ResourceManager::load_texture("_Assets_Image", "data/engine/icons/asset/img.png");
ResourceManager::load_texture("_Assets_Text", "data/engine/icons/asset/txt.png");
ResourceManager::load_texture("_Assets_Directory", "data/engine/icons/asset/dir.asset");
ResourceManager::load_texture("_Assets_Scene", "data/engine/icons/asset/scene.asset");
ResourceManager::load_texture("_Assets_Image", "data/engine/icons/asset/img.asset");
ResourceManager::load_texture("_Assets_Text", "data/engine/icons/asset/txt.asset");
m_directory_texture = ResourceManager::get_texture("_Assets_Directory");
m_scene_texture = ResourceManager::get_texture("_Assets_Scene");