#pragma once #include #include #include #include #include namespace gz::vk { /** * @brief Describes an area in the textureImage that is not in use */ struct TextureImageArea { // topleft slot uint16_t x; uint16_t y; // in slots uint16_t width; uint16_t height; std::string toString() const; }; /// strict weak ordering comparison, true if a < b inline auto freeAreaCmp = [](const TextureImageArea& a, const TextureImageArea& b) { // if a size < b size if (a.width * a.height < b.width * b.height) { return true; } if (a.width * a.height != b.width * b.height) { return false; } // if a size == b size, return true if a is toplefter if (a.x + a.y < b.x + b.y) { return true; } if (a.x + a.y != b.x + b.y) { return false; } // if both are same topleft return if a is lefter return a.x < b.x; }; /// Defined in vulkan_instance.hpp class VulkanInstance; class TextureAtlas { public: /** * @brief Create a texture atlas * @details * -# @ref VulkanInstance::registerCleanupCallback "register" @ref cleanup() "cleanup callback" * -# @ref createImageResources "create texture image, view and sampler" * * The textureImage will have the dimensions slotWidth * slotCountX, slotHeight * slotCountY */ TextureAtlas(VulkanInstance& instance, uint16_t slotWidth, uint16_t slotHeight, uint16_t slotCountX, uint16_t slotCountY); /** * @brief Add a texture to the atlas * @param textureWidth Width in pixels * @param textureHeight Height in pixels * @returns The topleft and bottomright texture coordinates in the image of the atlas * @throws Exception when there is no space in the atlas to add the texture */ std::pair addTexture(uint8_t* pixels, uint16_t textureWidth, uint16_t textureHeight); const VkImageView& getTextureImageView() const { return textureImageView; } const VkSampler& getTextureSampler() const { return textureSampler; } std::string toString() const; private: VulkanInstance& vk; /** * @brief Destroy all vulkan objects owned by this object */ void cleanup(); void blitTextureOnImage(uint8_t* pixels, uint16_t slotX, uint16_t slotY, uint16_t textureWidth, uint16_t textureHeight); /** * @brief Create textureImage, textureImageView and textureSampler * @details * the textureImage is created with missingTextureColor and then transitioned to SHADER_READ_ONLY_OPTIMAL layout. */ void createImageResources(); VkImage textureImage; VkDeviceMemory textureImageMemory; VkImageView textureImageView; VkSampler textureSampler; std::set freeAreas; /** * @todo implement merge */ void mergeFreeAreas(); uint16_t slotWidth; uint16_t slotHeight; uint16_t slotCountX; uint16_t slotCountY; }; } // namespace gz::vk