#pragma once #include #include #include #include #include #include #include #include #include namespace extra2d { // ============================================================================ // 纹理图集 - 自动将小纹理合并到大图集以减少 DrawCall // ============================================================================ /** * @brief 图集中的单个纹理条目 */ struct AtlasEntry { std::string name; // 原始纹理名称/路径 Rect uvRect; // 在图集中的 UV 坐标范围 Vec2 originalSize; // 原始纹理尺寸 uint32_t padding; // 边距(用于避免纹理 bleeding) AtlasEntry() : uvRect(), originalSize(), padding(2) {} }; /** * @brief 纹理图集页面 * 当单个图集放不下时,创建多个页面 */ class TextureAtlasPage { public: static constexpr int DEFAULT_SIZE = 2048; static constexpr int MAX_SIZE = 4096; static constexpr int MIN_TEXTURE_SIZE = 32; // 小于此大小的纹理才考虑合并 static constexpr int PADDING = 2; // 纹理间边距 TextureAtlasPage(int width = DEFAULT_SIZE, int height = DEFAULT_SIZE); ~TextureAtlasPage(); // 尝试添加纹理到图集 // 返回是否成功,如果成功则输出 uvRect bool tryAddTexture(const std::string& name, int texWidth, int texHeight, const uint8_t* pixels, Rect& outUvRect); // 获取图集纹理 Ptr getTexture() const { return texture_; } // 获取条目 const AtlasEntry* getEntry(const std::string& name) const; // 获取使用率 float getUsageRatio() const; // 获取尺寸 int getWidth() const { return width_; } int getHeight() const { return height_; } // 是否已满 bool isFull() const { return isFull_; } private: int width_, height_; Ptr texture_; std::unordered_map entries_; // 矩形打包数据 struct PackNode { int x, y, width, height; bool used; std::unique_ptr left; std::unique_ptr right; PackNode(int x_, int y_, int w, int h) : x(x_), y(y_), width(w), height(h), used(false) {} }; std::unique_ptr root_; bool isFull_; int usedArea_; // 递归插入 PackNode* insert(PackNode* node, int width, int height); void writePixels(int x, int y, int w, int h, const uint8_t* pixels); }; /** * @brief 纹理图集管理器 * 自动管理多个图集页面,提供统一的纹理查询接口 */ class TextureAtlas { public: TextureAtlas(); ~TextureAtlas(); // 初始化 void init(int pageSize = TextureAtlasPage::DEFAULT_SIZE); // 添加纹理到图集 // 如果纹理太大,返回 false,应该作为独立纹理加载 bool addTexture(const std::string& name, int width, int height, const uint8_t* pixels); // 查询纹理是否在图集中 bool contains(const std::string& name) const; // 获取纹理在图集中的信息 // 返回图集纹理和 UV 坐标 const Texture* getAtlasTexture(const std::string& name) const; Rect getUVRect(const std::string& name) const; // 获取原始纹理尺寸 Vec2 getOriginalSize(const std::string& name) const; // 获取所有图集页面 const std::vector>& getPages() const { return pages_; } // 获取总使用率 float getTotalUsageRatio() const; // 清空所有图集 void clear(); // 设置是否启用自动图集 void setEnabled(bool enabled) { enabled_ = enabled; } bool isEnabled() const { return enabled_; } // 设置纹理大小阈值(小于此大小的纹理才进入图集) void setSizeThreshold(int threshold) { sizeThreshold_ = threshold; } int getSizeThreshold() const { return sizeThreshold_; } private: std::vector> pages_; std::unordered_map entryToPage_; int pageSize_; int sizeThreshold_; bool enabled_; bool initialized_; }; /** * @brief 全局图集管理器(单例) */ class TextureAtlasManager { public: static TextureAtlasManager& getInstance(); // 获取主图集 TextureAtlas& getAtlas() { return atlas_; } // 快捷方法 bool addTexture(const std::string& name, int width, int height, const uint8_t* pixels) { return atlas_.addTexture(name, width, height, pixels); } bool contains(const std::string& name) const { return atlas_.contains(name); } const Texture* getAtlasTexture(const std::string& name) const { return atlas_.getAtlasTexture(name); } Rect getUVRect(const std::string& name) const { return atlas_.getUVRect(name); } private: TextureAtlasManager() = default; ~TextureAtlasManager() = default; TextureAtlasManager(const TextureAtlasManager&) = delete; TextureAtlasManager& operator=(const TextureAtlasManager&) = delete; TextureAtlas atlas_; }; } // namespace extra2d