#include #include #include #define STB_IMAGE_IMPLEMENTATION #include namespace extra2d { Texture::Texture() = default; Texture::~Texture() { // RHI 纹理句柄是轻量级句柄,不需要显式释放 // 实际的纹理资源由 RHI 设备管理 handle_ = TextureHandle(); } bool Texture::loadFromFile(const std::string& path) { // 加载图片 int channels; stbi_set_flip_vertically_on_load(true); unsigned char* data = stbi_load(path.c_str(), &width_, &height_, &channels, 0); if (!data) { E2D_LOG_ERROR("Failed to load texture: {}", path); return false; } // 根据通道数确定格式 TextureFormat format; switch (channels) { case 1: format = TextureFormat::R8; break; case 2: format = TextureFormat::RG8; break; case 3: format = TextureFormat::RGB8; break; case 4: format = TextureFormat::RGBA8; break; default: format = TextureFormat::RGBA8; break; } bool result = loadFromMemory(data, width_, height_, format); stbi_image_free(data); if (result) { E2D_LOG_DEBUG("Texture loaded: {} ({}x{})", path, width_, height_); } return result; } bool Texture::loadFromMemory(const uint8_t* data, int width, int height, TextureFormat format) { // 释放旧纹理 handle_ = TextureHandle(); width_ = width; height_ = height; format_ = format; // 获取 RHI 设备 auto* rhiModule = RHIModule::get(); if (!rhiModule) { E2D_LOG_ERROR("RHIModule not available"); return false; } auto* device = rhiModule->getDevice(); if (!device) { E2D_LOG_ERROR("RHIDevice not available"); return false; } // 创建纹理描述 TextureDesc desc; desc.width = static_cast(width); desc.height = static_cast(height); desc.format = format; desc.mipLevels = 1; // 初始创建 1 层,后续生成 mipmap // 创建 RHI 纹理 auto texture = device->createTexture(desc); if (!texture) { E2D_LOG_ERROR("Failed to create RHI texture"); return false; } // 上传纹理数据 if (data) { // 注意:update 方法的参数需要根据实际 RHI 接口调整 // 这里假设 update 接受数据指针 texture->update(data, static_cast(width * height * getBytesPerPixel(format))); // 生成 mipmap // 注意:generateMipmap 方法需要在 RHI 接口中实现 } // 获取纹理句柄 handle_ = TextureHandle(texture.release()); return true; } bool Texture::create(int width, int height, TextureFormat format) { // 释放旧纹理 handle_ = TextureHandle(); width_ = width; height_ = height; format_ = format; // 获取 RHI 设备 auto* rhiModule = RHIModule::get(); if (!rhiModule) { E2D_LOG_ERROR("RHIModule not available"); return false; } auto* device = rhiModule->getDevice(); if (!device) { E2D_LOG_ERROR("RHIDevice not available"); return false; } // 创建纹理描述 TextureDesc desc; desc.width = static_cast(width); desc.height = static_cast(height); desc.format = format; desc.mipLevels = 1; // 不生成 mipmap // 创建 RHI 纹理 auto texture = device->createTexture(desc); if (!texture) { E2D_LOG_ERROR("Failed to create RHI texture"); return false; } // 获取纹理句柄 handle_ = TextureHandle(texture.release()); return true; } bool Texture::reloadFromFile(const std::string& path) { // 加载图片 int channels; stbi_set_flip_vertically_on_load(true); unsigned char* data = stbi_load(path.c_str(), &width_, &height_, &channels, 0); if (!data) { E2D_LOG_ERROR("Failed to reload texture: {}", path); return false; } // 根据通道数确定格式 TextureFormat format; switch (channels) { case 1: format = TextureFormat::R8; break; case 2: format = TextureFormat::RG8; break; case 3: format = TextureFormat::RGB8; break; case 4: format = TextureFormat::RGBA8; break; default: format = TextureFormat::RGBA8; break; } bool result = reloadFromMemory(data, width_, height_, format); stbi_image_free(data); if (result) { E2D_LOG_INFO("Texture reloaded: {} ({}x{})", path, width_, height_); } return result; } bool Texture::reloadFromMemory(const uint8_t* data, int width, int height, TextureFormat format) { // 更新尺寸和格式 width_ = width; height_ = height; format_ = format; // 获取 RHI 设备 auto* rhiModule = RHIModule::get(); if (!rhiModule) { E2D_LOG_ERROR("RHIModule not available"); return false; } auto* device = rhiModule->getDevice(); if (!device) { E2D_LOG_ERROR("RHIDevice not available"); return false; } // 创建新的纹理描述 TextureDesc desc; desc.width = static_cast(width); desc.height = static_cast(height); desc.format = format; desc.mipLevels = 1; // 创建新的 RHI 纹理 auto texture = device->createTexture(desc); if (!texture) { E2D_LOG_ERROR("Failed to create RHI texture during reload"); return false; } // 上传纹理数据 if (data) { texture->update(data, static_cast(width * height * getBytesPerPixel(format))); } // 替换旧的纹理句柄 handle_ = TextureHandle(texture.release()); return true; } // 辅助函数:获取每个像素的字节数 uint32_t Texture::getBytesPerPixel(TextureFormat format) { switch (format) { case TextureFormat::R8: return 1; case TextureFormat::RG8: return 2; case TextureFormat::RGB8: return 3; case TextureFormat::RGBA8: case TextureFormat::RGBA8_SRGB: return 4; case TextureFormat::Depth16: return 2; case TextureFormat::Depth24: return 3; case TextureFormat::Depth32F: return 4; case TextureFormat::Depth24Stencil8: return 4; case TextureFormat::Depth32FStencil8: return 5; default: return 4; } } } // namespace extra2d