Merge pull request 'KTX and DDS image file loaders' (#169) from ktx_dds into master
Reviewed-on: https://git.madvoxel.net/OpenVulkano/OpenVulkano/pulls/169 Reviewed-by: Georg Hagen <georg.hagen@madvoxel.com>
This commit is contained in:
4
3rdParty/CMakeLists.txt
vendored
4
3rdParty/CMakeLists.txt
vendored
@@ -41,4 +41,6 @@ if(ENABLE_TEST)
|
|||||||
add_subdirectory(catch2)
|
add_subdirectory(catch2)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(tinyusdz)
|
add_subdirectory(tinyusdz)
|
||||||
|
add_subdirectory(ktx-software)
|
||||||
|
add_subdirectory(dds_image)
|
||||||
15
3rdParty/dds_image/CMakeLists.txt
vendored
Normal file
15
3rdParty/dds_image/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
if(NOT DEFINED DDS_IMAGE_REPO)
|
||||||
|
set(DDS_IMAGE_REPO https://github.com/spnda/dds_image.git)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
dds_image
|
||||||
|
EXCLUDE_FROM_ALL
|
||||||
|
GIT_REPOSITORY ${DDS_IMAGE_REPO}
|
||||||
|
GIT_TAG main
|
||||||
|
GIT_SHALLOW TRUE
|
||||||
|
)
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(dds_image)
|
||||||
20
3rdParty/ktx-software/CMakeLists.txt
vendored
Normal file
20
3rdParty/ktx-software/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
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(BASISU_SUPPORT_SSE OFF CACHE BOOL "" FORCE)
|
||||||
|
set(KTX_FEATURE_STATIC_LIBRARY ON CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(ktx)
|
||||||
@@ -67,7 +67,7 @@ if (NOT ANDROID AND NOT IOS)
|
|||||||
endif()
|
endif()
|
||||||
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 dds_image)
|
||||||
LinkAssimp(openVulkanoCpp)
|
LinkAssimp(openVulkanoCpp)
|
||||||
LinkLibArchive(openVulkanoCpp)
|
LinkLibArchive(openVulkanoCpp)
|
||||||
LinkLibJpegTurbo(openVulkanoCpp)
|
LinkLibJpegTurbo(openVulkanoCpp)
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ namespace OpenVulkano::Image
|
|||||||
JPEG,
|
JPEG,
|
||||||
PNG,
|
PNG,
|
||||||
BMP,
|
BMP,
|
||||||
|
KTX,
|
||||||
|
DDS,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Image
|
struct Image
|
||||||
|
|||||||
175
openVulkanoCpp/Image/ImageLoaderDds.cpp
Normal file
175
openVulkanoCpp/Image/ImageLoaderDds.cpp
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* 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 "ImageLoaderDds.hpp"
|
||||||
|
|
||||||
|
#include <dds.hpp>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <magic_enum.hpp>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::unordered_map<DXGI_FORMAT, OpenVulkano::DataFormat> DXGI_TO_OV_DATAFORMAT = {
|
||||||
|
{ DXGI_FORMAT_R32G32B32A32_FLOAT, OpenVulkano::DataFormat::Format::R32G32B32A32_SFLOAT },
|
||||||
|
{ DXGI_FORMAT_R32G32B32A32_UINT, OpenVulkano::DataFormat::Format::R32G32B32A32_UINT },
|
||||||
|
{ DXGI_FORMAT_R32G32B32A32_SINT, OpenVulkano::DataFormat::Format::R32G32B32A32_SINT },
|
||||||
|
{ DXGI_FORMAT_R32G32B32_FLOAT, OpenVulkano::DataFormat::Format::R32G32B32_SFLOAT },
|
||||||
|
{ DXGI_FORMAT_R32G32B32_UINT, OpenVulkano::DataFormat::Format::R32G32B32_UINT },
|
||||||
|
{ DXGI_FORMAT_R32G32B32_SINT, OpenVulkano::DataFormat::Format::R32G32B32_SINT },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_R16G16B16A16_FLOAT, OpenVulkano::DataFormat::Format::R16G16B16A16_SFLOAT },
|
||||||
|
{ DXGI_FORMAT_R16G16B16A16_UNORM, OpenVulkano::DataFormat::Format::R16G16B16A16_UNORM },
|
||||||
|
{ DXGI_FORMAT_R16G16B16A16_UINT, OpenVulkano::DataFormat::Format::R16G16B16A16_UINT },
|
||||||
|
{ DXGI_FORMAT_R16G16B16A16_SNORM, OpenVulkano::DataFormat::Format::R16G16B16A16_SNORM },
|
||||||
|
{ DXGI_FORMAT_R16G16B16A16_SINT, OpenVulkano::DataFormat::Format::R16G16B16A16_SINT },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_R32G32_FLOAT, OpenVulkano::DataFormat::Format::R32G32_SFLOAT },
|
||||||
|
{ DXGI_FORMAT_R32G32_UINT, OpenVulkano::DataFormat::Format::R32G32_UINT },
|
||||||
|
{ DXGI_FORMAT_R32G32_SINT, OpenVulkano::DataFormat::Format::R32G32_SINT },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_D32_FLOAT_S8X24_UINT, OpenVulkano::DataFormat::Format::D32_SFLOAT_S8_UINT },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_R8G8B8A8_UNORM, OpenVulkano::DataFormat::Format::R8G8B8A8_UNORM },
|
||||||
|
{ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, OpenVulkano::DataFormat::Format::R8G8B8A8_SRGB },
|
||||||
|
{ DXGI_FORMAT_R8G8B8A8_UINT, OpenVulkano::DataFormat::Format::R8G8B8A8_UINT },
|
||||||
|
{ DXGI_FORMAT_R8G8B8A8_SNORM, OpenVulkano::DataFormat::Format::R8G8B8A8_SNORM },
|
||||||
|
{ DXGI_FORMAT_R8G8B8A8_SINT, OpenVulkano::DataFormat::Format::R8G8B8A8_SINT },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_R16G16_FLOAT, OpenVulkano::DataFormat::Format::R16G16_SFLOAT },
|
||||||
|
{ DXGI_FORMAT_R16G16_UNORM, OpenVulkano::DataFormat::Format::R16G16_UNORM },
|
||||||
|
{ DXGI_FORMAT_R16G16_UINT, OpenVulkano::DataFormat::Format::R16G16_UINT },
|
||||||
|
{ DXGI_FORMAT_R16G16_SNORM, OpenVulkano::DataFormat::Format::R16G16_SNORM },
|
||||||
|
{ DXGI_FORMAT_R16G16_SINT, OpenVulkano::DataFormat::Format::R16G16_SINT },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_D32_FLOAT, OpenVulkano::DataFormat::Format::D32_SFLOAT },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_R32_FLOAT, OpenVulkano::DataFormat::Format::R32_SFLOAT },
|
||||||
|
{ DXGI_FORMAT_R32_UINT, OpenVulkano::DataFormat::Format::R32_UINT },
|
||||||
|
{ DXGI_FORMAT_R32_SINT, OpenVulkano::DataFormat::Format::R32_SINT },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_D24_UNORM_S8_UINT, OpenVulkano::DataFormat::Format::D24_UNORM_S8_UINT },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_R8G8_UNORM, OpenVulkano::DataFormat::Format::R8G8_UNORM },
|
||||||
|
{ DXGI_FORMAT_R8G8_UINT, OpenVulkano::DataFormat::Format::R8G8_UINT },
|
||||||
|
{ DXGI_FORMAT_R8G8_SNORM, OpenVulkano::DataFormat::Format::R8G8_SNORM },
|
||||||
|
{ DXGI_FORMAT_R8G8_SINT, OpenVulkano::DataFormat::Format::R8G8_SINT },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_D16_UNORM, OpenVulkano::DataFormat::Format::D16_UNORM },
|
||||||
|
{ DXGI_FORMAT_R16_FLOAT, OpenVulkano::DataFormat::Format::R16_SFLOAT },
|
||||||
|
{ DXGI_FORMAT_R16_UNORM, OpenVulkano::DataFormat::Format::R16_UNORM },
|
||||||
|
{ DXGI_FORMAT_R16_UINT, OpenVulkano::DataFormat::Format::R16_UINT },
|
||||||
|
{ DXGI_FORMAT_R16_SNORM, OpenVulkano::DataFormat::Format::R16_SNORM },
|
||||||
|
{ DXGI_FORMAT_R16_SINT, OpenVulkano::DataFormat::Format::R16_SINT },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_R8_UNORM, OpenVulkano::DataFormat::Format::R8_UNORM },
|
||||||
|
{ DXGI_FORMAT_R8_UINT, OpenVulkano::DataFormat::Format::R8_UINT },
|
||||||
|
{ DXGI_FORMAT_R8_SNORM, OpenVulkano::DataFormat::Format::R8_SNORM },
|
||||||
|
{ DXGI_FORMAT_R8_SINT, OpenVulkano::DataFormat::Format::R8_SINT },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_BC1_UNORM, OpenVulkano::DataFormat::Format::BC1_RGBA_UNORM_BLOCK },
|
||||||
|
{ DXGI_FORMAT_BC1_UNORM_SRGB, OpenVulkano::DataFormat::Format::BC1_RGBA_SRGB_BLOCK },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_BC2_UNORM, OpenVulkano::DataFormat::Format::BC2_UNORM_BLOCK },
|
||||||
|
{ DXGI_FORMAT_BC2_UNORM_SRGB, OpenVulkano::DataFormat::Format::BC2_SRGB_BLOCK },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_BC3_UNORM, OpenVulkano::DataFormat::Format::BC3_UNORM_BLOCK },
|
||||||
|
{ DXGI_FORMAT_BC3_UNORM_SRGB, OpenVulkano::DataFormat::Format::BC3_SRGB_BLOCK },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_BC4_UNORM, OpenVulkano::DataFormat::Format::BC4_UNORM_BLOCK },
|
||||||
|
{ DXGI_FORMAT_BC4_SNORM, OpenVulkano::DataFormat::Format::BC4_SNORM_BLOCK },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_BC5_UNORM, OpenVulkano::DataFormat::Format::BC5_UNORM_BLOCK },
|
||||||
|
{ DXGI_FORMAT_BC5_SNORM, OpenVulkano::DataFormat::Format::BC5_SNORM_BLOCK },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_B5G6R5_UNORM, OpenVulkano::DataFormat::Format::B5G6R5_UNORM_PACK16 },
|
||||||
|
{ DXGI_FORMAT_B5G5R5A1_UNORM, OpenVulkano::DataFormat::Format::B5G5R5A1_UNORM_PACK16 },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_B8G8R8A8_UNORM, OpenVulkano::DataFormat::Format::B8G8R8A8_UNORM },
|
||||||
|
{ DXGI_FORMAT_B8G8R8X8_UNORM, OpenVulkano::DataFormat::Format::B8G8R8A8_SNORM },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, OpenVulkano::DataFormat::Format::B8G8R8A8_SRGB },
|
||||||
|
{ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, OpenVulkano::DataFormat::Format::B8G8R8A8_SRGB },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_BC6H_UF16, OpenVulkano::DataFormat::Format::BC6H_UFLOAT_BLOCK },
|
||||||
|
{ DXGI_FORMAT_BC6H_SF16, OpenVulkano::DataFormat::Format::BC6H_SFLOAT_BLOCK },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_BC7_UNORM, OpenVulkano::DataFormat::Format::BC7_UNORM_BLOCK },
|
||||||
|
{ DXGI_FORMAT_BC7_UNORM_SRGB, OpenVulkano::DataFormat::Format::BC7_SRGB_BLOCK },
|
||||||
|
|
||||||
|
{ DXGI_FORMAT_B4G4R4A4_UNORM, OpenVulkano::DataFormat::Format::B4G4R4A4_UNORM_PACK16 },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace OpenVulkano::Image
|
||||||
|
{
|
||||||
|
std::unique_ptr<Image> ImageLoaderDds::loadFromFile(const std::string& filePath)
|
||||||
|
{
|
||||||
|
dds::Image image;
|
||||||
|
if (dds::readFile(filePath, &image) != dds::ReadResult::Success)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to load DDS texture");
|
||||||
|
}
|
||||||
|
return ExtractImage(&image);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Image> ImageLoaderDds::loadFromMemory(const std::vector<uint8_t>& buffer)
|
||||||
|
{
|
||||||
|
dds::Image image;
|
||||||
|
if (dds::readImage(const_cast<uint8_t*>(buffer.data()), buffer.size(), &image) != dds::ReadResult::Success)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to load DDS texture");
|
||||||
|
}
|
||||||
|
return ExtractImage(&image);
|
||||||
|
}
|
||||||
|
|
||||||
|
Math::Vector2i ImageLoaderDds::GetImageDimensions(const std::string& filename)
|
||||||
|
{
|
||||||
|
dds::Image image;
|
||||||
|
if (dds::readFile(filename, &image) != dds::ReadResult::Success)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to load DDS texture");
|
||||||
|
}
|
||||||
|
|
||||||
|
Math::Vector2i result;
|
||||||
|
result.x = image.width;
|
||||||
|
result.y = image.height;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Image> ImageLoaderDds::ExtractImage(dds::Image* ddsImage)
|
||||||
|
{
|
||||||
|
auto image = std::make_unique<Image>();
|
||||||
|
|
||||||
|
image->resolution.x = ddsImage->width;
|
||||||
|
image->resolution.y = ddsImage->height;
|
||||||
|
image->resolution.z = 1;
|
||||||
|
|
||||||
|
if (DXGI_TO_OV_DATAFORMAT.contains(ddsImage->format))
|
||||||
|
{
|
||||||
|
image->dataFormat = DXGI_TO_OV_DATAFORMAT[ddsImage->format];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::runtime_error(fmt::format("Unhandled DDS texture format: {} ({})",
|
||||||
|
magic_enum::enum_name(ddsImage->format),
|
||||||
|
static_cast<int>(ddsImage->format)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ddsImage->mipmaps.size() == 0)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to read an image from a texture with no mipmaps");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto texture = ddsImage->mipmaps[0];
|
||||||
|
image->data = Array<uint8_t>(texture.size_bytes());
|
||||||
|
memcpy(image->data.Data(), texture.data(), texture.size_bytes());
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
openVulkanoCpp/Image/ImageLoaderDds.hpp
Normal file
28
openVulkanoCpp/Image/ImageLoaderDds.hpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
namespace dds
|
||||||
|
{
|
||||||
|
struct Image;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace OpenVulkano::Image
|
||||||
|
{
|
||||||
|
class ImageLoaderDds : public IImageLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::unique_ptr<Image> loadFromFile(const std::string& filePath) override;
|
||||||
|
std::unique_ptr<Image> loadFromMemory(const std::vector<uint8_t>& buffer) override;
|
||||||
|
Math::Vector2i GetImageDimensions(const std::string& filename) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<Image> ExtractImage(dds::Image* ddsImage);
|
||||||
|
};
|
||||||
|
}
|
||||||
121
openVulkanoCpp/Image/ImageLoaderKtx.cpp
Normal file
121
openVulkanoCpp/Image/ImageLoaderKtx.cpp
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* 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 <ktx.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void KtxDestroy(ktxTexture* tex)
|
||||||
|
{
|
||||||
|
ktxTexture_Destroy(tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace OpenVulkano::Image
|
||||||
|
{
|
||||||
|
std::unique_ptr<Image> ImageLoaderKtx::loadFromFile(const std::string& filePath)
|
||||||
|
{
|
||||||
|
ktxTexture* tmp = nullptr;
|
||||||
|
KTX_error_code error_code =
|
||||||
|
ktxTexture_CreateFromNamedFile(filePath.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &tmp);
|
||||||
|
std::unique_ptr<ktxTexture, decltype(&KtxDestroy)> texture(tmp, &KtxDestroy);
|
||||||
|
|
||||||
|
if (error_code != KTX_SUCCESS)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to load KTX texture: " + std::string(ktxErrorString(error_code)));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = ExtractImage(texture.get());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Image> ImageLoaderKtx::loadFromMemory(const std::vector<uint8_t>& buffer)
|
||||||
|
{
|
||||||
|
ktxTexture* tmp = nullptr;
|
||||||
|
KTX_error_code error_code =
|
||||||
|
ktxTexture_CreateFromMemory(buffer.data(), buffer.size(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &tmp);
|
||||||
|
std::unique_ptr<ktxTexture, decltype(&KtxDestroy)> texture(tmp, &KtxDestroy);
|
||||||
|
|
||||||
|
if (error_code != KTX_SUCCESS)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to load KTX texture from memory: " + std::string(ktxErrorString(error_code)));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = ExtractImage(texture.get());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Math::Vector2i ImageLoaderKtx::GetImageDimensions(const std::string& filename)
|
||||||
|
{
|
||||||
|
ktxTexture* tmp = nullptr;
|
||||||
|
KTX_error_code result =
|
||||||
|
ktxTexture_CreateFromNamedFile(filename.c_str(), KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, &tmp);
|
||||||
|
std::unique_ptr<ktxTexture, decltype(&KtxDestroy)> texture(tmp, &KtxDestroy);
|
||||||
|
|
||||||
|
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);
|
||||||
|
return dimensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Image> ImageLoaderKtx::ExtractImage(ktxTexture* texture)
|
||||||
|
{
|
||||||
|
if (!texture->pData)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("No image data found in KTX texture.");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto width = static_cast<int>(texture->baseWidth);
|
||||||
|
auto height = static_cast<int>(texture->baseHeight);
|
||||||
|
|
||||||
|
auto image = std::make_unique<Image>();
|
||||||
|
image->resolution.x = width;
|
||||||
|
image->resolution.y = height;
|
||||||
|
image->resolution.z = 1;
|
||||||
|
|
||||||
|
if (texture->classId == ktxTexture1_c)
|
||||||
|
{
|
||||||
|
ktxTexture1* tx = reinterpret_cast<ktxTexture1*>(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<ktxTexture2*>(texture);
|
||||||
|
image->dataFormat = reinterpret_cast<DataFormat::Format&>(tx->vkFormat);
|
||||||
|
}
|
||||||
|
else [[unlikely]]
|
||||||
|
{
|
||||||
|
throw std::runtime_error("ktxTexture has unhandled classId!");
|
||||||
|
}
|
||||||
|
|
||||||
|
image->data = Array<uint8_t>(texture->dataSize);
|
||||||
|
memcpy(image->data.Data(), texture->pData, image->data.Size());
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
}
|
||||||
25
openVulkanoCpp/Image/ImageLoaderKtx.hpp
Normal file
25
openVulkanoCpp/Image/ImageLoaderKtx.hpp
Normal file
@@ -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<Image> loadFromFile(const std::string& filePath) override;
|
||||||
|
std::unique_ptr<Image> loadFromMemory(const std::vector<uint8_t>& buffer) override;
|
||||||
|
Math::Vector2i GetImageDimensions(const std::string& filename) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<Image> ExtractImage(ktxTexture* texture);
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user