DDS library + ImageLoaderDds

This commit is contained in:
Vladyslav Baranovskyi
2024-12-08 22:57:45 +02:00
parent f6ee1de342
commit 412f9bb68c
5 changed files with 340 additions and 2 deletions

View File

@@ -42,4 +42,5 @@ if(ENABLE_TEST)
endif() endif()
add_subdirectory(tinyusdz) add_subdirectory(tinyusdz)
add_subdirectory(ktx-software) add_subdirectory(ktx-software)
add_subdirectory(dds_image)

15
3rdParty/dds_image/CMakeLists.txt vendored Normal file
View 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)

View File

@@ -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 ktx) 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)

View File

@@ -0,0 +1,294 @@
/*
* 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>
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 (ddsImage->mipmaps.size() == 0)
{
throw std::runtime_error("Failed to read an image from a texture with no mipmaps");
}
dds::span texture = ddsImage->mipmaps[0];
image->data = Array<uint8_t>(texture.size_bytes());
memcpy(image->data.Data(), texture.data(), texture.size_bytes());
image->dataFormat = DataFormat::Format::UNDEFINED;
switch (ddsImage->format)
{
case DXGI_FORMAT_R32G32B32A32_FLOAT:
image->dataFormat = DataFormat::Format::R32G32B32A32_SFLOAT;
break;
case DXGI_FORMAT_R32G32B32A32_UINT:
image->dataFormat = DataFormat::Format::R32G32B32A32_UINT;
break;
case DXGI_FORMAT_R32G32B32A32_SINT:
image->dataFormat = DataFormat::Format::R32G32B32A32_SINT;
break;
case DXGI_FORMAT_R32G32B32_FLOAT:
image->dataFormat = DataFormat::Format::R32G32B32_SFLOAT;
break;
case DXGI_FORMAT_R32G32B32_UINT:
image->dataFormat = DataFormat::Format::R32G32B32_UINT;
break;
case DXGI_FORMAT_R32G32B32_SINT:
image->dataFormat = DataFormat::Format::R32G32B32_SINT;
break;
case DXGI_FORMAT_R16G16B16A16_FLOAT:
image->dataFormat = DataFormat::Format::R16G16B16A16_SFLOAT;
break;
case DXGI_FORMAT_R16G16B16A16_UNORM:
image->dataFormat = DataFormat::Format::R16G16B16A16_UNORM;
break;
case DXGI_FORMAT_R16G16B16A16_UINT:
image->dataFormat = DataFormat::Format::R16G16B16A16_UINT;
break;
case DXGI_FORMAT_R16G16B16A16_SNORM:
image->dataFormat = DataFormat::Format::R16G16B16A16_SNORM;
break;
case DXGI_FORMAT_R16G16B16A16_SINT:
image->dataFormat = DataFormat::Format::R16G16B16A16_SINT;
break;
case DXGI_FORMAT_R32G32_FLOAT:
image->dataFormat = DataFormat::Format::R32G32_SFLOAT;
break;
case DXGI_FORMAT_R32G32_UINT:
image->dataFormat = DataFormat::Format::R32G32_UINT;
break;
case DXGI_FORMAT_R32G32_SINT:
image->dataFormat = DataFormat::Format::R32G32_SINT;
break;
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
image->dataFormat = DataFormat::Format::D32_SFLOAT_S8_UINT;
break;
case DXGI_FORMAT_R8G8B8A8_UNORM:
image->dataFormat = DataFormat::Format::R8G8B8A8_UNORM;
break;
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
image->dataFormat = DataFormat::Format::R8G8B8A8_SRGB;
break;
case DXGI_FORMAT_R8G8B8A8_UINT:
image->dataFormat = DataFormat::Format::R8G8B8A8_UINT;
break;
case DXGI_FORMAT_R8G8B8A8_SNORM:
image->dataFormat = DataFormat::Format::R8G8B8A8_SNORM;
break;
case DXGI_FORMAT_R8G8B8A8_SINT:
image->dataFormat = DataFormat::Format::R8G8B8A8_SINT;
break;
case DXGI_FORMAT_R16G16_FLOAT:
image->dataFormat = DataFormat::Format::R16G16_SFLOAT;
break;
case DXGI_FORMAT_R16G16_UNORM:
image->dataFormat = DataFormat::Format::R16G16_UNORM;
break;
case DXGI_FORMAT_R16G16_UINT:
image->dataFormat = DataFormat::Format::R16G16_UINT;
break;
case DXGI_FORMAT_R16G16_SNORM:
image->dataFormat = DataFormat::Format::R16G16_SNORM;
break;
case DXGI_FORMAT_R16G16_SINT:
image->dataFormat = DataFormat::Format::R16G16_SINT;
break;
case DXGI_FORMAT_D32_FLOAT:
image->dataFormat = DataFormat::Format::D32_SFLOAT;
break;
case DXGI_FORMAT_R32_FLOAT:
image->dataFormat = DataFormat::Format::R32_SFLOAT;
break;
case DXGI_FORMAT_R32_UINT:
image->dataFormat = DataFormat::Format::R32_UINT;
break;
case DXGI_FORMAT_R32_SINT:
image->dataFormat = DataFormat::Format::R32_SINT;
break;
case DXGI_FORMAT_D24_UNORM_S8_UINT:
image->dataFormat = DataFormat::Format::D24_UNORM_S8_UINT;
break;
case DXGI_FORMAT_R8G8_UNORM:
image->dataFormat = DataFormat::Format::R8G8_UNORM;
break;
case DXGI_FORMAT_R8G8_UINT:
image->dataFormat = DataFormat::Format::R8G8_UINT;
break;
case DXGI_FORMAT_R8G8_SNORM:
image->dataFormat = DataFormat::Format::R8G8_SNORM;
break;
case DXGI_FORMAT_R8G8_SINT:
image->dataFormat = DataFormat::Format::R8G8_SINT;
break;
case DXGI_FORMAT_D16_UNORM:
image->dataFormat = DataFormat::Format::D16_UNORM;
break;
case DXGI_FORMAT_R16_FLOAT:
image->dataFormat = DataFormat::Format::R16_SFLOAT;
break;
case DXGI_FORMAT_R16_UNORM:
image->dataFormat = DataFormat::Format::R16_UNORM;
break;
case DXGI_FORMAT_R16_UINT:
image->dataFormat = DataFormat::Format::R16_UINT;
break;
case DXGI_FORMAT_R16_SNORM:
image->dataFormat = DataFormat::Format::R16_SNORM;
break;
case DXGI_FORMAT_R16_SINT:
image->dataFormat = DataFormat::Format::R16_SINT;
break;
case DXGI_FORMAT_R8_UNORM:
image->dataFormat = DataFormat::Format::R8_UNORM;
break;
case DXGI_FORMAT_R8_UINT:
image->dataFormat = DataFormat::Format::R8_UINT;
break;
case DXGI_FORMAT_R8_SNORM:
image->dataFormat = DataFormat::Format::R8_SNORM;
break;
case DXGI_FORMAT_R8_SINT:
image->dataFormat = DataFormat::Format::R8_SINT;
break;
case DXGI_FORMAT_BC1_UNORM:
image->dataFormat = DataFormat::Format::BC1_RGBA_UNORM_BLOCK;
break;
case DXGI_FORMAT_BC1_UNORM_SRGB:
image->dataFormat = DataFormat::Format::BC1_RGBA_SRGB_BLOCK;
break;
case DXGI_FORMAT_BC2_UNORM:
image->dataFormat = DataFormat::Format::BC2_UNORM_BLOCK;
break;
case DXGI_FORMAT_BC2_UNORM_SRGB:
image->dataFormat = DataFormat::Format::BC2_SRGB_BLOCK;
break;
case DXGI_FORMAT_BC3_UNORM:
image->dataFormat = DataFormat::Format::BC3_UNORM_BLOCK;
break;
case DXGI_FORMAT_BC3_UNORM_SRGB:
image->dataFormat = DataFormat::Format::BC3_SRGB_BLOCK;
break;
case DXGI_FORMAT_BC4_UNORM:
image->dataFormat = DataFormat::Format::BC4_UNORM_BLOCK;
break;
case DXGI_FORMAT_BC4_SNORM:
image->dataFormat = DataFormat::Format::BC4_SNORM_BLOCK;
break;
case DXGI_FORMAT_BC5_UNORM:
image->dataFormat = DataFormat::Format::BC5_UNORM_BLOCK;
break;
case DXGI_FORMAT_BC5_SNORM:
image->dataFormat = DataFormat::Format::BC5_SNORM_BLOCK;
break;
case DXGI_FORMAT_B5G6R5_UNORM:
image->dataFormat = DataFormat::Format::B5G6R5_UNORM_PACK16;
break;
case DXGI_FORMAT_B5G5R5A1_UNORM:
image->dataFormat = DataFormat::Format::B5G5R5A1_UNORM_PACK16;
break;
case DXGI_FORMAT_B8G8R8A8_UNORM:
image->dataFormat = DataFormat::Format::B8G8R8A8_UNORM;
break;
case DXGI_FORMAT_B8G8R8X8_UNORM:
image->dataFormat = DataFormat::Format::B8G8R8A8_SNORM;
break;
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
image->dataFormat = DataFormat::Format::B8G8R8A8_SRGB;
break;
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
image->dataFormat = DataFormat::Format::B8G8R8A8_SRGB;
break;
case DXGI_FORMAT_BC6H_UF16:
image->dataFormat = DataFormat::Format::BC6H_UFLOAT_BLOCK;
break;
case DXGI_FORMAT_BC6H_SF16:
image->dataFormat = DataFormat::Format::BC6H_SFLOAT_BLOCK;
break;
case DXGI_FORMAT_BC7_UNORM:
image->dataFormat = DataFormat::Format::BC7_UNORM_BLOCK;
break;
case DXGI_FORMAT_BC7_UNORM_SRGB:
image->dataFormat = DataFormat::Format::BC7_SRGB_BLOCK;
break;
case DXGI_FORMAT_B4G4R4A4_UNORM:
image->dataFormat = DataFormat::Format::B4G4R4A4_UNORM_PACK16;
break;
default:
throw std::runtime_error("Unhandled DDS texture format: "
+ std::to_string(*reinterpret_cast<int*>(&ddsImage->format)));
}
return image;
}
}

View 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);
};
}