#include "TextureLoader.h" #include "../RHI/RHIDevice.h" #define STB_IMAGE_IMPLEMENTATION #include #include #include namespace grove { TextureLoader::LoadResult TextureLoader::loadFromFile(rhi::IRHIDevice& device, const std::string& path) { LoadResult result; spdlog::info("📂 TextureLoader: Loading texture from '{}'", path); // Read file into memory std::ifstream file(path, std::ios::binary | std::ios::ate); if (!file.is_open()) { result.error = "Failed to open file: " + path; spdlog::error("❌ TextureLoader: FAILED to open file '{}'", path); return result; } std::streamsize size = file.tellg(); file.seekg(0, std::ios::beg); std::vector buffer(static_cast(size)); if (!file.read(reinterpret_cast(buffer.data()), size)) { result.error = "Failed to read file: " + path; spdlog::error("❌ TextureLoader: FAILED to read file '{}'", path); return result; } spdlog::info("✅ TextureLoader: File '{}' read successfully ({} bytes)", path, size); auto loadResult = loadFromMemory(device, buffer.data(), buffer.size()); if (loadResult.success) { spdlog::info("✅ TextureLoader: Texture '{}' loaded successfully ({}x{}, handle={})", path, loadResult.width, loadResult.height, loadResult.handle.id); } else { spdlog::error("❌ TextureLoader: FAILED to load texture '{}': {}", path, loadResult.error); } return loadResult; } TextureLoader::LoadResult TextureLoader::loadFromMemory(rhi::IRHIDevice& device, const uint8_t* data, size_t size) { LoadResult result; // Decode image with stb_image int width, height, channels; // Force RGBA output (4 channels) stbi_uc* pixels = stbi_load_from_memory(data, static_cast(size), &width, &height, &channels, 4); if (!pixels) { result.error = "stb_image failed: "; result.error += stbi_failure_reason(); return result; } // Log decoded image info spdlog::info("TextureLoader: Decoded image {}x{} (original {} channels, converted to RGBA)", width, height, channels); if (width > 0 && height > 0) { spdlog::info(" First pixel: R={}, G={}, B={}, A={}", pixels[0], pixels[1], pixels[2], pixels[3]); spdlog::info(" Last pixel: R={}, G={}, B={}, A={}", pixels[(width*height-1)*4 + 0], pixels[(width*height-1)*4 + 1], pixels[(width*height-1)*4 + 2], pixels[(width*height-1)*4 + 3]); } // Create texture via RHI rhi::TextureDesc desc; desc.width = static_cast(width); desc.height = static_cast(height); desc.format = rhi::TextureDesc::RGBA8; desc.data = pixels; desc.dataSize = static_cast(width * height * 4); result.handle = device.createTexture(desc); result.width = desc.width; result.height = desc.height; result.success = result.handle.isValid(); if (result.success) { spdlog::info("✅ TextureLoader: GPU texture created successfully (handle={})", result.handle.id); } else { result.error = "Failed to create GPU texture"; spdlog::error("❌ TextureLoader: FAILED to create GPU texture (handle invalid)"); } // Free stb_image memory stbi_image_free(pixels); return result; } } // namespace grove