Import material textures with mesh assets

This commit is contained in:
2026-03-26 16:22:24 +08:00
parent c479595bf5
commit e174862b8a
18 changed files with 622 additions and 21 deletions

View File

@@ -1,9 +1,54 @@
#include <XCEngine/Resources/Texture/TextureLoader.h>
#include <XCEngine/Core/Asset/ResourceManager.h>
#include <stb_image.h>
#include <filesystem>
namespace XCEngine {
namespace Resources {
namespace {
Containers::String GetResourceNameFromPath(const Containers::String& path) {
const std::filesystem::path filePath(path.CStr());
const std::string fileName = filePath.filename().string();
if (!fileName.empty()) {
return Containers::String(fileName.c_str());
}
return path;
}
LoadResult CreateTextureResource(const Containers::String& path,
TextureFormat format,
Core::uint32 width,
Core::uint32 height,
const void* pixelData,
size_t pixelDataSize) {
auto* texture = new Texture();
IResource::ConstructParams params;
params.name = GetResourceNameFromPath(path);
params.path = path;
params.guid = ResourceGUID::Generate(path);
params.memorySize = 0;
texture->Initialize(params);
if (!texture->Create(width,
height,
1,
1,
TextureType::Texture2D,
format,
pixelData,
pixelDataSize)) {
delete texture;
return LoadResult(Containers::String("Failed to create texture resource: ") + path);
}
return LoadResult(texture);
}
} // namespace
TextureLoader::TextureLoader() = default;
TextureLoader::~TextureLoader() = default;
@@ -21,8 +66,7 @@ Containers::Array<Containers::String> TextureLoader::GetSupportedExtensions() co
}
bool TextureLoader::CanLoad(const Containers::String& path) const {
Containers::String ext = GetExtension(path);
ext.ToLower();
Containers::String ext = GetExtension(path).ToLower();
return ext == "png" || ext == "jpg" || ext == "jpeg" ||
ext == "tga" || ext == "bmp" || ext == "gif" ||
@@ -32,29 +76,83 @@ bool TextureLoader::CanLoad(const Containers::String& path) const {
LoadResult TextureLoader::Load(const Containers::String& path, const ImportSettings* settings) {
(void)settings;
Containers::String ext = GetExtension(path);
ext.ToLower();
Containers::String ext = GetExtension(path).ToLower();
if (!CanLoad(path)) {
return LoadResult(Containers::String("Unsupported texture format: ") + ext);
}
if (ext == "dds") {
return LoadResult(Containers::String("DDS texture decoding is not implemented yet: ") + path);
}
Containers::Array<Core::uint8> fileData = ReadFileData(path);
if (fileData.Empty()) {
return LoadResult(Containers::String("Failed to read file: ") + path);
}
auto* texture = new Texture();
IResource::ConstructParams params;
params.name = path;
params.path = path;
params.guid = ResourceGUID::Generate(path);
params.memorySize = fileData.Size();
texture->Initialize(params);
return LoadResult(texture);
return LoadFromMemory(path, fileData.Data(), fileData.Size());
}
LoadResult TextureLoader::LoadFromMemory(const Containers::String& path, const void* data, size_t dataSize) const {
if (data == nullptr || dataSize == 0) {
return LoadResult(Containers::String("Texture data is empty: ") + path);
}
const auto* stbData = reinterpret_cast<const stbi_uc*>(data);
const int stbDataSize = static_cast<int>(dataSize);
int width = 0;
int height = 0;
int channels = 0;
if (stbi_is_hdr_from_memory(stbData, stbDataSize) != 0) {
float* pixels = stbi_loadf_from_memory(stbData,
stbDataSize,
&width,
&height,
&channels,
STBI_rgb_alpha);
if (pixels == nullptr) {
return LoadResult(Containers::String("Failed to decode HDR texture: ") + path);
}
const size_t pixelDataSize = static_cast<size_t>(width) *
static_cast<size_t>(height) *
4u *
sizeof(float);
LoadResult result = CreateTextureResource(path,
TextureFormat::RGBA32_FLOAT,
static_cast<Core::uint32>(width),
static_cast<Core::uint32>(height),
pixels,
pixelDataSize);
stbi_image_free(pixels);
return result;
}
stbi_uc* pixels = stbi_load_from_memory(stbData,
stbDataSize,
&width,
&height,
&channels,
STBI_rgb_alpha);
if (pixels == nullptr) {
return LoadResult(Containers::String("Failed to decode texture: ") + path);
}
const size_t pixelDataSize = static_cast<size_t>(width) *
static_cast<size_t>(height) *
4u *
sizeof(stbi_uc);
LoadResult result = CreateTextureResource(path,
TextureFormat::RGBA8_UNORM,
static_cast<Core::uint32>(width),
static_cast<Core::uint32>(height),
pixels,
pixelDataSize);
stbi_image_free(pixels);
return result;
}
ImportSettings* TextureLoader::GetDefaultSettings() const {