diff --git a/3rdParty/CMakeLists.txt b/3rdParty/CMakeLists.txt index eb47921..c9bc665 100644 --- a/3rdParty/CMakeLists.txt +++ b/3rdParty/CMakeLists.txt @@ -41,4 +41,5 @@ if(ENABLE_TEST) add_subdirectory(catch2) endif() -add_subdirectory(tinyusdz) \ No newline at end of file +add_subdirectory(tinyusdz) +add_subdirectory(ktx-software) \ No newline at end of file diff --git a/3rdParty/ktx-software/CMakeLists.txt b/3rdParty/ktx-software/CMakeLists.txt new file mode 100644 index 0000000..34f8475 --- /dev/null +++ b/3rdParty/ktx-software/CMakeLists.txt @@ -0,0 +1,19 @@ +include(FetchContent) + +if(NOT DEFINED KTX_REPO) + set(KTX_REPO https://github.com/KhronosGroup/KTX-Software.git) +endif () + +FetchContent_Declare( + ktx + EXCLUDE_FROM_ALL + GIT_REPOSITORY ${KTX_REPO} + GIT_TAG v4.3.2 + GIT_SHALLOW TRUE +) + +set(LIB_TYPE_DEFAULT OFF CACHE BOOL "" FORCE) +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) +set(KTX_FEATURE_STATIC_LIBRARY ON CACHE BOOL "" FORCE) + +FetchContent_MakeAvailable(ktx) \ No newline at end of file diff --git a/openVulkanoCpp/CMakeLists.txt b/openVulkanoCpp/CMakeLists.txt index 8ed12cd..dfb5641 100644 --- a/openVulkanoCpp/CMakeLists.txt +++ b/openVulkanoCpp/CMakeLists.txt @@ -67,7 +67,7 @@ if (NOT ANDROID AND NOT IOS) endif() endif() -target_link_libraries(openVulkanoCpp PUBLIC magic_enum yaml-cpp fmt spdlog glm pugixml stb eigen utf8cpp imgui_internal TracyClient stud-uuid ryml unordered_dense units) +target_link_libraries(openVulkanoCpp PUBLIC magic_enum yaml-cpp fmt spdlog glm pugixml stb eigen utf8cpp imgui_internal TracyClient stud-uuid ryml unordered_dense units ktx) LinkAssimp(openVulkanoCpp) LinkLibArchive(openVulkanoCpp) LinkLibJpegTurbo(openVulkanoCpp) diff --git a/openVulkanoCpp/Image/Image.hpp b/openVulkanoCpp/Image/Image.hpp index b440de3..22a43f0 100644 --- a/openVulkanoCpp/Image/Image.hpp +++ b/openVulkanoCpp/Image/Image.hpp @@ -17,6 +17,8 @@ namespace OpenVulkano::Image JPEG, PNG, BMP, + KTX, + DDS, }; struct Image diff --git a/openVulkanoCpp/Image/ImageLoaderKtx.cpp b/openVulkanoCpp/Image/ImageLoaderKtx.cpp new file mode 100644 index 0000000..4b18ec9 --- /dev/null +++ b/openVulkanoCpp/Image/ImageLoaderKtx.cpp @@ -0,0 +1,109 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "ImageLoaderKtx.hpp" + +#include + +#include +#include +#include +#include + +namespace OpenVulkano::Image +{ + std::unique_ptr ImageLoaderKtx::loadFromFile(const std::string& filePath) + { + ktxTexture* texture; + KTX_error_code result = + ktxTexture_CreateFromNamedFile(filePath.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &texture); + + if (result != KTX_SUCCESS) + { + throw std::runtime_error("Failed to load KTX texture: " + std::string(ktxErrorString(result))); + } + + auto image = ExtractImage(texture); + ktxTexture_Destroy(texture); + return image; + } + + std::unique_ptr ImageLoaderKtx::loadFromMemory(const std::vector& buffer) + { + ktxTexture* texture; + KTX_error_code result = + ktxTexture_CreateFromMemory(buffer.data(), buffer.size(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &texture); + + if (result != KTX_SUCCESS) + { + throw std::runtime_error("Failed to load KTX texture from memory: " + std::string(ktxErrorString(result))); + } + + auto image = ExtractImage(texture); + ktxTexture_Destroy(texture); + return image; + } + + Math::Vector2i ImageLoaderKtx::GetImageDimensions(const std::string& filename) + { + ktxTexture* texture; + KTX_error_code result = + ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &texture); + + if (result != KTX_SUCCESS) + { + throw std::runtime_error("Failed to load KTX texture for dimensions: " + + std::string(ktxErrorString(result))); + } + + Math::Vector2i dimensions(texture->baseWidth, texture->baseHeight); + ktxTexture_Destroy(texture); + return dimensions; + } + + std::unique_ptr ImageLoaderKtx::ExtractImage(ktxTexture* texture) + { + if (!texture->pData) + { + throw std::runtime_error("No image data found in KTX texture."); + } + + auto width = static_cast(texture->baseWidth); + auto height = static_cast(texture->baseHeight); + + auto image = std::make_unique(); + image->resolution.x = width; + image->resolution.y = height; + image->resolution.z = 1; + + if (texture->classId == ktxTexture1_c) + { + ktxTexture1* tx = reinterpret_cast(texture); + DataFormat format = DataFormat::Format::UNDEFINED; + switch (tx->glInternalformat) + { + case 0x8051: /* GL_RGB8_EXT */ format = DataFormat::Format::R8G8B8_UNORM; break; + case 0x8054: /* GL_RGB16_EXT */ format = DataFormat::Format::R16G16B16_UNORM; break; + case 0x8057: /* GL_RGB5_A1_EXT */ format = DataFormat::Format::R5G5B5A1_UNORM_PACK16; break; + case 0x8058: /* GL_RGBA8_EXT */ format = DataFormat::Format::R8G8B8A8_UNORM; break; + case 0x8059: /* GL_RGB10_A2_EXT */ format = DataFormat::Format::A2R10G10B10_UNORM_PACK32; break; + case 0x805B: /* GL_RGBA16_EXT */ format = DataFormat::Format::R16G16B16A16_UNORM; break; + default: throw std::runtime_error("Unhandled texture1 format: " + tx->glInternalformat); + } + image->dataFormat = format; + } + else if (texture->classId == ktxTexture2_c) + { + ktxTexture2* tx = reinterpret_cast(texture); + image->dataFormat = *reinterpret_cast(&tx->vkFormat); + } + + image->data = Array(texture->dataSize); + memcpy(image->data.Data(), texture->pData, image->data.Size()); + + return image; + } +} \ No newline at end of file diff --git a/openVulkanoCpp/Image/ImageLoaderKtx.hpp b/openVulkanoCpp/Image/ImageLoaderKtx.hpp new file mode 100644 index 0000000..c9f9db9 --- /dev/null +++ b/openVulkanoCpp/Image/ImageLoaderKtx.hpp @@ -0,0 +1,25 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "ImageLoader.hpp" + +struct ktxTexture; + +namespace OpenVulkano::Image +{ + class ImageLoaderKtx : public IImageLoader + { + public: + std::unique_ptr loadFromFile(const std::string& filePath) override; + std::unique_ptr loadFromMemory(const std::vector& buffer) override; + Math::Vector2i GetImageDimensions(const std::string& filename) override; + + protected: + std::unique_ptr ExtractImage(ktxTexture* texture); + }; +}