2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-01-07 17:31:49 +00:00

chore: update image namespacing

This commit is contained in:
Jan Laupetin
2026-01-03 13:58:46 +01:00
parent b2e6f7a4ea
commit a5d1d09fa9
47 changed files with 1940 additions and 1832 deletions

View File

@@ -38,11 +38,13 @@ function ImageConverter:project()
self:include(includes) self:include(includes)
Utils:include(includes) Utils:include(includes)
Common:include(includes)
ObjImage:include(includes) ObjImage:include(includes)
Raw:use() Raw:use()
links:linkto(Utils) links:linkto(Utils)
links:linkto(Common)
links:linkto(ObjImage) links:linkto(ObjImage)
links:linkall() links:linkall()
end end

View File

@@ -1,5 +1,6 @@
#include "ImageConverter.h" #include "ImageConverter.h"
#include "Game/IGame.h"
#include "Image/DdsLoader.h" #include "Image/DdsLoader.h"
#include "Image/DdsWriter.h" #include "Image/DdsWriter.h"
#include "Image/IwiLoader.h" #include "Image/IwiLoader.h"
@@ -17,10 +18,12 @@
#include <format> #include <format>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <optional>
namespace fs = std::filesystem; namespace fs = std::filesystem;
using namespace image;
namespace image_converter namespace
{ {
constexpr auto EXTENSION_IWI = ".iwi"; constexpr auto EXTENSION_IWI = ".iwi";
constexpr auto EXTENSION_DDS = ".dds"; constexpr auto EXTENSION_DDS = ".dds";
@@ -29,7 +32,7 @@ namespace image_converter
{ {
public: public:
ImageConverterImpl() ImageConverterImpl()
: m_game_to_convert_to(image_converter::Game::UNKNOWN) : m_game_to_convert_to(std::nullopt)
{ {
} }
@@ -76,7 +79,7 @@ namespace image_converter
return false; return false;
} }
const auto texture = iwi::LoadIwi(file); const auto texture = image::LoadIwi(file);
if (!texture) if (!texture)
return false; return false;
@@ -103,7 +106,7 @@ namespace image_converter
return false; return false;
} }
const auto texture = dds::LoadDds(file); const auto texture = image::LoadDds(file);
if (!texture) if (!texture)
return false; return false;
@@ -129,23 +132,23 @@ namespace image_converter
if (m_iwi_writer) if (m_iwi_writer)
return true; return true;
if (m_game_to_convert_to == Game::UNKNOWN && !ShowGameTui()) if (!m_game_to_convert_to && !ShowGameTui())
return false; return false;
switch (m_game_to_convert_to) switch (*m_game_to_convert_to)
{ {
case Game::IW3: case GameId::IW3:
m_iwi_writer = std::make_unique<iwi6::IwiWriter>(); m_iwi_writer = std::make_unique<image::iwi6::IwiWriter>();
break; break;
case Game::IW4: case GameId::IW4:
case Game::IW5: case GameId::IW5:
m_iwi_writer = std::make_unique<iwi8::IwiWriter>(); m_iwi_writer = std::make_unique<image::iwi8::IwiWriter>();
break; break;
case Game::T5: case GameId::T5:
m_iwi_writer = std::make_unique<iwi13::IwiWriter>(); m_iwi_writer = std::make_unique<image::iwi13::IwiWriter>();
break; break;
case Game::T6: case GameId::T6:
m_iwi_writer = std::make_unique<iwi27::IwiWriter>(); m_iwi_writer = std::make_unique<image::iwi27::IwiWriter>();
break; break;
default: default:
assert(false); assert(false);
@@ -170,19 +173,19 @@ namespace image_converter
switch (num) switch (num)
{ {
case 1: case 1:
m_game_to_convert_to = Game::IW3; m_game_to_convert_to = GameId::IW3;
break; break;
case 2: case 2:
m_game_to_convert_to = Game::IW4; m_game_to_convert_to = GameId::IW4;
break; break;
case 3: case 3:
m_game_to_convert_to = Game::IW5; m_game_to_convert_to = GameId::IW5;
break; break;
case 4: case 4:
m_game_to_convert_to = Game::T5; m_game_to_convert_to = GameId::T5;
break; break;
case 5: case 5:
m_game_to_convert_to = Game::T6; m_game_to_convert_to = GameId::T6;
break; break;
default: default:
con::error("Invalid input"); con::error("Invalid input");
@@ -193,13 +196,13 @@ namespace image_converter
} }
ImageConverterArgs m_args; ImageConverterArgs m_args;
image_converter::Game m_game_to_convert_to; std::optional<GameId> m_game_to_convert_to;
DdsWriter m_dds_writer; DdsWriter m_dds_writer;
std::unique_ptr<IImageWriter> m_iwi_writer; std::unique_ptr<ImageWriter> m_iwi_writer;
}; };
} // namespace image_converter } // namespace
std::unique_ptr<ImageConverter> ImageConverter::Create() std::unique_ptr<ImageConverter> ImageConverter::Create()
{ {
return std::make_unique<image_converter::ImageConverterImpl>(); return std::make_unique<ImageConverterImpl>();
} }

View File

@@ -86,7 +86,7 @@ const CommandLineOption* const COMMAND_LINE_OPTIONS[]{
}; };
ImageConverterArgs::ImageConverterArgs() ImageConverterArgs::ImageConverterArgs()
: m_game_to_convert_to(image_converter::Game::UNKNOWN), : m_game_to_convert_to(std::nullopt),
m_argument_parser(COMMAND_LINE_OPTIONS, std::extent_v<decltype(COMMAND_LINE_OPTIONS)>) m_argument_parser(COMMAND_LINE_OPTIONS, std::extent_v<decltype(COMMAND_LINE_OPTIONS)>)
{ {
} }

View File

@@ -1,24 +1,13 @@
#pragma once #pragma once
#include "Game/IGame.h"
#include "Utils/Arguments/ArgumentParser.h" #include "Utils/Arguments/ArgumentParser.h"
#include <cstdint> #include <cstdint>
#include <optional>
#include <string> #include <string>
#include <vector> #include <vector>
namespace image_converter
{
enum class Game : std::uint8_t
{
UNKNOWN,
IW3,
IW4,
IW5,
T5,
T6
};
} // namespace image_converter
class ImageConverterArgs class ImageConverterArgs
{ {
public: public:
@@ -26,7 +15,7 @@ public:
bool ParseArgs(int argc, const char** argv, bool& shouldContinue); bool ParseArgs(int argc, const char** argv, bool& shouldContinue);
std::vector<std::string> m_files_to_convert; std::vector<std::string> m_files_to_convert;
image_converter::Game m_game_to_convert_to; std::optional<GameId> m_game_to_convert_to;
private: private:
/** /**

View File

@@ -9,7 +9,9 @@
#include <iostream> #include <iostream>
#include <memory> #include <memory>
namespace dds using namespace image;
namespace
{ {
class DdsLoaderInternal class DdsLoaderInternal
{ {
@@ -193,7 +195,7 @@ namespace dds
return ReadPixelFormatUnsigned(pf); return ReadPixelFormatUnsigned(pf);
} }
_NODISCARD bool ReadHeader() [[nodiscard]] bool ReadHeader()
{ {
DDS_HEADER header{}; DDS_HEADER header{};
m_stream.read(reinterpret_cast<char*>(&header), sizeof(header)); m_stream.read(reinterpret_cast<char*>(&header), sizeof(header));
@@ -277,10 +279,13 @@ namespace dds
unsigned m_depth; unsigned m_depth;
const ImageFormat* m_format; const ImageFormat* m_format;
}; };
} // namespace
namespace image
{
std::unique_ptr<Texture> LoadDds(std::istream& stream) std::unique_ptr<Texture> LoadDds(std::istream& stream)
{ {
DdsLoaderInternal internal(stream); DdsLoaderInternal internal(stream);
return internal.LoadDds(); return internal.LoadDds();
} }
} // namespace dds } // namespace image

View File

@@ -5,7 +5,7 @@
#include <istream> #include <istream>
#include <memory> #include <memory>
namespace dds namespace image
{ {
std::unique_ptr<Texture> LoadDds(std::istream& stream); std::unique_ptr<Texture> LoadDds(std::istream& stream);
} }

View File

@@ -2,110 +2,114 @@
#include <cstdint> #include <cstdint>
constexpr uint32_t MakeFourCc(const char ch0, const char ch1, const char ch2, const char ch3) namespace image
{ {
return static_cast<uint32_t>(ch0) | static_cast<uint32_t>(ch1) << 8 | static_cast<uint32_t>(ch2) << 16 | static_cast<uint32_t>(ch3) << 24; constexpr uint32_t MakeFourCc(const char ch0, const char ch1, const char ch2, const char ch3)
} {
return static_cast<uint32_t>(ch0) | static_cast<uint32_t>(ch1) << 8 | static_cast<uint32_t>(ch2) << 16 | static_cast<uint32_t>(ch3) << 24;
}
enum DDP_FLAGS enum DDP_FLAGS
{ {
DDPF_ALPHAPIXELS = 0x1, DDPF_ALPHAPIXELS = 0x1,
DDPF_ALPHA = 0x2, DDPF_ALPHA = 0x2,
DDPF_FOURCC = 0x4, DDPF_FOURCC = 0x4,
DDPF_RGB = 0x40, DDPF_RGB = 0x40,
DDPF_YUV = 0x200, DDPF_YUV = 0x200,
DDPF_LUMINANCE = 0x20000 DDPF_LUMINANCE = 0x20000
}; };
enum DDS_HEADER_FLAGS enum DDS_HEADER_FLAGS
{ {
DDSD_CAPS = 0x1, DDSD_CAPS = 0x1,
DDSD_HEIGHT = 0x2, DDSD_HEIGHT = 0x2,
DDSD_WIDTH = 0x4, DDSD_WIDTH = 0x4,
DDSD_PITCH = 0x8, DDSD_PITCH = 0x8,
DDSD_PIXELFORMAT = 0x1000, DDSD_PIXELFORMAT = 0x1000,
DDSD_MIPMAPCOUNT = 0x20000, DDSD_MIPMAPCOUNT = 0x20000,
DDSD_LINEARSIZE = 0x80000, DDSD_LINEARSIZE = 0x80000,
DDSD_DEPTH = 0x800000, DDSD_DEPTH = 0x800000,
}; };
enum DDS_HEADER_CAPS enum DDS_HEADER_CAPS
{ {
DDSCAPS_COMPLEX = 0x8, DDSCAPS_COMPLEX = 0x8,
DDSCAPS_TEXTURE = 0x1000, DDSCAPS_TEXTURE = 0x1000,
DDSCAPS_MIPMAP = 0x400000, DDSCAPS_MIPMAP = 0x400000,
}; };
enum DDS_HEADER_CAPS2 enum DDS_HEADER_CAPS2
{ {
DDSCAPS2_CUBEMAP = 0x200, DDSCAPS2_CUBEMAP = 0x200,
DDSCAPS2_CUBEMAP_POSITIVEX = 0x400, DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800, DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000, DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000, DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000, DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000, DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
DDSCAPS2_VOLUME = 0x200000, DDSCAPS2_VOLUME = 0x200000,
}; };
struct DDS_PIXELFORMAT struct DDS_PIXELFORMAT
{ {
uint32_t dwSize; uint32_t dwSize;
uint32_t dwFlags; uint32_t dwFlags;
uint32_t dwFourCC; uint32_t dwFourCC;
uint32_t dwRGBBitCount; uint32_t dwRGBBitCount;
uint32_t dwRBitMask; uint32_t dwRBitMask;
uint32_t dwGBitMask; uint32_t dwGBitMask;
uint32_t dwBBitMask; uint32_t dwBBitMask;
uint32_t dwABitMask; uint32_t dwABitMask;
}; };
struct DDS_HEADER struct DDS_HEADER
{ {
uint32_t dwSize; uint32_t dwSize;
uint32_t dwFlags; uint32_t dwFlags;
uint32_t dwHeight; uint32_t dwHeight;
uint32_t dwWidth; uint32_t dwWidth;
uint32_t dwPitchOrLinearSize; uint32_t dwPitchOrLinearSize;
uint32_t dwDepth; uint32_t dwDepth;
uint32_t dwMipMapCount; uint32_t dwMipMapCount;
uint32_t dwReserved1[11]; uint32_t dwReserved1[11];
DDS_PIXELFORMAT ddspf; DDS_PIXELFORMAT ddspf;
uint32_t dwCaps; uint32_t dwCaps;
uint32_t dwCaps2; uint32_t dwCaps2;
uint32_t dwCaps3; uint32_t dwCaps3;
uint32_t dwCaps4; uint32_t dwCaps4;
uint32_t dwReserved2; uint32_t dwReserved2;
}; };
enum D3D10_RESOURCE_DIMENSION enum D3D10_RESOURCE_DIMENSION
{ {
D3D10_RESOURCE_DIMENSION_UNKNOWN, D3D10_RESOURCE_DIMENSION_UNKNOWN,
D3D10_RESOURCE_DIMENSION_BUFFER, D3D10_RESOURCE_DIMENSION_BUFFER,
D3D10_RESOURCE_DIMENSION_TEXTURE1D, D3D10_RESOURCE_DIMENSION_TEXTURE1D,
D3D10_RESOURCE_DIMENSION_TEXTURE2D, D3D10_RESOURCE_DIMENSION_TEXTURE2D,
D3D10_RESOURCE_DIMENSION_TEXTURE3D D3D10_RESOURCE_DIMENSION_TEXTURE3D
}; };
enum DDS_HEADER_DXT10_MISC enum DDS_HEADER_DXT10_MISC
{ {
DDS_RESOURCE_MISC_TEXTURECUBE = 0x4 DDS_RESOURCE_MISC_TEXTURECUBE = 0x4
}; };
enum DDS_HEADER_DXT10_MISC2 enum DDS_HEADER_DXT10_MISC2
{ {
DDS_ALPHA_MODE_UNKNOWN = 0x0, DDS_ALPHA_MODE_UNKNOWN = 0x0,
DDS_ALPHA_MODE_STRAIGHT = 0x1, DDS_ALPHA_MODE_STRAIGHT = 0x1,
DDS_ALPHA_MODE_PREMULTIPLIED = 0x2, DDS_ALPHA_MODE_PREMULTIPLIED = 0x2,
DDS_ALPHA_MODE_OPAQUE = 0x3, DDS_ALPHA_MODE_OPAQUE = 0x3,
DDS_ALPHA_MODE_CUSTOM = 0x4, DDS_ALPHA_MODE_CUSTOM = 0x4,
}; };
struct DDS_HEADER_DXT10 struct DDS_HEADER_DXT10
{ {
oat::DXGI_FORMAT dxgiFormat; oat::DXGI_FORMAT dxgiFormat;
D3D10_RESOURCE_DIMENSION resourceDimension; D3D10_RESOURCE_DIMENSION resourceDimension;
uint32_t miscFlag; uint32_t miscFlag;
uint32_t arraySize; uint32_t arraySize;
uint32_t miscFlags2; uint32_t miscFlags2;
}; };
} // namespace image

View File

@@ -7,234 +7,242 @@
#include <map> #include <map>
#include <memory> #include <memory>
const std::map<ImageFormatId, ImageFormatId> DDS_CONVERSION_TABLE{ using namespace image;
{ImageFormatId::R8_G8_B8, ImageFormatId::B8_G8_R8_X8},
};
class DdsWriterInternal namespace
{ {
public: const std::map<ImageFormatId, ImageFormatId> DDS_CONVERSION_TABLE{
static bool SupportsImageFormat(const ImageFormat* imageFormat) {ImageFormatId::R8_G8_B8, ImageFormatId::B8_G8_R8_X8},
};
class DdsWriterInternal
{ {
return true; public:
} static bool SupportsImageFormat(const ImageFormat* imageFormat)
static std::string GetFileExtension()
{
return ".dds";
}
DdsWriterInternal(std::ostream& stream, const Texture* texture)
: m_stream(stream),
m_texture(texture),
m_use_dx10_extension(false)
{
}
void DumpImage()
{
ConvertTextureIfNecessary();
DDS_HEADER header{};
PopulateDdsHeader(header);
constexpr auto magic = MakeFourCc('D', 'D', 'S', ' ');
m_stream.write(reinterpret_cast<const char*>(&magic), sizeof(magic));
m_stream.write(reinterpret_cast<const char*>(&header), sizeof(header));
if (m_use_dx10_extension)
{ {
DDS_HEADER_DXT10 dxt10{}; return true;
PopulateDxt10Header(dxt10);
m_stream.write(reinterpret_cast<const char*>(&dxt10), sizeof(dxt10));
} }
const auto mipCount = m_texture->HasMipMaps() ? m_texture->GetMipMapCount() : 1; static std::string GetFileExtension()
for (auto mipLevel = 0; mipLevel < mipCount; mipLevel++)
{ {
const auto* buffer = m_texture->GetBufferForMipLevel(mipLevel); return ".dds";
const auto mipLevelSize = m_texture->GetSizeOfMipLevel(mipLevel) * m_texture->GetFaceCount();
m_stream.write(reinterpret_cast<const char*>(buffer), static_cast<std::streamsize>(mipLevelSize));
}
}
static constexpr unsigned Mask1(const unsigned length)
{
if (length >= sizeof(unsigned) * 8)
return UINT32_MAX;
return UINT32_MAX >> (sizeof(unsigned) * 8 - length);
}
void PopulatePixelFormatBlockCompressed(DDS_PIXELFORMAT& pf, const ImageFormatBlockCompressed* format)
{
pf.dwSize = sizeof(DDS_PIXELFORMAT);
pf.dwFlags = DDPF_FOURCC;
pf.dwRGBBitCount = 0;
pf.dwRBitMask = 0;
pf.dwGBitMask = 0;
pf.dwBBitMask = 0;
pf.dwABitMask = 0;
// Use standard pixel format for DXT1-5 for maximum compatibility and only otherwise use DX10 extension
switch (format->GetDxgiFormat())
{
case oat::DXGI_FORMAT_BC1_UNORM:
pf.dwFourCC = MakeFourCc('D', 'X', 'T', '1');
break;
case oat::DXGI_FORMAT_BC2_UNORM:
pf.dwFourCC = MakeFourCc('D', 'X', 'T', '3');
break;
case oat::DXGI_FORMAT_BC3_UNORM:
pf.dwFourCC = MakeFourCc('D', 'X', 'T', '5');
break;
default:
m_use_dx10_extension = true;
pf.dwFourCC = MakeFourCc('D', 'X', '1', '0');
break;
}
}
static void PopulatePixelFormatUnsigned(DDS_PIXELFORMAT& pf, const ImageFormatUnsigned* format)
{
pf.dwSize = sizeof(DDS_PIXELFORMAT);
pf.dwFourCC = 0;
pf.dwRGBBitCount = format->m_bits_per_pixel;
pf.dwRBitMask = format->HasR() ? Mask1(format->m_r_size) << format->m_r_offset : 0;
pf.dwGBitMask = format->HasG() ? Mask1(format->m_g_size) << format->m_g_offset : 0;
pf.dwBBitMask = format->HasB() ? Mask1(format->m_b_size) << format->m_b_offset : 0;
pf.dwABitMask = format->HasA() ? Mask1(format->m_a_size) << format->m_a_offset : 0;
pf.dwFlags = 0;
if (format->HasA())
pf.dwFlags |= DDPF_ALPHAPIXELS;
if (format->HasR() && !format->HasG() && !format->HasB())
pf.dwFlags |= DDPF_LUMINANCE;
else
pf.dwFlags |= DDPF_RGB;
}
void PopulatePixelFormat(DDS_PIXELFORMAT& pf)
{
const auto* format = m_texture->GetFormat();
switch (format->GetType())
{
case ImageFormatType::BLOCK_COMPRESSED:
PopulatePixelFormatBlockCompressed(pf, dynamic_cast<const ImageFormatBlockCompressed*>(format));
break;
case ImageFormatType::UNSIGNED:
PopulatePixelFormatUnsigned(pf, dynamic_cast<const ImageFormatUnsigned*>(format));
break;
default:
assert(false);
break;
}
}
void PopulateDdsHeader(DDS_HEADER& header)
{
header.dwSize = sizeof(header);
header.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
if (m_texture->HasMipMaps())
header.dwFlags |= DDSD_MIPMAPCOUNT;
if (m_texture->GetFormat()->GetType() == ImageFormatType::BLOCK_COMPRESSED)
header.dwFlags |= DDSD_LINEARSIZE;
else
header.dwFlags |= DDSD_PITCH;
if (m_texture->GetDepth() > 1)
header.dwFlags |= DDSD_DEPTH;
header.dwHeight = m_texture->GetHeight();
header.dwWidth = m_texture->GetWidth();
header.dwDepth = m_texture->GetDepth();
header.dwPitchOrLinearSize = static_cast<uint32_t>(m_texture->GetFormat()->GetPitch(0, m_texture->GetWidth()));
header.dwMipMapCount = m_texture->HasMipMaps() ? m_texture->GetMipMapCount() : 1;
PopulatePixelFormat(header.ddspf);
header.dwCaps = DDSCAPS_TEXTURE;
if (m_texture->HasMipMaps())
header.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
if (m_texture->GetTextureType() == TextureType::T_CUBE)
header.dwCaps |= DDSCAPS_COMPLEX;
header.dwCaps2 = 0;
if (m_texture->GetTextureType() == TextureType::T_CUBE)
{
header.dwCaps2 |= DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_NEGATIVEX | DDSCAPS2_CUBEMAP_POSITIVEY
| DDSCAPS2_CUBEMAP_NEGATIVEY | DDSCAPS2_CUBEMAP_POSITIVEZ | DDSCAPS2_CUBEMAP_NEGATIVEZ;
} }
header.dwCaps3 = 0; DdsWriterInternal(std::ostream& stream, const Texture* texture)
header.dwCaps4 = 0; : m_stream(stream),
header.dwReserved2 = 0; m_texture(texture),
} m_use_dx10_extension(false)
void PopulateDxt10Header(DDS_HEADER_DXT10& header) const
{
header.dxgiFormat = m_texture->GetFormat()->GetDxgiFormat();
header.miscFlag = 0;
header.miscFlags2 = 0;
switch (m_texture->GetTextureType())
{ {
case TextureType::T_2D:
header.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
header.arraySize = 1;
break;
case TextureType::T_CUBE:
header.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
header.arraySize = 6;
header.miscFlag |= DDS_RESOURCE_MISC_TEXTURECUBE;
break;
case TextureType::T_3D:
header.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D;
header.arraySize = 1;
break;
} }
}
void ConvertTextureIfNecessary() void DumpImage()
{
const auto entry = DDS_CONVERSION_TABLE.find(m_texture->GetFormat()->GetId());
if (entry != DDS_CONVERSION_TABLE.end())
{ {
TextureConverter converter(m_texture, ImageFormat::ALL_FORMATS[static_cast<unsigned>(entry->second)]); ConvertTextureIfNecessary();
m_converted_texture = converter.Convert();
m_texture = m_converted_texture.get(); DDS_HEADER header{};
PopulateDdsHeader(header);
constexpr auto magic = MakeFourCc('D', 'D', 'S', ' ');
m_stream.write(reinterpret_cast<const char*>(&magic), sizeof(magic));
m_stream.write(reinterpret_cast<const char*>(&header), sizeof(header));
if (m_use_dx10_extension)
{
DDS_HEADER_DXT10 dxt10{};
PopulateDxt10Header(dxt10);
m_stream.write(reinterpret_cast<const char*>(&dxt10), sizeof(dxt10));
}
const auto mipCount = m_texture->HasMipMaps() ? m_texture->GetMipMapCount() : 1;
for (auto mipLevel = 0; mipLevel < mipCount; mipLevel++)
{
const auto* buffer = m_texture->GetBufferForMipLevel(mipLevel);
const auto mipLevelSize = m_texture->GetSizeOfMipLevel(mipLevel) * m_texture->GetFaceCount();
m_stream.write(reinterpret_cast<const char*>(buffer), static_cast<std::streamsize>(mipLevelSize));
}
} }
}
std::ostream& m_stream; static constexpr unsigned Mask1(const unsigned length)
const Texture* m_texture; {
std::unique_ptr<Texture> m_converted_texture; if (length >= sizeof(unsigned) * 8)
bool m_use_dx10_extension; return UINT32_MAX;
};
DdsWriter::~DdsWriter() = default; return UINT32_MAX >> (sizeof(unsigned) * 8 - length);
}
bool DdsWriter::SupportsImageFormat(const ImageFormat* imageFormat) void PopulatePixelFormatBlockCompressed(DDS_PIXELFORMAT& pf, const ImageFormatBlockCompressed* format)
{
pf.dwSize = sizeof(DDS_PIXELFORMAT);
pf.dwFlags = DDPF_FOURCC;
pf.dwRGBBitCount = 0;
pf.dwRBitMask = 0;
pf.dwGBitMask = 0;
pf.dwBBitMask = 0;
pf.dwABitMask = 0;
// Use standard pixel format for DXT1-5 for maximum compatibility and only otherwise use DX10 extension
switch (format->GetDxgiFormat())
{
case oat::DXGI_FORMAT_BC1_UNORM:
pf.dwFourCC = MakeFourCc('D', 'X', 'T', '1');
break;
case oat::DXGI_FORMAT_BC2_UNORM:
pf.dwFourCC = MakeFourCc('D', 'X', 'T', '3');
break;
case oat::DXGI_FORMAT_BC3_UNORM:
pf.dwFourCC = MakeFourCc('D', 'X', 'T', '5');
break;
default:
m_use_dx10_extension = true;
pf.dwFourCC = MakeFourCc('D', 'X', '1', '0');
break;
}
}
static void PopulatePixelFormatUnsigned(DDS_PIXELFORMAT& pf, const ImageFormatUnsigned* format)
{
pf.dwSize = sizeof(DDS_PIXELFORMAT);
pf.dwFourCC = 0;
pf.dwRGBBitCount = format->m_bits_per_pixel;
pf.dwRBitMask = format->HasR() ? Mask1(format->m_r_size) << format->m_r_offset : 0;
pf.dwGBitMask = format->HasG() ? Mask1(format->m_g_size) << format->m_g_offset : 0;
pf.dwBBitMask = format->HasB() ? Mask1(format->m_b_size) << format->m_b_offset : 0;
pf.dwABitMask = format->HasA() ? Mask1(format->m_a_size) << format->m_a_offset : 0;
pf.dwFlags = 0;
if (format->HasA())
pf.dwFlags |= DDPF_ALPHAPIXELS;
if (format->HasR() && !format->HasG() && !format->HasB())
pf.dwFlags |= DDPF_LUMINANCE;
else
pf.dwFlags |= DDPF_RGB;
}
void PopulatePixelFormat(DDS_PIXELFORMAT& pf)
{
const auto* format = m_texture->GetFormat();
switch (format->GetType())
{
case ImageFormatType::BLOCK_COMPRESSED:
PopulatePixelFormatBlockCompressed(pf, dynamic_cast<const ImageFormatBlockCompressed*>(format));
break;
case ImageFormatType::UNSIGNED:
PopulatePixelFormatUnsigned(pf, dynamic_cast<const ImageFormatUnsigned*>(format));
break;
default:
assert(false);
break;
}
}
void PopulateDdsHeader(DDS_HEADER& header)
{
header.dwSize = sizeof(header);
header.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
if (m_texture->HasMipMaps())
header.dwFlags |= DDSD_MIPMAPCOUNT;
if (m_texture->GetFormat()->GetType() == ImageFormatType::BLOCK_COMPRESSED)
header.dwFlags |= DDSD_LINEARSIZE;
else
header.dwFlags |= DDSD_PITCH;
if (m_texture->GetDepth() > 1)
header.dwFlags |= DDSD_DEPTH;
header.dwHeight = m_texture->GetHeight();
header.dwWidth = m_texture->GetWidth();
header.dwDepth = m_texture->GetDepth();
header.dwPitchOrLinearSize = static_cast<uint32_t>(m_texture->GetFormat()->GetPitch(0, m_texture->GetWidth()));
header.dwMipMapCount = m_texture->HasMipMaps() ? m_texture->GetMipMapCount() : 1;
PopulatePixelFormat(header.ddspf);
header.dwCaps = DDSCAPS_TEXTURE;
if (m_texture->HasMipMaps())
header.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
if (m_texture->GetTextureType() == TextureType::T_CUBE)
header.dwCaps |= DDSCAPS_COMPLEX;
header.dwCaps2 = 0;
if (m_texture->GetTextureType() == TextureType::T_CUBE)
{
header.dwCaps2 |= DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_NEGATIVEX | DDSCAPS2_CUBEMAP_POSITIVEY
| DDSCAPS2_CUBEMAP_NEGATIVEY | DDSCAPS2_CUBEMAP_POSITIVEZ | DDSCAPS2_CUBEMAP_NEGATIVEZ;
}
header.dwCaps3 = 0;
header.dwCaps4 = 0;
header.dwReserved2 = 0;
}
void PopulateDxt10Header(DDS_HEADER_DXT10& header) const
{
header.dxgiFormat = m_texture->GetFormat()->GetDxgiFormat();
header.miscFlag = 0;
header.miscFlags2 = 0;
switch (m_texture->GetTextureType())
{
case TextureType::T_2D:
header.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
header.arraySize = 1;
break;
case TextureType::T_CUBE:
header.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
header.arraySize = 6;
header.miscFlag |= DDS_RESOURCE_MISC_TEXTURECUBE;
break;
case TextureType::T_3D:
header.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D;
header.arraySize = 1;
break;
}
}
void ConvertTextureIfNecessary()
{
const auto entry = DDS_CONVERSION_TABLE.find(m_texture->GetFormat()->GetId());
if (entry != DDS_CONVERSION_TABLE.end())
{
TextureConverter converter(m_texture, ImageFormat::ALL_FORMATS[static_cast<unsigned>(entry->second)]);
m_converted_texture = converter.Convert();
m_texture = m_converted_texture.get();
}
}
std::ostream& m_stream;
const Texture* m_texture;
std::unique_ptr<Texture> m_converted_texture;
bool m_use_dx10_extension;
};
} // namespace
namespace image
{ {
return DdsWriterInternal::SupportsImageFormat(imageFormat); DdsWriter::~DdsWriter() = default;
}
std::string DdsWriter::GetFileExtension() bool DdsWriter::SupportsImageFormat(const ImageFormat* imageFormat)
{ {
return DdsWriterInternal::GetFileExtension(); return DdsWriterInternal::SupportsImageFormat(imageFormat);
} }
void DdsWriter::DumpImage(std::ostream& stream, const Texture* texture) std::string DdsWriter::GetFileExtension()
{ {
DdsWriterInternal internal(stream, texture); return DdsWriterInternal::GetFileExtension();
internal.DumpImage(); }
}
void DdsWriter::DumpImage(std::ostream& stream, const Texture* texture)
{
DdsWriterInternal internal(stream, texture);
internal.DumpImage();
}
} // namespace image

View File

@@ -1,12 +1,16 @@
#pragma once #pragma once
#include "IImageWriter.h"
class DdsWriter final : public IImageWriter #include "ImageWriter.h"
namespace image
{ {
public: class DdsWriter final : public ImageWriter
~DdsWriter() override; {
public:
~DdsWriter() override;
bool SupportsImageFormat(const ImageFormat* imageFormat) override; bool SupportsImageFormat(const ImageFormat* imageFormat) override;
std::string GetFileExtension() override; std::string GetFileExtension() override;
void DumpImage(std::ostream& stream, const Texture* texture) override; void DumpImage(std::ostream& stream, const Texture* texture) override;
}; };
} // namespace image

View File

@@ -2,103 +2,106 @@
#include <cstring> #include <cstring>
Dx12TextureLoader::Dx12TextureLoader() namespace image
: m_format(oat::DXGI_FORMAT_UNKNOWN),
m_type(TextureType::T_2D),
m_has_mip_maps(false),
m_width(1u),
m_height(1u),
m_depth(1u)
{ {
} Dx12TextureLoader::Dx12TextureLoader()
: m_format(oat::DXGI_FORMAT_UNKNOWN),
const ImageFormat* Dx12TextureLoader::GetFormatForDx12Format() const m_type(TextureType::T_2D),
{ m_has_mip_maps(false),
for (const auto* i : ImageFormat::ALL_FORMATS) m_width(1u),
m_height(1u),
m_depth(1u)
{ {
if (i->GetDxgiFormat() == m_format)
return i;
} }
return nullptr; const ImageFormat* Dx12TextureLoader::GetFormatForDx12Format() const
}
Dx12TextureLoader& Dx12TextureLoader::Format(const oat::DXGI_FORMAT format)
{
m_format = format;
return *this;
}
Dx12TextureLoader& Dx12TextureLoader::Type(const TextureType textureType)
{
m_type = textureType;
return *this;
}
Dx12TextureLoader& Dx12TextureLoader::HasMipMaps(const bool hasMipMaps)
{
m_has_mip_maps = hasMipMaps;
return *this;
}
Dx12TextureLoader& Dx12TextureLoader::Width(const unsigned width)
{
m_width = width;
return *this;
}
Dx12TextureLoader& Dx12TextureLoader::Height(const unsigned height)
{
m_height = height;
return *this;
}
Dx12TextureLoader& Dx12TextureLoader::Depth(const unsigned depth)
{
m_depth = depth;
return *this;
}
std::unique_ptr<Texture> Dx12TextureLoader::LoadTexture(const void* data)
{
const auto* format = GetFormatForDx12Format();
if (format == nullptr)
return nullptr;
std::unique_ptr<Texture> texture;
switch (m_type)
{ {
case TextureType::T_2D: for (const auto* i : ImageFormat::ALL_FORMATS)
texture = std::make_unique<Texture2D>(format, m_width, m_height, m_has_mip_maps);
break;
case TextureType::T_3D:
texture = std::make_unique<Texture3D>(format, m_width, m_height, m_depth, m_has_mip_maps);
break;
case TextureType::T_CUBE:
texture = std::make_unique<TextureCube>(format, m_width, m_width, m_has_mip_maps);
break;
default:
return nullptr;
}
texture->Allocate();
const auto mipMapCount = m_has_mip_maps ? texture->GetMipMapCount() : 1;
const auto faceCount = m_type == TextureType::T_CUBE ? 6 : 1;
const void* currentDataOffset = data;
for (auto currentMipLevel = 0; currentMipLevel < mipMapCount; currentMipLevel++)
{
for (auto currentFace = 0; currentFace < faceCount; currentFace++)
{ {
const auto mipSize = texture->GetSizeOfMipLevel(currentMipLevel); if (i->GetDxgiFormat() == m_format)
memcpy(texture->GetBufferForMipLevel(currentMipLevel, currentFace), currentDataOffset, mipSize); return i;
currentDataOffset = reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(currentDataOffset) + mipSize);
} }
return nullptr;
} }
return texture; Dx12TextureLoader& Dx12TextureLoader::Format(const oat::DXGI_FORMAT format)
} {
m_format = format;
return *this;
}
Dx12TextureLoader& Dx12TextureLoader::Type(const TextureType textureType)
{
m_type = textureType;
return *this;
}
Dx12TextureLoader& Dx12TextureLoader::HasMipMaps(const bool hasMipMaps)
{
m_has_mip_maps = hasMipMaps;
return *this;
}
Dx12TextureLoader& Dx12TextureLoader::Width(const unsigned width)
{
m_width = width;
return *this;
}
Dx12TextureLoader& Dx12TextureLoader::Height(const unsigned height)
{
m_height = height;
return *this;
}
Dx12TextureLoader& Dx12TextureLoader::Depth(const unsigned depth)
{
m_depth = depth;
return *this;
}
std::unique_ptr<Texture> Dx12TextureLoader::LoadTexture(const void* data)
{
const auto* format = GetFormatForDx12Format();
if (format == nullptr)
return nullptr;
std::unique_ptr<Texture> texture;
switch (m_type)
{
case TextureType::T_2D:
texture = std::make_unique<Texture2D>(format, m_width, m_height, m_has_mip_maps);
break;
case TextureType::T_3D:
texture = std::make_unique<Texture3D>(format, m_width, m_height, m_depth, m_has_mip_maps);
break;
case TextureType::T_CUBE:
texture = std::make_unique<TextureCube>(format, m_width, m_width, m_has_mip_maps);
break;
default:
return nullptr;
}
texture->Allocate();
const auto mipMapCount = m_has_mip_maps ? texture->GetMipMapCount() : 1;
const auto faceCount = m_type == TextureType::T_CUBE ? 6 : 1;
const void* currentDataOffset = data;
for (auto currentMipLevel = 0; currentMipLevel < mipMapCount; currentMipLevel++)
{
for (auto currentFace = 0; currentFace < faceCount; currentFace++)
{
const auto mipSize = texture->GetSizeOfMipLevel(currentMipLevel);
memcpy(texture->GetBufferForMipLevel(currentMipLevel, currentFace), currentDataOffset, mipSize);
currentDataOffset = reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(currentDataOffset) + mipSize);
}
}
return texture;
}
} // namespace image

View File

@@ -6,29 +6,32 @@
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
class Dx12TextureLoader namespace image
{ {
public: class Dx12TextureLoader
Dx12TextureLoader(); {
public:
Dx12TextureLoader();
Dx12TextureLoader& Format(oat::DXGI_FORMAT format); Dx12TextureLoader& Format(oat::DXGI_FORMAT format);
Dx12TextureLoader& Type(TextureType textureType); Dx12TextureLoader& Type(TextureType textureType);
Dx12TextureLoader& HasMipMaps(bool hasMipMaps); Dx12TextureLoader& HasMipMaps(bool hasMipMaps);
Dx12TextureLoader& Width(unsigned width); Dx12TextureLoader& Width(unsigned width);
Dx12TextureLoader& Height(unsigned height); Dx12TextureLoader& Height(unsigned height);
Dx12TextureLoader& Depth(unsigned depth); Dx12TextureLoader& Depth(unsigned depth);
std::unique_ptr<Texture> LoadTexture(const void* data); std::unique_ptr<Texture> LoadTexture(const void* data);
private: private:
[[nodiscard]] const ImageFormat* GetFormatForDx12Format() const; [[nodiscard]] const ImageFormat* GetFormatForDx12Format() const;
static std::unordered_map<ImageFormatId, ImageFormatId> m_conversion_table; static std::unordered_map<ImageFormatId, ImageFormatId> m_conversion_table;
oat::DXGI_FORMAT m_format; oat::DXGI_FORMAT m_format;
TextureType m_type; TextureType m_type;
bool m_has_mip_maps; bool m_has_mip_maps;
unsigned m_width; unsigned m_width;
unsigned m_height; unsigned m_height;
unsigned m_depth; unsigned m_depth;
}; };
} // namespace image

View File

@@ -2,103 +2,106 @@
#include <cstring> #include <cstring>
Dx9TextureLoader::Dx9TextureLoader() namespace image
: m_format(oat::D3DFMT_UNKNOWN),
m_type(TextureType::T_2D),
m_has_mip_maps(false),
m_width(1u),
m_height(1u),
m_depth(1u)
{ {
} Dx9TextureLoader::Dx9TextureLoader()
: m_format(oat::D3DFMT_UNKNOWN),
const ImageFormat* Dx9TextureLoader::GetFormatForDx9Format() const m_type(TextureType::T_2D),
{ m_has_mip_maps(false),
for (const auto* i : ImageFormat::ALL_FORMATS) m_width(1u),
m_height(1u),
m_depth(1u)
{ {
if (i->GetD3DFormat() == m_format)
return i;
} }
return nullptr; const ImageFormat* Dx9TextureLoader::GetFormatForDx9Format() const
}
Dx9TextureLoader& Dx9TextureLoader::Format(const oat::D3DFORMAT format)
{
m_format = format;
return *this;
}
Dx9TextureLoader& Dx9TextureLoader::Type(const TextureType textureType)
{
m_type = textureType;
return *this;
}
Dx9TextureLoader& Dx9TextureLoader::HasMipMaps(const bool hasMipMaps)
{
m_has_mip_maps = hasMipMaps;
return *this;
}
Dx9TextureLoader& Dx9TextureLoader::Width(const unsigned width)
{
m_width = width;
return *this;
}
Dx9TextureLoader& Dx9TextureLoader::Height(const unsigned height)
{
m_height = height;
return *this;
}
Dx9TextureLoader& Dx9TextureLoader::Depth(const unsigned depth)
{
m_depth = depth;
return *this;
}
std::unique_ptr<Texture> Dx9TextureLoader::LoadTexture(const void* data)
{
const auto* format = GetFormatForDx9Format();
if (format == nullptr)
return nullptr;
std::unique_ptr<Texture> texture;
switch (m_type)
{ {
case TextureType::T_2D: for (const auto* i : ImageFormat::ALL_FORMATS)
texture = std::make_unique<Texture2D>(format, m_width, m_height, m_has_mip_maps);
break;
case TextureType::T_3D:
texture = std::make_unique<Texture3D>(format, m_width, m_height, m_depth, m_has_mip_maps);
break;
case TextureType::T_CUBE:
texture = std::make_unique<TextureCube>(format, m_width, m_width, m_has_mip_maps);
break;
default:
return nullptr;
}
texture->Allocate();
const auto mipMapCount = m_has_mip_maps ? texture->GetMipMapCount() : 1;
const auto faceCount = m_type == TextureType::T_CUBE ? 6 : 1;
const void* currentDataOffset = data;
for (auto currentMipLevel = 0; currentMipLevel < mipMapCount; currentMipLevel++)
{
for (auto currentFace = 0; currentFace < faceCount; currentFace++)
{ {
const auto mipSize = texture->GetSizeOfMipLevel(currentMipLevel); if (i->GetD3DFormat() == m_format)
memcpy(texture->GetBufferForMipLevel(currentMipLevel, currentFace), currentDataOffset, mipSize); return i;
currentDataOffset = reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(currentDataOffset) + mipSize);
} }
return nullptr;
} }
return texture; Dx9TextureLoader& Dx9TextureLoader::Format(const oat::D3DFORMAT format)
} {
m_format = format;
return *this;
}
Dx9TextureLoader& Dx9TextureLoader::Type(const TextureType textureType)
{
m_type = textureType;
return *this;
}
Dx9TextureLoader& Dx9TextureLoader::HasMipMaps(const bool hasMipMaps)
{
m_has_mip_maps = hasMipMaps;
return *this;
}
Dx9TextureLoader& Dx9TextureLoader::Width(const unsigned width)
{
m_width = width;
return *this;
}
Dx9TextureLoader& Dx9TextureLoader::Height(const unsigned height)
{
m_height = height;
return *this;
}
Dx9TextureLoader& Dx9TextureLoader::Depth(const unsigned depth)
{
m_depth = depth;
return *this;
}
std::unique_ptr<Texture> Dx9TextureLoader::LoadTexture(const void* data)
{
const auto* format = GetFormatForDx9Format();
if (format == nullptr)
return nullptr;
std::unique_ptr<Texture> texture;
switch (m_type)
{
case TextureType::T_2D:
texture = std::make_unique<Texture2D>(format, m_width, m_height, m_has_mip_maps);
break;
case TextureType::T_3D:
texture = std::make_unique<Texture3D>(format, m_width, m_height, m_depth, m_has_mip_maps);
break;
case TextureType::T_CUBE:
texture = std::make_unique<TextureCube>(format, m_width, m_width, m_has_mip_maps);
break;
default:
return nullptr;
}
texture->Allocate();
const auto mipMapCount = m_has_mip_maps ? texture->GetMipMapCount() : 1;
const auto faceCount = m_type == TextureType::T_CUBE ? 6 : 1;
const void* currentDataOffset = data;
for (auto currentMipLevel = 0; currentMipLevel < mipMapCount; currentMipLevel++)
{
for (auto currentFace = 0; currentFace < faceCount; currentFace++)
{
const auto mipSize = texture->GetSizeOfMipLevel(currentMipLevel);
memcpy(texture->GetBufferForMipLevel(currentMipLevel, currentFace), currentDataOffset, mipSize);
currentDataOffset = reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(currentDataOffset) + mipSize);
}
}
return texture;
}
} // namespace image

View File

@@ -5,27 +5,30 @@
#include <memory> #include <memory>
class Dx9TextureLoader namespace image
{ {
public: class Dx9TextureLoader
Dx9TextureLoader(); {
public:
Dx9TextureLoader();
Dx9TextureLoader& Format(oat::D3DFORMAT format); Dx9TextureLoader& Format(oat::D3DFORMAT format);
Dx9TextureLoader& Type(TextureType textureType); Dx9TextureLoader& Type(TextureType textureType);
Dx9TextureLoader& HasMipMaps(bool hasMipMaps); Dx9TextureLoader& HasMipMaps(bool hasMipMaps);
Dx9TextureLoader& Width(unsigned width); Dx9TextureLoader& Width(unsigned width);
Dx9TextureLoader& Height(unsigned height); Dx9TextureLoader& Height(unsigned height);
Dx9TextureLoader& Depth(unsigned depth); Dx9TextureLoader& Depth(unsigned depth);
std::unique_ptr<Texture> LoadTexture(const void* data); std::unique_ptr<Texture> LoadTexture(const void* data);
private: private:
[[nodiscard]] const ImageFormat* GetFormatForDx9Format() const; [[nodiscard]] const ImageFormat* GetFormatForDx9Format() const;
oat::D3DFORMAT m_format; oat::D3DFORMAT m_format;
TextureType m_type; TextureType m_type;
bool m_has_mip_maps; bool m_has_mip_maps;
unsigned m_width; unsigned m_width;
unsigned m_height; unsigned m_height;
unsigned m_depth; unsigned m_depth;
}; };
} // namespace image

View File

@@ -1,21 +0,0 @@
#pragma once
#include "Image/Texture.h"
#include <ostream>
#include <string>
class IImageWriter
{
public:
IImageWriter() = default;
virtual ~IImageWriter() = default;
IImageWriter(const IImageWriter& other) = default;
IImageWriter(IImageWriter&& other) noexcept = default;
IImageWriter& operator=(const IImageWriter& other) = default;
IImageWriter& operator=(IImageWriter&& other) noexcept = default;
virtual bool SupportsImageFormat(const ImageFormat* imageFormat) = 0;
virtual std::string GetFileExtension() = 0;
virtual void DumpImage(std::ostream& stream, const Texture* texture) = 0;
};

View File

@@ -1,175 +1,178 @@
#include "ImageFormat.h" #include "ImageFormat.h"
ImageFormat::ImageFormat(const ImageFormatId id, const oat::D3DFORMAT d3dFormat, const oat::DXGI_FORMAT dxgiFormat) namespace image
: m_id(id),
m_d3d_format(d3dFormat),
m_dxgi_format(dxgiFormat)
{ {
} ImageFormat::ImageFormat(const ImageFormatId id, const oat::D3DFORMAT d3dFormat, const oat::DXGI_FORMAT dxgiFormat)
: m_id(id),
m_d3d_format(d3dFormat),
m_dxgi_format(dxgiFormat)
{
}
ImageFormatId ImageFormat::GetId() const ImageFormatId ImageFormat::GetId() const
{ {
return m_id; return m_id;
} }
oat::D3DFORMAT ImageFormat::GetD3DFormat() const oat::D3DFORMAT ImageFormat::GetD3DFormat() const
{ {
return m_d3d_format; return m_d3d_format;
} }
oat::DXGI_FORMAT ImageFormat::GetDxgiFormat() const oat::DXGI_FORMAT ImageFormat::GetDxgiFormat() const
{ {
return m_dxgi_format; return m_dxgi_format;
} }
ImageFormatUnsigned::ImageFormatUnsigned(const ImageFormatId id, ImageFormatUnsigned::ImageFormatUnsigned(const ImageFormatId id,
const oat::D3DFORMAT d3dFormat, const oat::D3DFORMAT d3dFormat,
const oat::DXGI_FORMAT dxgiFormat, const oat::DXGI_FORMAT dxgiFormat,
const unsigned bitsPerPixel, const unsigned bitsPerPixel,
const unsigned rOffset, const unsigned rOffset,
const unsigned rSize, const unsigned rSize,
const unsigned gOffset, const unsigned gOffset,
const unsigned gSize, const unsigned gSize,
const unsigned bOffset, const unsigned bOffset,
const unsigned bSize, const unsigned bSize,
const unsigned aOffset, const unsigned aOffset,
const unsigned aSize) const unsigned aSize)
: ImageFormat(id, d3dFormat, dxgiFormat), : ImageFormat(id, d3dFormat, dxgiFormat),
m_bits_per_pixel(bitsPerPixel), m_bits_per_pixel(bitsPerPixel),
m_r_offset(rOffset), m_r_offset(rOffset),
m_r_size(rSize), m_r_size(rSize),
m_g_offset(gOffset), m_g_offset(gOffset),
m_g_size(gSize), m_g_size(gSize),
m_b_offset(bOffset), m_b_offset(bOffset),
m_b_size(bSize), m_b_size(bSize),
m_a_offset(aOffset), m_a_offset(aOffset),
m_a_size(aSize) m_a_size(aSize)
{ {
} }
ImageFormatType ImageFormatUnsigned::GetType() const ImageFormatType ImageFormatUnsigned::GetType() const
{ {
return ImageFormatType::UNSIGNED; return ImageFormatType::UNSIGNED;
} }
size_t ImageFormatUnsigned::GetPitch(const unsigned mipLevel, const unsigned width) const size_t ImageFormatUnsigned::GetPitch(const unsigned mipLevel, const unsigned width) const
{ {
unsigned mipWidth = width >> mipLevel; unsigned mipWidth = width >> mipLevel;
if (mipWidth == 0) if (mipWidth == 0)
mipWidth = 1; mipWidth = 1;
return mipWidth * m_bits_per_pixel / 8; return mipWidth * m_bits_per_pixel / 8;
} }
size_t ImageFormatUnsigned::GetSizeOfMipLevel(const unsigned mipLevel, const unsigned width, const unsigned height, const unsigned depth) const size_t ImageFormatUnsigned::GetSizeOfMipLevel(const unsigned mipLevel, const unsigned width, const unsigned height, const unsigned depth) const
{ {
unsigned mipWidth = width >> mipLevel; unsigned mipWidth = width >> mipLevel;
unsigned mipHeight = height >> mipLevel; unsigned mipHeight = height >> mipLevel;
unsigned mipDepth = depth >> mipLevel; unsigned mipDepth = depth >> mipLevel;
if (mipWidth == 0) if (mipWidth == 0)
mipWidth = 1; mipWidth = 1;
if (mipHeight == 0) if (mipHeight == 0)
mipHeight = 1; mipHeight = 1;
if (mipDepth == 0) if (mipDepth == 0)
mipDepth = 1; mipDepth = 1;
return mipWidth * mipHeight * mipDepth * m_bits_per_pixel / 8; return mipWidth * mipHeight * mipDepth * m_bits_per_pixel / 8;
} }
ImageFormatBlockCompressed::ImageFormatBlockCompressed( ImageFormatBlockCompressed::ImageFormatBlockCompressed(
const ImageFormatId id, const oat::D3DFORMAT d3dFormat, const oat::DXGI_FORMAT dxgiFormat, const unsigned blockSize, const unsigned bitsPerBlock) const ImageFormatId id, const oat::D3DFORMAT d3dFormat, const oat::DXGI_FORMAT dxgiFormat, const unsigned blockSize, const unsigned bitsPerBlock)
: ImageFormat(id, d3dFormat, dxgiFormat), : ImageFormat(id, d3dFormat, dxgiFormat),
m_block_size(blockSize), m_block_size(blockSize),
m_bits_per_block(bitsPerBlock) m_bits_per_block(bitsPerBlock)
{ {
} }
ImageFormatType ImageFormatBlockCompressed::GetType() const ImageFormatType ImageFormatBlockCompressed::GetType() const
{ {
return ImageFormatType::BLOCK_COMPRESSED; return ImageFormatType::BLOCK_COMPRESSED;
} }
size_t ImageFormatBlockCompressed::GetPitch(const unsigned mipLevel, const unsigned width) const size_t ImageFormatBlockCompressed::GetPitch(const unsigned mipLevel, const unsigned width) const
{ {
unsigned mipWidth = width >> mipLevel; unsigned mipWidth = width >> mipLevel;
if (mipWidth == 0) if (mipWidth == 0)
mipWidth = 1; mipWidth = 1;
const unsigned blockCount = (mipWidth + m_block_size - 1) / m_block_size; const unsigned blockCount = (mipWidth + m_block_size - 1) / m_block_size;
return blockCount * m_bits_per_block / 8; return blockCount * m_bits_per_block / 8;
} }
size_t ImageFormatBlockCompressed::GetSizeOfMipLevel(const unsigned mipLevel, const unsigned width, const unsigned height, const unsigned depth) const size_t ImageFormatBlockCompressed::GetSizeOfMipLevel(const unsigned mipLevel, const unsigned width, const unsigned height, const unsigned depth) const
{ {
unsigned mipWidth = width >> mipLevel; unsigned mipWidth = width >> mipLevel;
unsigned mipHeight = height >> mipLevel; unsigned mipHeight = height >> mipLevel;
unsigned mipDepth = depth >> mipLevel; unsigned mipDepth = depth >> mipLevel;
if (mipWidth == 0) if (mipWidth == 0)
mipWidth = 1; mipWidth = 1;
if (mipHeight == 0) if (mipHeight == 0)
mipHeight = 1; mipHeight = 1;
if (mipDepth == 0) if (mipDepth == 0)
mipDepth = 1; mipDepth = 1;
const unsigned blockCount = ((mipWidth + m_block_size - 1) / m_block_size) * ((mipHeight + m_block_size - 1) / m_block_size) * mipDepth; const unsigned blockCount = ((mipWidth + m_block_size - 1) / m_block_size) * ((mipHeight + m_block_size - 1) / m_block_size) * mipDepth;
return blockCount * m_bits_per_block / 8; return blockCount * m_bits_per_block / 8;
} }
bool ImageFormatUnsigned::HasR() const bool ImageFormatUnsigned::HasR() const
{ {
return m_r_size > 0; return m_r_size > 0;
} }
bool ImageFormatUnsigned::HasG() const bool ImageFormatUnsigned::HasG() const
{ {
return m_g_size > 0; return m_g_size > 0;
} }
bool ImageFormatUnsigned::HasB() const bool ImageFormatUnsigned::HasB() const
{ {
return m_b_size > 0; return m_b_size > 0;
} }
bool ImageFormatUnsigned::HasA() const bool ImageFormatUnsigned::HasA() const
{ {
return m_a_size > 0; return m_a_size > 0;
} }
const ImageFormatUnsigned ImageFormat::FORMAT_R8_G8_B8(ImageFormatId::R8_G8_B8, oat::D3DFMT_R8G8B8, oat::DXGI_FORMAT_UNKNOWN, 24, 0, 8, 8, 8, 16, 8, 0, 0); const ImageFormatUnsigned ImageFormat::FORMAT_R8_G8_B8(ImageFormatId::R8_G8_B8, oat::D3DFMT_R8G8B8, oat::DXGI_FORMAT_UNKNOWN, 24, 0, 8, 8, 8, 16, 8, 0, 0);
const ImageFormatUnsigned const ImageFormatUnsigned
ImageFormat::FORMAT_B8_G8_R8_X8(ImageFormatId::B8_G8_R8_X8, oat::D3DFMT_X8R8G8B8, oat::DXGI_FORMAT_B8G8R8X8_UNORM, 32, 16, 8, 8, 8, 0, 8, 0, 0); ImageFormat::FORMAT_B8_G8_R8_X8(ImageFormatId::B8_G8_R8_X8, oat::D3DFMT_X8R8G8B8, oat::DXGI_FORMAT_B8G8R8X8_UNORM, 32, 16, 8, 8, 8, 0, 8, 0, 0);
const ImageFormatUnsigned const ImageFormatUnsigned
ImageFormat::FORMAT_R8_G8_B8_A8(ImageFormatId::R8_G8_B8_A8, oat::D3DFMT_A8B8G8R8, oat::DXGI_FORMAT_R8G8B8A8_UNORM, 32, 0, 8, 8, 8, 16, 8, 24, 8); ImageFormat::FORMAT_R8_G8_B8_A8(ImageFormatId::R8_G8_B8_A8, oat::D3DFMT_A8B8G8R8, oat::DXGI_FORMAT_R8G8B8A8_UNORM, 32, 0, 8, 8, 8, 16, 8, 24, 8);
const ImageFormatUnsigned const ImageFormatUnsigned
ImageFormat::FORMAT_B8_G8_R8_A8(ImageFormatId::B8_G8_R8_A8, oat::D3DFMT_A8R8G8B8, oat::DXGI_FORMAT_B8G8R8A8_UNORM, 32, 16, 8, 8, 8, 0, 8, 24, 8); ImageFormat::FORMAT_B8_G8_R8_A8(ImageFormatId::B8_G8_R8_A8, oat::D3DFMT_A8R8G8B8, oat::DXGI_FORMAT_B8G8R8A8_UNORM, 32, 16, 8, 8, 8, 0, 8, 24, 8);
const ImageFormatUnsigned ImageFormat::FORMAT_A8(ImageFormatId::A8, oat::D3DFMT_A8, oat::DXGI_FORMAT_A8_UNORM, 8, 0, 0, 0, 0, 0, 0, 0, 8); const ImageFormatUnsigned ImageFormat::FORMAT_A8(ImageFormatId::A8, oat::D3DFMT_A8, oat::DXGI_FORMAT_A8_UNORM, 8, 0, 0, 0, 0, 0, 0, 0, 8);
const ImageFormatUnsigned ImageFormat::FORMAT_R16_G16_B16_A16_FLOAT( const ImageFormatUnsigned ImageFormat::FORMAT_R16_G16_B16_A16_FLOAT(
ImageFormatId::R16_G16_B16_A16_FLOAT, oat::D3DFMT_A16B16G16R16F, oat::DXGI_FORMAT_R16G16B16A16_FLOAT, 128, 0, 0, 0, 0, 0, 0, 0, 8); ImageFormatId::R16_G16_B16_A16_FLOAT, oat::D3DFMT_A16B16G16R16F, oat::DXGI_FORMAT_R16G16B16A16_FLOAT, 128, 0, 0, 0, 0, 0, 0, 0, 8);
const ImageFormatUnsigned ImageFormat::FORMAT_R8(ImageFormatId::R8, oat::D3DFMT_L8, oat::DXGI_FORMAT_R8_UNORM, 8, 0, 8, 0, 0, 0, 0, 0, 0); const ImageFormatUnsigned ImageFormat::FORMAT_R8(ImageFormatId::R8, oat::D3DFMT_L8, oat::DXGI_FORMAT_R8_UNORM, 8, 0, 8, 0, 0, 0, 0, 0, 0);
const ImageFormatUnsigned ImageFormat::FORMAT_R8_A8(ImageFormatId::R8_A8, oat::D3DFMT_A8L8, oat::DXGI_FORMAT_UNKNOWN, 16, 0, 8, 0, 0, 0, 0, 8, 8); const ImageFormatUnsigned ImageFormat::FORMAT_R8_A8(ImageFormatId::R8_A8, oat::D3DFMT_A8L8, oat::DXGI_FORMAT_UNKNOWN, 16, 0, 8, 0, 0, 0, 0, 8, 8);
const ImageFormatBlockCompressed ImageFormat::FORMAT_BC1(ImageFormatId::BC1, oat::D3DFMT_DXT1, oat::DXGI_FORMAT_BC1_UNORM, 4, 64); const ImageFormatBlockCompressed ImageFormat::FORMAT_BC1(ImageFormatId::BC1, oat::D3DFMT_DXT1, oat::DXGI_FORMAT_BC1_UNORM, 4, 64);
const ImageFormatBlockCompressed ImageFormat::FORMAT_BC2(ImageFormatId::BC2, oat::D3DFMT_DXT3, oat::DXGI_FORMAT_BC2_UNORM, 4, 128); const ImageFormatBlockCompressed ImageFormat::FORMAT_BC2(ImageFormatId::BC2, oat::D3DFMT_DXT3, oat::DXGI_FORMAT_BC2_UNORM, 4, 128);
const ImageFormatBlockCompressed ImageFormat::FORMAT_BC3(ImageFormatId::BC3, oat::D3DFMT_DXT5, oat::DXGI_FORMAT_BC3_UNORM, 4, 128); const ImageFormatBlockCompressed ImageFormat::FORMAT_BC3(ImageFormatId::BC3, oat::D3DFMT_DXT5, oat::DXGI_FORMAT_BC3_UNORM, 4, 128);
const ImageFormatBlockCompressed ImageFormat::FORMAT_BC4(ImageFormatId::BC4, oat::D3DFMT_UNKNOWN, oat::DXGI_FORMAT_BC4_UNORM, 4, 64); const ImageFormatBlockCompressed ImageFormat::FORMAT_BC4(ImageFormatId::BC4, oat::D3DFMT_UNKNOWN, oat::DXGI_FORMAT_BC4_UNORM, 4, 64);
const ImageFormatBlockCompressed ImageFormat::FORMAT_BC5(ImageFormatId::BC5, oat::D3DFMT_UNKNOWN, oat::DXGI_FORMAT_BC5_UNORM, 4, 128); const ImageFormatBlockCompressed ImageFormat::FORMAT_BC5(ImageFormatId::BC5, oat::D3DFMT_UNKNOWN, oat::DXGI_FORMAT_BC5_UNORM, 4, 128);
const ImageFormat* const ImageFormat::ALL_FORMATS[static_cast<unsigned>(ImageFormatId::MAX)]{ const ImageFormat* const ImageFormat::ALL_FORMATS[static_cast<unsigned>(ImageFormatId::MAX)]{
&FORMAT_R8_G8_B8, &FORMAT_R8_G8_B8,
&FORMAT_B8_G8_R8_X8, &FORMAT_B8_G8_R8_X8,
&FORMAT_R8_G8_B8_A8, &FORMAT_R8_G8_B8_A8,
&FORMAT_B8_G8_R8_A8, &FORMAT_B8_G8_R8_A8,
&FORMAT_A8, &FORMAT_A8,
&FORMAT_R16_G16_B16_A16_FLOAT, &FORMAT_R16_G16_B16_A16_FLOAT,
&FORMAT_R8, &FORMAT_R8,
&FORMAT_R8_A8, &FORMAT_R8_A8,
&FORMAT_BC1, &FORMAT_BC1,
&FORMAT_BC2, &FORMAT_BC2,
&FORMAT_BC3, &FORMAT_BC3,
&FORMAT_BC4, &FORMAT_BC4,
&FORMAT_BC5, &FORMAT_BC5,
}; };
} // namespace image

View File

@@ -6,117 +6,120 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
enum class ImageFormatId namespace image
{ {
UNKNOWN = -1, enum class ImageFormatId
R8_G8_B8, {
B8_G8_R8_X8, UNKNOWN = -1,
R8_G8_B8_A8, R8_G8_B8,
B8_G8_R8_A8, B8_G8_R8_X8,
A8, R8_G8_B8_A8,
R16_G16_B16_A16_FLOAT, B8_G8_R8_A8,
R8, A8,
R8_A8, R16_G16_B16_A16_FLOAT,
BC1, R8,
BC2, R8_A8,
BC3, BC1,
BC4, BC2,
BC5, BC3,
BC4,
BC5,
MAX MAX
}; };
enum class ImageFormatType enum class ImageFormatType
{ {
UNKNOWN, UNKNOWN,
UNSIGNED, UNSIGNED,
BLOCK_COMPRESSED BLOCK_COMPRESSED
}; };
class ImageFormatUnsigned; class ImageFormatUnsigned;
class ImageFormatBlockCompressed; class ImageFormatBlockCompressed;
class ImageFormat class ImageFormat
{ {
ImageFormatId m_id; ImageFormatId m_id;
oat::D3DFORMAT m_d3d_format; oat::D3DFORMAT m_d3d_format;
oat::DXGI_FORMAT m_dxgi_format; oat::DXGI_FORMAT m_dxgi_format;
protected: protected:
ImageFormat(ImageFormatId id, oat::D3DFORMAT d3dFormat, oat::DXGI_FORMAT dxgiFormat); ImageFormat(ImageFormatId id, oat::D3DFORMAT d3dFormat, oat::DXGI_FORMAT dxgiFormat);
public: public:
virtual ~ImageFormat() = default; virtual ~ImageFormat() = default;
[[nodiscard]] ImageFormatId GetId() const; [[nodiscard]] ImageFormatId GetId() const;
[[nodiscard]] oat::D3DFORMAT GetD3DFormat() const; [[nodiscard]] oat::D3DFORMAT GetD3DFormat() const;
[[nodiscard]] oat::DXGI_FORMAT GetDxgiFormat() const; [[nodiscard]] oat::DXGI_FORMAT GetDxgiFormat() const;
[[nodiscard]] virtual ImageFormatType GetType() const = 0; [[nodiscard]] virtual ImageFormatType GetType() const = 0;
[[nodiscard]] virtual size_t GetPitch(unsigned mipLevel, unsigned width) const = 0; [[nodiscard]] virtual size_t GetPitch(unsigned mipLevel, unsigned width) const = 0;
[[nodiscard]] virtual size_t GetSizeOfMipLevel(unsigned mipLevel, unsigned width, unsigned height, unsigned depth) const = 0; [[nodiscard]] virtual size_t GetSizeOfMipLevel(unsigned mipLevel, unsigned width, unsigned height, unsigned depth) const = 0;
static const ImageFormatUnsigned FORMAT_R8_G8_B8; static const ImageFormatUnsigned FORMAT_R8_G8_B8;
static const ImageFormatUnsigned FORMAT_B8_G8_R8_X8; static const ImageFormatUnsigned FORMAT_B8_G8_R8_X8;
static const ImageFormatUnsigned FORMAT_R8_G8_B8_A8; static const ImageFormatUnsigned FORMAT_R8_G8_B8_A8;
static const ImageFormatUnsigned FORMAT_B8_G8_R8_A8; static const ImageFormatUnsigned FORMAT_B8_G8_R8_A8;
static const ImageFormatUnsigned FORMAT_A8; static const ImageFormatUnsigned FORMAT_A8;
static const ImageFormatUnsigned FORMAT_R16_G16_B16_A16_FLOAT; // TODO: Float not unsigned static const ImageFormatUnsigned FORMAT_R16_G16_B16_A16_FLOAT; // TODO: Float not unsigned
static const ImageFormatUnsigned FORMAT_R8; static const ImageFormatUnsigned FORMAT_R8;
static const ImageFormatUnsigned FORMAT_R8_A8; static const ImageFormatUnsigned FORMAT_R8_A8;
static const ImageFormatBlockCompressed FORMAT_BC1; static const ImageFormatBlockCompressed FORMAT_BC1;
static const ImageFormatBlockCompressed FORMAT_BC2; static const ImageFormatBlockCompressed FORMAT_BC2;
static const ImageFormatBlockCompressed FORMAT_BC3; static const ImageFormatBlockCompressed FORMAT_BC3;
static const ImageFormatBlockCompressed FORMAT_BC4; static const ImageFormatBlockCompressed FORMAT_BC4;
static const ImageFormatBlockCompressed FORMAT_BC5; static const ImageFormatBlockCompressed FORMAT_BC5;
static const ImageFormat* const ALL_FORMATS[static_cast<unsigned>(ImageFormatId::MAX)]; static const ImageFormat* const ALL_FORMATS[static_cast<unsigned>(ImageFormatId::MAX)];
}; };
class ImageFormatUnsigned final : public ImageFormat class ImageFormatUnsigned final : public ImageFormat
{ {
public: public:
unsigned m_bits_per_pixel; unsigned m_bits_per_pixel;
unsigned m_r_offset; unsigned m_r_offset;
unsigned m_r_size; unsigned m_r_size;
unsigned m_g_offset; unsigned m_g_offset;
unsigned m_g_size; unsigned m_g_size;
unsigned m_b_offset; unsigned m_b_offset;
unsigned m_b_size; unsigned m_b_size;
unsigned m_a_offset; unsigned m_a_offset;
unsigned m_a_size; unsigned m_a_size;
ImageFormatUnsigned(ImageFormatId id, ImageFormatUnsigned(ImageFormatId id,
oat::D3DFORMAT d3dFormat, oat::D3DFORMAT d3dFormat,
oat::DXGI_FORMAT dxgiFormat, oat::DXGI_FORMAT dxgiFormat,
unsigned bitsPerPixel, unsigned bitsPerPixel,
unsigned rOffset, unsigned rOffset,
unsigned rSize, unsigned rSize,
unsigned gOffset, unsigned gOffset,
unsigned gSize, unsigned gSize,
unsigned bOffset, unsigned bOffset,
unsigned bSize, unsigned bSize,
unsigned aOffset, unsigned aOffset,
unsigned aSize); unsigned aSize);
[[nodiscard]] ImageFormatType GetType() const override; [[nodiscard]] ImageFormatType GetType() const override;
[[nodiscard]] size_t GetPitch(unsigned mipLevel, unsigned width) const override; [[nodiscard]] size_t GetPitch(unsigned mipLevel, unsigned width) const override;
[[nodiscard]] size_t GetSizeOfMipLevel(unsigned mipLevel, unsigned width, unsigned height, unsigned depth) const override; [[nodiscard]] size_t GetSizeOfMipLevel(unsigned mipLevel, unsigned width, unsigned height, unsigned depth) const override;
[[nodiscard]] bool HasR() const; [[nodiscard]] bool HasR() const;
[[nodiscard]] bool HasG() const; [[nodiscard]] bool HasG() const;
[[nodiscard]] bool HasB() const; [[nodiscard]] bool HasB() const;
[[nodiscard]] bool HasA() const; [[nodiscard]] bool HasA() const;
}; };
class ImageFormatBlockCompressed final : public ImageFormat class ImageFormatBlockCompressed final : public ImageFormat
{ {
public: public:
unsigned m_block_size; unsigned m_block_size;
unsigned m_bits_per_block; unsigned m_bits_per_block;
ImageFormatBlockCompressed(ImageFormatId id, oat::D3DFORMAT d3dFormat, oat::DXGI_FORMAT dxgiFormat, unsigned blockSize, unsigned bitsPerBlock); ImageFormatBlockCompressed(ImageFormatId id, oat::D3DFORMAT d3dFormat, oat::DXGI_FORMAT dxgiFormat, unsigned blockSize, unsigned bitsPerBlock);
[[nodiscard]] ImageFormatType GetType() const override; [[nodiscard]] ImageFormatType GetType() const override;
[[nodiscard]] size_t GetPitch(unsigned mipLevel, unsigned width) const override; [[nodiscard]] size_t GetPitch(unsigned mipLevel, unsigned width) const override;
[[nodiscard]] size_t GetSizeOfMipLevel(unsigned mipLevel, unsigned width, unsigned height, unsigned depth) const override; [[nodiscard]] size_t GetSizeOfMipLevel(unsigned mipLevel, unsigned width, unsigned height, unsigned depth) const override;
}; };
} // namespace image

View File

@@ -0,0 +1,24 @@
#pragma once
#include "Image/Texture.h"
#include <ostream>
#include <string>
namespace image
{
class ImageWriter
{
public:
ImageWriter() = default;
virtual ~ImageWriter() = default;
ImageWriter(const ImageWriter& other) = default;
ImageWriter(ImageWriter&& other) noexcept = default;
ImageWriter& operator=(const ImageWriter& other) = default;
ImageWriter& operator=(ImageWriter&& other) noexcept = default;
virtual bool SupportsImageFormat(const ImageFormat* imageFormat) = 0;
virtual std::string GetFileExtension() = 0;
virtual void DumpImage(std::ostream& stream, const Texture* texture) = 0;
};
} // namespace image

View File

@@ -8,7 +8,9 @@
#include <iostream> #include <iostream>
#include <type_traits> #include <type_traits>
namespace iwi using namespace image;
namespace
{ {
const ImageFormat* GetFormat6(int8_t format) const ImageFormat* GetFormat6(int8_t format)
{ {
@@ -74,7 +76,7 @@ namespace iwi
texture->Allocate(); texture->Allocate();
auto currentFileSize = sizeof(iwi6::IwiHeader) + sizeof(IwiVersion); auto currentFileSize = sizeof(iwi6::IwiHeader) + sizeof(IwiVersionHeader);
const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1; const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--) for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--)
@@ -188,7 +190,7 @@ namespace iwi
texture->Allocate(); texture->Allocate();
auto currentFileSize = sizeof(iwi8::IwiHeader) + sizeof(IwiVersion); auto currentFileSize = sizeof(iwi8::IwiHeader) + sizeof(IwiVersionHeader);
const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1; const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--) for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--)
@@ -283,7 +285,7 @@ namespace iwi
texture->Allocate(); texture->Allocate();
auto currentFileSize = sizeof(iwi13::IwiHeader) + sizeof(IwiVersion); auto currentFileSize = sizeof(iwi13::IwiHeader) + sizeof(IwiVersionHeader);
const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1; const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--) for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--)
@@ -380,7 +382,7 @@ namespace iwi
texture->Allocate(); texture->Allocate();
auto currentFileSize = sizeof(iwi27::IwiHeader) + sizeof(IwiVersion); auto currentFileSize = sizeof(iwi27::IwiHeader) + sizeof(IwiVersionHeader);
const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1; const auto mipMapCount = hasMipMaps ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--) for (auto currentMipLevel = mipMapCount - 1; currentMipLevel >= 0; currentMipLevel--)
@@ -405,22 +407,25 @@ namespace iwi
return texture; return texture;
} }
} // namespace
namespace image
{
std::unique_ptr<Texture> LoadIwi(std::istream& stream) std::unique_ptr<Texture> LoadIwi(std::istream& stream)
{ {
IwiVersion iwiVersion{}; IwiVersionHeader iwiVersionHeader{};
stream.read(reinterpret_cast<char*>(&iwiVersion), sizeof(iwiVersion)); stream.read(reinterpret_cast<char*>(&iwiVersionHeader), sizeof(iwiVersionHeader));
if (stream.gcount() != sizeof(iwiVersion)) if (stream.gcount() != sizeof(iwiVersionHeader))
return nullptr; return nullptr;
if (iwiVersion.tag[0] != 'I' || iwiVersion.tag[1] != 'W' || iwiVersion.tag[2] != 'i') if (iwiVersionHeader.tag[0] != 'I' || iwiVersionHeader.tag[1] != 'W' || iwiVersionHeader.tag[2] != 'i')
{ {
con::error("Invalid IWI magic"); con::error("Invalid IWI magic");
return nullptr; return nullptr;
} }
switch (iwiVersion.version) switch (iwiVersionHeader.version)
{ {
case 6: case 6:
return LoadIwi6(stream); return LoadIwi6(stream);
@@ -438,7 +443,7 @@ namespace iwi
break; break;
} }
con::error("Unknown IWI version {}", iwiVersion.version); con::error("Unknown IWI version {}", iwiVersionHeader.version);
return nullptr; return nullptr;
} }
} // namespace iwi } // namespace image

View File

@@ -5,7 +5,7 @@
#include <istream> #include <istream>
#include <memory> #include <memory>
namespace iwi namespace image
{ {
std::unique_ptr<Texture> LoadIwi(std::istream& stream); std::unique_ptr<Texture> LoadIwi(std::istream& stream);
}; // namespace iwi }; // namespace image

View File

@@ -2,234 +2,245 @@
#include <cstdint> #include <cstdint>
struct IwiVersion namespace image
{ {
char tag[3]; enum class IwiVersion : std::uint8_t
char version;
};
// IW3
namespace iwi6
{
struct IwiHeader
{ {
int8_t format; // IW3
int8_t flags; IWI_6 = 6,
uint16_t dimensions[3]; // IW4, IW5
uint32_t fileSizeForPicmip[4]; IWI_8 = 8,
// T5
IWI_13 = 13,
// T6
IWI_27 = 27
}; };
enum class IwiFormat struct IwiVersionHeader
{ {
IMG_FORMAT_INVALID = 0x0, char tag[3];
IMG_FORMAT_BITMAP_RGBA = 0x1, char version;
IMG_FORMAT_BITMAP_RGB = 0x2,
IMG_FORMAT_BITMAP_LUMINANCE_ALPHA = 0x3,
IMG_FORMAT_BITMAP_LUMINANCE = 0x4,
IMG_FORMAT_BITMAP_ALPHA = 0x5,
IMG_FORMAT_WAVELET_RGBA = 0x6,
IMG_FORMAT_WAVELET_RGB = 0x7,
IMG_FORMAT_WAVELET_LUMINANCE_ALPHA = 0x8,
IMG_FORMAT_WAVELET_LUMINANCE = 0x9,
IMG_FORMAT_WAVELET_ALPHA = 0xA,
IMG_FORMAT_DXT1 = 0xB,
IMG_FORMAT_DXT3 = 0xC,
IMG_FORMAT_DXT5 = 0xD,
IMG_FORMAT_DXN = 0xE,
IMG_FORMAT_COUNT
}; };
enum IwiFlags namespace iwi6
{ {
IMG_FLAG_NOPICMIP = 1 << 0, struct IwiHeader
IMG_FLAG_NOMIPMAPS = 1 << 1, {
IMG_FLAG_CUBEMAP = 1 << 2, int8_t format;
IMG_FLAG_VOLMAP = 1 << 3, int8_t flags;
IMG_FLAG_STREAMING = 1 << 4, uint16_t dimensions[3];
IMG_FLAG_LEGACY_NORMALS = 1 << 5, uint32_t fileSizeForPicmip[4];
IMG_FLAG_CLAMP_U = 1 << 6, };
IMG_FLAG_CLAMP_V = 1 << 7,
IMG_FLAG_DYNAMIC = 1 << 16,
IMG_FLAG_RENDER_TARGET = 1 << 17,
IMG_FLAG_SYSTEMMEM = 1 << 18
};
} // namespace iwi6
// IW4 enum class IwiFormat
namespace iwi8 {
{ IMG_FORMAT_INVALID = 0x0,
struct IwiHeader IMG_FORMAT_BITMAP_RGBA = 0x1,
IMG_FORMAT_BITMAP_RGB = 0x2,
IMG_FORMAT_BITMAP_LUMINANCE_ALPHA = 0x3,
IMG_FORMAT_BITMAP_LUMINANCE = 0x4,
IMG_FORMAT_BITMAP_ALPHA = 0x5,
IMG_FORMAT_WAVELET_RGBA = 0x6,
IMG_FORMAT_WAVELET_RGB = 0x7,
IMG_FORMAT_WAVELET_LUMINANCE_ALPHA = 0x8,
IMG_FORMAT_WAVELET_LUMINANCE = 0x9,
IMG_FORMAT_WAVELET_ALPHA = 0xA,
IMG_FORMAT_DXT1 = 0xB,
IMG_FORMAT_DXT3 = 0xC,
IMG_FORMAT_DXT5 = 0xD,
IMG_FORMAT_DXN = 0xE,
IMG_FORMAT_COUNT
};
enum IwiFlags
{
IMG_FLAG_NOPICMIP = 1 << 0,
IMG_FLAG_NOMIPMAPS = 1 << 1,
IMG_FLAG_CUBEMAP = 1 << 2,
IMG_FLAG_VOLMAP = 1 << 3,
IMG_FLAG_STREAMING = 1 << 4,
IMG_FLAG_LEGACY_NORMALS = 1 << 5,
IMG_FLAG_CLAMP_U = 1 << 6,
IMG_FLAG_CLAMP_V = 1 << 7,
IMG_FLAG_DYNAMIC = 1 << 16,
IMG_FLAG_RENDER_TARGET = 1 << 17,
IMG_FLAG_SYSTEMMEM = 1 << 18
};
} // namespace iwi6
namespace iwi8
{ {
uint32_t flags; struct IwiHeader
int8_t format; {
int8_t unused; uint32_t flags;
uint16_t dimensions[3]; int8_t format;
uint32_t fileSizeForPicmip[4]; int8_t unused;
}; uint16_t dimensions[3];
uint32_t fileSizeForPicmip[4];
};
enum class IwiFormat enum class IwiFormat
{
IMG_FORMAT_INVALID = 0x0,
IMG_FORMAT_BITMAP_RGBA = 0x1,
IMG_FORMAT_BITMAP_RGB = 0x2,
IMG_FORMAT_BITMAP_LUMINANCE_ALPHA = 0x3,
IMG_FORMAT_BITMAP_LUMINANCE = 0x4,
IMG_FORMAT_BITMAP_ALPHA = 0x5,
IMG_FORMAT_WAVELET_RGBA = 0x6,
IMG_FORMAT_WAVELET_RGB = 0x7,
IMG_FORMAT_WAVELET_LUMINANCE_ALPHA = 0x8,
IMG_FORMAT_WAVELET_LUMINANCE = 0x9,
IMG_FORMAT_WAVELET_ALPHA = 0xA,
IMG_FORMAT_DXT1 = 0xB,
IMG_FORMAT_DXT3 = 0xC,
IMG_FORMAT_DXT5 = 0xD,
IMG_FORMAT_DXN = 0xE,
IMG_FORMAT_DXT3A_AS_LUMINANCE = 0xF,
IMG_FORMAT_DXT5A_AS_LUMINANCE = 0x10,
IMG_FORMAT_DXT3A_AS_ALPHA = 0x11,
IMG_FORMAT_DXT5A_AS_ALPHA = 0x12,
IMG_FORMAT_DXT1_AS_LUMINANCE_ALPHA = 0x13,
IMG_FORMAT_DXN_AS_LUMINANCE_ALPHA = 0x14,
IMG_FORMAT_DXT1_AS_LUMINANCE = 0x15,
IMG_FORMAT_DXT1_AS_ALPHA = 0x16,
IMG_FORMAT_COUNT
};
enum IwiFlags
{
IMG_FLAG_NOPICMIP = 1 << 0,
IMG_FLAG_NOMIPMAPS = 1 << 1,
IMG_FLAG_STREAMING = 1 << 2,
IMG_FLAG_LEGACY_NORMALS = 1 << 3,
IMG_FLAG_CLAMP_U = 1 << 4,
IMG_FLAG_CLAMP_V = 1 << 5,
IMG_FLAG_ALPHA_WEIGHTED_COLORS = 1 << 6,
IMG_FLAG_DXTC_APPROX_WEIGHTS = 1 << 7,
IMG_FLAG_GAMMA_NONE = 0,
IMG_FLAG_GAMMA_SRGB = 1 << 8,
IMG_FLAG_GAMMA_PWL = 1 << 9,
IMG_FLAG_GAMMA_2 = IMG_FLAG_GAMMA_SRGB | IMG_FLAG_GAMMA_PWL,
IMG_FLAG_MAPTYPE_2D = 0,
IMG_FLAG_MAPTYPE_CUBE = 1 << 16,
IMG_FLAG_MAPTYPE_3D = 1 << 17,
IMG_FLAG_MAPTYPE_1D = IMG_FLAG_MAPTYPE_CUBE | IMG_FLAG_MAPTYPE_3D,
IMG_FLAG_MAPTYPE_MASK = IMG_FLAG_MAPTYPE_2D | IMG_FLAG_MAPTYPE_CUBE | IMG_FLAG_MAPTYPE_3D | IMG_FLAG_MAPTYPE_1D,
IMG_FLAG_NORMALMAP = 1 << 18,
IMG_FLAG_INTENSITY_TO_ALPHA = 1 << 19,
IMG_FLAG_DYNAMIC = 1 << 24,
IMG_FLAG_RENDER_TARGET = 1 << 25,
IMG_FLAG_SYSTEMMEM = 1 << 26
};
} // namespace iwi8
namespace iwi13
{ {
IMG_FORMAT_INVALID = 0x0, struct IwiHeader
IMG_FORMAT_BITMAP_RGBA = 0x1, {
IMG_FORMAT_BITMAP_RGB = 0x2, int8_t format;
IMG_FORMAT_BITMAP_LUMINANCE_ALPHA = 0x3, int8_t flags;
IMG_FORMAT_BITMAP_LUMINANCE = 0x4, uint16_t dimensions[3];
IMG_FORMAT_BITMAP_ALPHA = 0x5, float gamma;
IMG_FORMAT_WAVELET_RGBA = 0x6, uint32_t fileSizeForPicmip[8];
IMG_FORMAT_WAVELET_RGB = 0x7, };
IMG_FORMAT_WAVELET_LUMINANCE_ALPHA = 0x8,
IMG_FORMAT_WAVELET_LUMINANCE = 0x9,
IMG_FORMAT_WAVELET_ALPHA = 0xA,
IMG_FORMAT_DXT1 = 0xB,
IMG_FORMAT_DXT3 = 0xC,
IMG_FORMAT_DXT5 = 0xD,
IMG_FORMAT_DXN = 0xE,
IMG_FORMAT_DXT3A_AS_LUMINANCE = 0xF,
IMG_FORMAT_DXT5A_AS_LUMINANCE = 0x10,
IMG_FORMAT_DXT3A_AS_ALPHA = 0x11,
IMG_FORMAT_DXT5A_AS_ALPHA = 0x12,
IMG_FORMAT_DXT1_AS_LUMINANCE_ALPHA = 0x13,
IMG_FORMAT_DXN_AS_LUMINANCE_ALPHA = 0x14,
IMG_FORMAT_DXT1_AS_LUMINANCE = 0x15,
IMG_FORMAT_DXT1_AS_ALPHA = 0x16,
IMG_FORMAT_COUNT enum class IwiFormat
}; {
IMG_FORMAT_INVALID = 0x0,
IMG_FORMAT_BITMAP_RGBA = 0x1,
IMG_FORMAT_BITMAP_RGB = 0x2,
IMG_FORMAT_BITMAP_LUMINANCE_ALPHA = 0x3,
IMG_FORMAT_BITMAP_LUMINANCE = 0x4,
IMG_FORMAT_BITMAP_ALPHA = 0x5,
IMG_FORMAT_WAVELET_RGBA = 0x6,
IMG_FORMAT_WAVELET_RGB = 0x7,
IMG_FORMAT_WAVELET_LUMINANCE_ALPHA = 0x8,
IMG_FORMAT_WAVELET_LUMINANCE = 0x9,
IMG_FORMAT_WAVELET_ALPHA = 0xA,
IMG_FORMAT_DXT1 = 0xB,
IMG_FORMAT_DXT3 = 0xC,
IMG_FORMAT_DXT5 = 0xD,
IMG_FORMAT_DXN = 0xE,
IMG_FORMAT_BITMAP_RGB565 = 0xF,
IMG_FORMAT_BITMAP_RGB5A3 = 0x10,
IMG_FORMAT_BITMAP_C8 = 0x11,
IMG_FORMAT_BITMAP_RGBA8 = 0x12,
IMG_FORMAT_A16B16G16R16F = 0x13,
IMG_FORMAT_COUNT = 0x14,
};
enum IwiFlags enum IwiFlags
{
IMG_FLAG_NOPICMIP = 1 << 0,
IMG_FLAG_NOMIPMAPS = 1 << 1,
IMG_FLAG_CUBEMAP = 1 << 2,
IMG_FLAG_VOLMAP = 1 << 3,
IMG_FLAG_STREAMING = 1 << 4,
IMG_FLAG_LEGACY_NORMALS = 1 << 5,
IMG_FLAG_CLAMP_U = 1 << 6,
IMG_FLAG_CLAMP_V = 1 << 7,
IMG_FLAG_FORCE_SYSTEM = 1 << 8,
IMG_FLAG_DYNAMIC = 1 << 16,
IMG_FLAG_RENDER_TARGET = 1 << 17,
IMG_FLAG_SYSTEMMEM = 1 << 18,
};
} // namespace iwi13
namespace iwi27
{ {
IMG_FLAG_NOPICMIP = 1 << 0, struct IwiHeader
IMG_FLAG_NOMIPMAPS = 1 << 1, {
IMG_FLAG_STREAMING = 1 << 2, int8_t format;
IMG_FLAG_LEGACY_NORMALS = 1 << 3, int8_t flags;
IMG_FLAG_CLAMP_U = 1 << 4, uint16_t dimensions[3];
IMG_FLAG_CLAMP_V = 1 << 5, float gamma;
IMG_FLAG_ALPHA_WEIGHTED_COLORS = 1 << 6, int8_t maxGlossForMip[16];
IMG_FLAG_DXTC_APPROX_WEIGHTS = 1 << 7, uint32_t fileSizeForPicmip[8];
IMG_FLAG_GAMMA_NONE = 0, };
IMG_FLAG_GAMMA_SRGB = 1 << 8,
IMG_FLAG_GAMMA_PWL = 1 << 9,
IMG_FLAG_GAMMA_2 = IMG_FLAG_GAMMA_SRGB | IMG_FLAG_GAMMA_PWL,
IMG_FLAG_MAPTYPE_2D = 0,
IMG_FLAG_MAPTYPE_CUBE = 1 << 16,
IMG_FLAG_MAPTYPE_3D = 1 << 17,
IMG_FLAG_MAPTYPE_1D = IMG_FLAG_MAPTYPE_CUBE | IMG_FLAG_MAPTYPE_3D,
IMG_FLAG_MAPTYPE_MASK = IMG_FLAG_MAPTYPE_2D | IMG_FLAG_MAPTYPE_CUBE | IMG_FLAG_MAPTYPE_3D | IMG_FLAG_MAPTYPE_1D,
IMG_FLAG_NORMALMAP = 1 << 18,
IMG_FLAG_INTENSITY_TO_ALPHA = 1 << 19,
IMG_FLAG_DYNAMIC = 1 << 24,
IMG_FLAG_RENDER_TARGET = 1 << 25,
IMG_FLAG_SYSTEMMEM = 1 << 26
};
} // namespace iwi8
// T5 enum class IwiFormat
namespace iwi13 {
{ IMG_FORMAT_INVALID = 0x0,
struct IwiHeader IMG_FORMAT_BITMAP_RGBA = 0x1,
{ IMG_FORMAT_BITMAP_RGB = 0x2,
int8_t format; IMG_FORMAT_BITMAP_LUMINANCE_ALPHA = 0x3,
int8_t flags; IMG_FORMAT_BITMAP_LUMINANCE = 0x4,
uint16_t dimensions[3]; IMG_FORMAT_BITMAP_ALPHA = 0x5,
float gamma; IMG_FORMAT_WAVELET_RGBA = 0x6,
uint32_t fileSizeForPicmip[8]; IMG_FORMAT_WAVELET_RGB = 0x7,
}; IMG_FORMAT_WAVELET_LUMINANCE_ALPHA = 0x8,
IMG_FORMAT_WAVELET_LUMINANCE = 0x9,
IMG_FORMAT_WAVELET_ALPHA = 0xA,
IMG_FORMAT_DXT1 = 0xB,
IMG_FORMAT_DXT3 = 0xC,
IMG_FORMAT_DXT5 = 0xD,
IMG_FORMAT_DXN = 0xE,
IMG_FORMAT_BITMAP_RGB565 = 0xF,
IMG_FORMAT_BITMAP_RGB5A3 = 0x10,
IMG_FORMAT_BITMAP_C8 = 0x11,
IMG_FORMAT_BITMAP_RGBA8 = 0x12,
IMG_FORMAT_A16B16G16R16F = 0x13,
IMG_FORMAT_COUNT,
};
enum class IwiFormat enum IwiFlags
{ {
IMG_FORMAT_INVALID = 0x0, IMG_FLAG_NOPICMIP = 1 << 0,
IMG_FORMAT_BITMAP_RGBA = 0x1, IMG_FLAG_NOMIPMAPS = 1 << 1,
IMG_FORMAT_BITMAP_RGB = 0x2, IMG_FLAG_CUBEMAP = 1 << 2,
IMG_FORMAT_BITMAP_LUMINANCE_ALPHA = 0x3, IMG_FLAG_VOLMAP = 1 << 3,
IMG_FORMAT_BITMAP_LUMINANCE = 0x4, IMG_FLAG_STREAMING = 1 << 4,
IMG_FORMAT_BITMAP_ALPHA = 0x5, IMG_FLAG_CLAMP_U = 1 << 6,
IMG_FORMAT_WAVELET_RGBA = 0x6, IMG_FLAG_CLAMP_V = 1 << 7,
IMG_FORMAT_WAVELET_RGB = 0x7, IMG_FLAG_FORCE_SYSTEM = 1 << 8,
IMG_FORMAT_WAVELET_LUMINANCE_ALPHA = 0x8, IMG_FLAG_DYNAMIC = 1 << 16,
IMG_FORMAT_WAVELET_LUMINANCE = 0x9, IMG_FLAG_RENDER_TARGET = 1 << 17,
IMG_FORMAT_WAVELET_ALPHA = 0xA, IMG_FLAG_MULTISAMPLE = 1 << 18,
IMG_FORMAT_DXT1 = 0xB, };
IMG_FORMAT_DXT3 = 0xC,
IMG_FORMAT_DXT5 = 0xD,
IMG_FORMAT_DXN = 0xE,
IMG_FORMAT_BITMAP_RGB565 = 0xF,
IMG_FORMAT_BITMAP_RGB5A3 = 0x10,
IMG_FORMAT_BITMAP_C8 = 0x11,
IMG_FORMAT_BITMAP_RGBA8 = 0x12,
IMG_FORMAT_A16B16G16R16F = 0x13,
IMG_FORMAT_COUNT = 0x14,
};
enum IwiFlags } // namespace iwi27
{ } // namespace image
IMG_FLAG_NOPICMIP = 1 << 0,
IMG_FLAG_NOMIPMAPS = 1 << 1,
IMG_FLAG_CUBEMAP = 1 << 2,
IMG_FLAG_VOLMAP = 1 << 3,
IMG_FLAG_STREAMING = 1 << 4,
IMG_FLAG_LEGACY_NORMALS = 1 << 5,
IMG_FLAG_CLAMP_U = 1 << 6,
IMG_FLAG_CLAMP_V = 1 << 7,
IMG_FLAG_FORCE_SYSTEM = 1 << 8,
IMG_FLAG_DYNAMIC = 1 << 16,
IMG_FLAG_RENDER_TARGET = 1 << 17,
IMG_FLAG_SYSTEMMEM = 1 << 18,
};
} // namespace iwi13
// T6
namespace iwi27
{
struct IwiHeader
{
int8_t format;
int8_t flags;
uint16_t dimensions[3];
float gamma;
int8_t maxGlossForMip[16];
uint32_t fileSizeForPicmip[8];
};
enum class IwiFormat
{
IMG_FORMAT_INVALID = 0x0,
IMG_FORMAT_BITMAP_RGBA = 0x1,
IMG_FORMAT_BITMAP_RGB = 0x2,
IMG_FORMAT_BITMAP_LUMINANCE_ALPHA = 0x3,
IMG_FORMAT_BITMAP_LUMINANCE = 0x4,
IMG_FORMAT_BITMAP_ALPHA = 0x5,
IMG_FORMAT_WAVELET_RGBA = 0x6,
IMG_FORMAT_WAVELET_RGB = 0x7,
IMG_FORMAT_WAVELET_LUMINANCE_ALPHA = 0x8,
IMG_FORMAT_WAVELET_LUMINANCE = 0x9,
IMG_FORMAT_WAVELET_ALPHA = 0xA,
IMG_FORMAT_DXT1 = 0xB,
IMG_FORMAT_DXT3 = 0xC,
IMG_FORMAT_DXT5 = 0xD,
IMG_FORMAT_DXN = 0xE,
IMG_FORMAT_BITMAP_RGB565 = 0xF,
IMG_FORMAT_BITMAP_RGB5A3 = 0x10,
IMG_FORMAT_BITMAP_C8 = 0x11,
IMG_FORMAT_BITMAP_RGBA8 = 0x12,
IMG_FORMAT_A16B16G16R16F = 0x13,
IMG_FORMAT_COUNT,
};
enum IwiFlags
{
IMG_FLAG_NOPICMIP = 1 << 0,
IMG_FLAG_NOMIPMAPS = 1 << 1,
IMG_FLAG_CUBEMAP = 1 << 2,
IMG_FLAG_VOLMAP = 1 << 3,
IMG_FLAG_STREAMING = 1 << 4,
IMG_FLAG_CLAMP_U = 1 << 6,
IMG_FLAG_CLAMP_V = 1 << 7,
IMG_FLAG_FORCE_SYSTEM = 1 << 8,
IMG_FLAG_DYNAMIC = 1 << 16,
IMG_FLAG_RENDER_TARGET = 1 << 17,
IMG_FLAG_MULTISAMPLE = 1 << 18,
};
} // namespace iwi27

View File

@@ -3,7 +3,7 @@
#include <cassert> #include <cassert>
#include <ostream> #include <ostream>
using namespace iwi13; using namespace image::iwi13;
IwiWriter::IwiWriter() = default; IwiWriter::IwiWriter() = default;
@@ -54,13 +54,13 @@ std::string IwiWriter::GetFileExtension()
void IwiWriter::WriteVersion(std::ostream& stream) void IwiWriter::WriteVersion(std::ostream& stream)
{ {
IwiVersion version{}; IwiVersionHeader version{};
version.tag[0] = 'I'; version.tag[0] = 'I';
version.tag[1] = 'W'; version.tag[1] = 'W';
version.tag[2] = 'i'; version.tag[2] = 'i';
version.version = 13; version.version = 13;
stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersion)); stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersionHeader));
} }
void IwiWriter::FillHeader2D(IwiHeader& header, const Texture2D& texture) void IwiWriter::FillHeader2D(IwiHeader& header, const Texture2D& texture)
@@ -101,7 +101,7 @@ void IwiWriter::DumpImage(std::ostream& stream, const Texture* texture)
if (!texture->HasMipMaps()) if (!texture->HasMipMaps())
header.flags |= IMG_FLAG_NOMIPMAPS; header.flags |= IMG_FLAG_NOMIPMAPS;
auto currentFileSize = sizeof(IwiVersion) + sizeof(IwiHeader); auto currentFileSize = sizeof(IwiVersionHeader) + sizeof(IwiHeader);
const auto textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1; const auto textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--) for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--)

View File

@@ -1,11 +1,11 @@
#pragma once #pragma once
#include "IImageWriter.h"
#include "Image/IwiTypes.h" #include "Image/IwiTypes.h"
#include "ImageWriter.h"
namespace iwi13 namespace image::iwi13
{ {
class IwiWriter final : public IImageWriter class IwiWriter final : public ImageWriter
{ {
static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat); static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat);
@@ -27,4 +27,4 @@ namespace iwi13
std::string GetFileExtension() override; std::string GetFileExtension() override;
void DumpImage(std::ostream& stream, const Texture* texture) override; void DumpImage(std::ostream& stream, const Texture* texture) override;
}; };
} // namespace iwi13 } // namespace image::iwi13

View File

@@ -3,7 +3,7 @@
#include <cassert> #include <cassert>
#include <ostream> #include <ostream>
using namespace iwi27; using namespace image::iwi27;
IwiWriter::IwiWriter() = default; IwiWriter::IwiWriter() = default;
@@ -54,13 +54,13 @@ std::string IwiWriter::GetFileExtension()
void IwiWriter::WriteVersion(std::ostream& stream) void IwiWriter::WriteVersion(std::ostream& stream)
{ {
IwiVersion version{}; IwiVersionHeader version{};
version.tag[0] = 'I'; version.tag[0] = 'I';
version.tag[1] = 'W'; version.tag[1] = 'W';
version.tag[2] = 'i'; version.tag[2] = 'i';
version.version = 27; version.version = 27;
stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersion)); stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersionHeader));
} }
void IwiWriter::FillHeader2D(IwiHeader& header, const Texture2D& texture) void IwiWriter::FillHeader2D(IwiHeader& header, const Texture2D& texture)
@@ -104,7 +104,7 @@ void IwiWriter::DumpImage(std::ostream& stream, const Texture* texture)
for (auto& i : header.maxGlossForMip) for (auto& i : header.maxGlossForMip)
i = 0; i = 0;
auto currentFileSize = sizeof(IwiVersion) + sizeof(IwiHeader); auto currentFileSize = sizeof(IwiVersionHeader) + sizeof(IwiHeader);
const auto textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1; const auto textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--) for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--)

View File

@@ -1,11 +1,11 @@
#pragma once #pragma once
#include "IImageWriter.h"
#include "Image/IwiTypes.h" #include "Image/IwiTypes.h"
#include "ImageWriter.h"
namespace iwi27 namespace image::iwi27
{ {
class IwiWriter final : public IImageWriter class IwiWriter final : public ImageWriter
{ {
static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat); static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat);
@@ -27,4 +27,4 @@ namespace iwi27
std::string GetFileExtension() override; std::string GetFileExtension() override;
void DumpImage(std::ostream& stream, const Texture* texture) override; void DumpImage(std::ostream& stream, const Texture* texture) override;
}; };
} // namespace iwi27 } // namespace image::iwi27

View File

@@ -2,7 +2,7 @@
#include <cassert> #include <cassert>
using namespace iwi6; using namespace image::iwi6;
IwiWriter::IwiWriter() = default; IwiWriter::IwiWriter() = default;
@@ -40,13 +40,13 @@ IwiFormat IwiWriter::GetIwiFormatForImageFormat(const ImageFormat* imageFormat)
void IwiWriter::WriteVersion(std::ostream& stream) void IwiWriter::WriteVersion(std::ostream& stream)
{ {
IwiVersion version{}; IwiVersionHeader version{};
version.tag[0] = 'I'; version.tag[0] = 'I';
version.tag[1] = 'W'; version.tag[1] = 'W';
version.tag[2] = 'i'; version.tag[2] = 'i';
version.version = 6; version.version = 6;
stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersion)); stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersionHeader));
} }
void IwiWriter::FillHeader2D(IwiHeader& header, const Texture2D& texture) void IwiWriter::FillHeader2D(IwiHeader& header, const Texture2D& texture)
@@ -96,7 +96,7 @@ void IwiWriter::DumpImage(std::ostream& stream, const Texture* texture)
if (!texture->HasMipMaps()) if (!texture->HasMipMaps())
header.flags |= IMG_FLAG_NOMIPMAPS; header.flags |= IMG_FLAG_NOMIPMAPS;
auto currentFileSize = sizeof(IwiVersion) + sizeof(IwiHeader); auto currentFileSize = sizeof(IwiVersionHeader) + sizeof(IwiHeader);
const auto textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1; const auto textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--) for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--)

View File

@@ -1,11 +1,11 @@
#pragma once #pragma once
#include "IImageWriter.h"
#include "Image/IwiTypes.h" #include "Image/IwiTypes.h"
#include "ImageWriter.h"
namespace iwi6 namespace image::iwi6
{ {
class IwiWriter final : public IImageWriter class IwiWriter final : public ImageWriter
{ {
static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat); static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat);
@@ -27,4 +27,4 @@ namespace iwi6
std::string GetFileExtension() override; std::string GetFileExtension() override;
void DumpImage(std::ostream& stream, const Texture* texture) override; void DumpImage(std::ostream& stream, const Texture* texture) override;
}; };
} // namespace iwi6 } // namespace image::iwi6

View File

@@ -2,7 +2,7 @@
#include <cassert> #include <cassert>
using namespace iwi8; using namespace image::iwi8;
IwiWriter::IwiWriter() = default; IwiWriter::IwiWriter() = default;
@@ -40,13 +40,13 @@ IwiFormat IwiWriter::GetIwiFormatForImageFormat(const ImageFormat* imageFormat)
void IwiWriter::WriteVersion(std::ostream& stream) void IwiWriter::WriteVersion(std::ostream& stream)
{ {
IwiVersion version{}; IwiVersionHeader version{};
version.tag[0] = 'I'; version.tag[0] = 'I';
version.tag[1] = 'W'; version.tag[1] = 'W';
version.tag[2] = 'i'; version.tag[2] = 'i';
version.version = 8; version.version = 8;
stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersion)); stream.write(reinterpret_cast<char*>(&version), sizeof(IwiVersionHeader));
} }
void IwiWriter::FillHeader2D(IwiHeader& header, const Texture2D& texture) void IwiWriter::FillHeader2D(IwiHeader& header, const Texture2D& texture)
@@ -96,7 +96,7 @@ void IwiWriter::DumpImage(std::ostream& stream, const Texture* texture)
if (!texture->HasMipMaps()) if (!texture->HasMipMaps())
header.flags |= IMG_FLAG_NOMIPMAPS; header.flags |= IMG_FLAG_NOMIPMAPS;
auto currentFileSize = sizeof(IwiVersion) + sizeof(IwiHeader); auto currentFileSize = sizeof(IwiVersionHeader) + sizeof(IwiHeader);
const auto textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1; const auto textureMipCount = texture->HasMipMaps() ? texture->GetMipMapCount() : 1;
for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--) for (auto currentMipLevel = textureMipCount - 1; currentMipLevel >= 0; currentMipLevel--)

View File

@@ -1,11 +1,11 @@
#pragma once #pragma once
#include "IImageWriter.h"
#include "Image/IwiTypes.h" #include "Image/IwiTypes.h"
#include "ImageWriter.h"
namespace iwi8 namespace image::iwi8
{ {
class IwiWriter final : public IImageWriter class IwiWriter final : public ImageWriter
{ {
static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat); static IwiFormat GetIwiFormatForImageFormat(const ImageFormat* imageFormat);
@@ -27,4 +27,4 @@ namespace iwi8
std::string GetFileExtension() override; std::string GetFileExtension() override;
void DumpImage(std::ostream& stream, const Texture* texture) override; void DumpImage(std::ostream& stream, const Texture* texture) override;
}; };
} // namespace iwi8 } // namespace image::iwi8

View File

@@ -4,440 +4,443 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
// ============================================== namespace image
// ================= Texture ====================
// ==============================================
Texture::Texture(const ImageFormat* format, const bool mipMaps)
{ {
m_format = format; // ==============================================
m_has_mip_maps = mipMaps; // ================= Texture ====================
m_data = nullptr; // ==============================================
} Texture::Texture(const ImageFormat* format, const bool mipMaps)
Texture::Texture(Texture&& other) noexcept
{
m_format = other.m_format;
m_has_mip_maps = other.m_has_mip_maps;
m_data = other.m_data;
other.m_data = nullptr;
}
Texture& Texture::operator=(Texture&& other) noexcept
{
m_format = other.m_format;
m_has_mip_maps = other.m_has_mip_maps;
m_data = other.m_data;
other.m_data = nullptr;
return *this;
}
Texture::~Texture()
{
delete[] m_data;
m_data = nullptr;
}
const ImageFormat* Texture::GetFormat() const
{
return m_format;
}
void Texture::Allocate()
{
size_t storageRequirement = 0;
const int mipLevelCount = m_has_mip_maps ? GetMipMapCount() : 1;
for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++)
{ {
storageRequirement += GetSizeOfMipLevel(currentMipLevel) * GetFaceCount(); m_format = format;
m_has_mip_maps = mipMaps;
m_data = nullptr;
} }
if (storageRequirement > 0) Texture::Texture(Texture&& other) noexcept
{ {
m_data = new uint8_t[storageRequirement]; m_format = other.m_format;
memset(m_data, 0, storageRequirement); m_has_mip_maps = other.m_has_mip_maps;
m_data = other.m_data;
other.m_data = nullptr;
} }
}
bool Texture::Empty() const Texture& Texture::operator=(Texture&& other) noexcept
{ {
return m_data == nullptr; m_format = other.m_format;
} m_has_mip_maps = other.m_has_mip_maps;
m_data = other.m_data;
bool Texture::HasMipMaps() const other.m_data = nullptr;
{
return m_has_mip_maps;
}
uint8_t* Texture::GetBufferForMipLevel(const int mipLevel)
{
return GetBufferForMipLevel(mipLevel, 0);
}
const uint8_t* Texture::GetBufferForMipLevel(const int mipLevel) const
{
return GetBufferForMipLevel(mipLevel, 0);
}
// ==============================================
// ================ Texture2D ===================
// ==============================================
Texture2D::Texture2D(const ImageFormat* format, const unsigned width, const unsigned height)
: Texture2D(format, width, height, false)
{
}
Texture2D::Texture2D(const ImageFormat* format, const unsigned width, const unsigned height, const bool mipMaps)
: Texture(format, mipMaps)
{
m_width = width;
m_height = height;
}
Texture2D::Texture2D(Texture2D&& other) noexcept
: Texture(std::move(other)),
m_width(other.m_width),
m_height(other.m_height)
{
}
Texture2D::~Texture2D() = default;
Texture2D& Texture2D::operator=(Texture2D&& other) noexcept
{
if (this == &other)
return *this; return *this;
Texture::operator=(std::move(other));
m_width = other.m_width;
m_height = other.m_height;
return *this;
}
TextureType Texture2D::GetTextureType() const
{
return TextureType::T_2D;
}
unsigned Texture2D::GetWidth() const
{
return m_width;
}
unsigned Texture2D::GetHeight() const
{
return m_height;
}
unsigned Texture2D::GetDepth() const
{
return 1;
}
int Texture2D::GetFaceCount() const
{
return 1;
}
size_t Texture2D::GetSizeOfMipLevel(const int mipLevel) const
{
return m_format->GetSizeOfMipLevel(mipLevel, m_width, m_height, 1);
}
int Texture2D::GetMipMapCount() const
{
unsigned maxDimension = std::max(m_width, m_height);
int mipMapCount = 0;
while (maxDimension != 0)
{
maxDimension >>= 1;
mipMapCount++;
} }
return mipMapCount; Texture::~Texture()
}
uint8_t* Texture2D::GetBufferForMipLevel(const int mipLevel, const int face)
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face == 0);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face != 0)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{ {
bufferOffset += GetSizeOfMipLevel(previousMipLevel); delete[] m_data;
m_data = nullptr;
} }
return &m_data[bufferOffset]; const ImageFormat* Texture::GetFormat() const
}
const uint8_t* Texture2D::GetBufferForMipLevel(const int mipLevel, const int face) const
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face == 0);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face != 0)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{ {
bufferOffset += GetSizeOfMipLevel(previousMipLevel); return m_format;
} }
return &m_data[bufferOffset]; void Texture::Allocate()
} {
size_t storageRequirement = 0;
const int mipLevelCount = m_has_mip_maps ? GetMipMapCount() : 1;
// ============================================== for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++)
// =============== TextureCube ================== {
// ============================================== storageRequirement += GetSizeOfMipLevel(currentMipLevel) * GetFaceCount();
const int TextureCube::FACE_COUNT = 6; }
TextureCube::TextureCube(const ImageFormat* format, const unsigned width, const unsigned height) if (storageRequirement > 0)
: Texture2D(format, width, height) {
{ m_data = new uint8_t[storageRequirement];
} memset(m_data, 0, storageRequirement);
}
}
TextureCube::TextureCube(const ImageFormat* format, const unsigned width, const unsigned height, const bool mipMaps) bool Texture::Empty() const
: Texture2D(format, width, height, mipMaps) {
{ return m_data == nullptr;
} }
TextureCube::TextureCube(TextureCube&& other) noexcept bool Texture::HasMipMaps() const
: Texture2D(std::move(other)) {
{ return m_has_mip_maps;
} }
TextureCube::~TextureCube() = default; uint8_t* Texture::GetBufferForMipLevel(const int mipLevel)
{
return GetBufferForMipLevel(mipLevel, 0);
}
const uint8_t* Texture::GetBufferForMipLevel(const int mipLevel) const
{
return GetBufferForMipLevel(mipLevel, 0);
}
// ==============================================
// ================ Texture2D ===================
// ==============================================
Texture2D::Texture2D(const ImageFormat* format, const unsigned width, const unsigned height)
: Texture2D(format, width, height, false)
{
}
Texture2D::Texture2D(const ImageFormat* format, const unsigned width, const unsigned height, const bool mipMaps)
: Texture(format, mipMaps)
{
m_width = width;
m_height = height;
}
Texture2D::Texture2D(Texture2D&& other) noexcept
: Texture(std::move(other)),
m_width(other.m_width),
m_height(other.m_height)
{
}
Texture2D::~Texture2D() = default;
Texture2D& Texture2D::operator=(Texture2D&& other) noexcept
{
if (this == &other)
return *this;
Texture::operator=(std::move(other));
m_width = other.m_width;
m_height = other.m_height;
TextureCube& TextureCube::operator=(TextureCube&& other) noexcept
{
if (this == &other)
return *this; return *this;
Texture2D::operator=(std::move(other));
return *this;
}
TextureType TextureCube::GetTextureType() const
{
return TextureType::T_CUBE;
}
int TextureCube::GetFaceCount() const
{
return FACE_COUNT;
}
uint8_t* TextureCube::GetBufferForMipLevel(const int mipLevel, const int face)
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face >= 0);
assert(face < FACE_COUNT);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face < 0 || face >= FACE_COUNT)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{
bufferOffset += GetSizeOfMipLevel(previousMipLevel) * FACE_COUNT;
} }
return &m_data[bufferOffset + GetSizeOfMipLevel(mipLevel) * face]; TextureType Texture2D::GetTextureType() const
}
const uint8_t* TextureCube::GetBufferForMipLevel(const int mipLevel, const int face) const
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face >= 0);
assert(face < FACE_COUNT);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face < 0 || face >= FACE_COUNT)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{ {
bufferOffset += GetSizeOfMipLevel(previousMipLevel) * FACE_COUNT; return TextureType::T_2D;
} }
return &m_data[bufferOffset + GetSizeOfMipLevel(mipLevel) * face]; unsigned Texture2D::GetWidth() const
} {
return m_width;
}
// ============================================== unsigned Texture2D::GetHeight() const
// ================ Texture3D =================== {
// ============================================== return m_height;
}
Texture3D::Texture3D(const ImageFormat* format, const unsigned width, const unsigned height, const unsigned depth) unsigned Texture2D::GetDepth() const
: Texture3D(format, width, height, depth, false) {
{ return 1;
} }
Texture3D::Texture3D(const ImageFormat* format, const unsigned width, const unsigned height, const unsigned depth, const bool mipMaps) int Texture2D::GetFaceCount() const
: Texture(format, mipMaps) {
{ return 1;
m_width = width; }
m_height = height;
m_depth = depth;
}
Texture3D::Texture3D(Texture3D&& other) noexcept size_t Texture2D::GetSizeOfMipLevel(const int mipLevel) const
: Texture(std::move(other)), {
m_width(other.m_width), return m_format->GetSizeOfMipLevel(mipLevel, m_width, m_height, 1);
m_height(other.m_height), }
m_depth(other.m_depth)
{
}
Texture3D::~Texture3D() = default; int Texture2D::GetMipMapCount() const
{
unsigned maxDimension = std::max(m_width, m_height);
int mipMapCount = 0;
while (maxDimension != 0)
{
maxDimension >>= 1;
mipMapCount++;
}
return mipMapCount;
}
uint8_t* Texture2D::GetBufferForMipLevel(const int mipLevel, const int face)
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face == 0);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face != 0)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{
bufferOffset += GetSizeOfMipLevel(previousMipLevel);
}
return &m_data[bufferOffset];
}
const uint8_t* Texture2D::GetBufferForMipLevel(const int mipLevel, const int face) const
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face == 0);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face != 0)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{
bufferOffset += GetSizeOfMipLevel(previousMipLevel);
}
return &m_data[bufferOffset];
}
// ==============================================
// =============== TextureCube ==================
// ==============================================
const int TextureCube::FACE_COUNT = 6;
TextureCube::TextureCube(const ImageFormat* format, const unsigned width, const unsigned height)
: Texture2D(format, width, height)
{
}
TextureCube::TextureCube(const ImageFormat* format, const unsigned width, const unsigned height, const bool mipMaps)
: Texture2D(format, width, height, mipMaps)
{
}
TextureCube::TextureCube(TextureCube&& other) noexcept
: Texture2D(std::move(other))
{
}
TextureCube::~TextureCube() = default;
TextureCube& TextureCube::operator=(TextureCube&& other) noexcept
{
if (this == &other)
return *this;
Texture2D::operator=(std::move(other));
Texture3D& Texture3D::operator=(Texture3D&& other) noexcept
{
if (this == &other)
return *this; return *this;
Texture::operator=(std::move(other));
m_width = other.m_width;
m_height = other.m_height;
m_depth = other.m_depth;
return *this;
}
TextureType Texture3D::GetTextureType() const
{
return TextureType::T_3D;
}
unsigned Texture3D::GetWidth() const
{
return m_width;
}
unsigned Texture3D::GetHeight() const
{
return m_height;
}
unsigned Texture3D::GetDepth() const
{
return m_depth;
}
int Texture3D::GetFaceCount() const
{
return 1;
}
size_t Texture3D::GetSizeOfMipLevel(const int mipLevel) const
{
return m_format->GetSizeOfMipLevel(mipLevel, m_width, m_height, m_depth);
}
int Texture3D::GetMipMapCount() const
{
unsigned maxDimension = std::max(std::max(m_width, m_height), m_depth);
int mipMapCount = 0;
while (maxDimension != 0)
{
maxDimension >>= 1;
mipMapCount++;
} }
return mipMapCount; TextureType TextureCube::GetTextureType() const
}
uint8_t* Texture3D::GetBufferForMipLevel(const int mipLevel, const int face)
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face == 0);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face != 0)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{ {
bufferOffset += GetSizeOfMipLevel(previousMipLevel); return TextureType::T_CUBE;
} }
return &m_data[bufferOffset]; int TextureCube::GetFaceCount() const
}
const uint8_t* Texture3D::GetBufferForMipLevel(const int mipLevel, const int face) const
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face == 0);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face != 0)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{ {
bufferOffset += GetSizeOfMipLevel(previousMipLevel); return FACE_COUNT;
} }
return &m_data[bufferOffset]; uint8_t* TextureCube::GetBufferForMipLevel(const int mipLevel, const int face)
} {
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face >= 0);
assert(face < FACE_COUNT);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face < 0 || face >= FACE_COUNT)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{
bufferOffset += GetSizeOfMipLevel(previousMipLevel) * FACE_COUNT;
}
return &m_data[bufferOffset + GetSizeOfMipLevel(mipLevel) * face];
}
const uint8_t* TextureCube::GetBufferForMipLevel(const int mipLevel, const int face) const
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face >= 0);
assert(face < FACE_COUNT);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face < 0 || face >= FACE_COUNT)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{
bufferOffset += GetSizeOfMipLevel(previousMipLevel) * FACE_COUNT;
}
return &m_data[bufferOffset + GetSizeOfMipLevel(mipLevel) * face];
}
// ==============================================
// ================ Texture3D ===================
// ==============================================
Texture3D::Texture3D(const ImageFormat* format, const unsigned width, const unsigned height, const unsigned depth)
: Texture3D(format, width, height, depth, false)
{
}
Texture3D::Texture3D(const ImageFormat* format, const unsigned width, const unsigned height, const unsigned depth, const bool mipMaps)
: Texture(format, mipMaps)
{
m_width = width;
m_height = height;
m_depth = depth;
}
Texture3D::Texture3D(Texture3D&& other) noexcept
: Texture(std::move(other)),
m_width(other.m_width),
m_height(other.m_height),
m_depth(other.m_depth)
{
}
Texture3D::~Texture3D() = default;
Texture3D& Texture3D::operator=(Texture3D&& other) noexcept
{
if (this == &other)
return *this;
Texture::operator=(std::move(other));
m_width = other.m_width;
m_height = other.m_height;
m_depth = other.m_depth;
return *this;
}
TextureType Texture3D::GetTextureType() const
{
return TextureType::T_3D;
}
unsigned Texture3D::GetWidth() const
{
return m_width;
}
unsigned Texture3D::GetHeight() const
{
return m_height;
}
unsigned Texture3D::GetDepth() const
{
return m_depth;
}
int Texture3D::GetFaceCount() const
{
return 1;
}
size_t Texture3D::GetSizeOfMipLevel(const int mipLevel) const
{
return m_format->GetSizeOfMipLevel(mipLevel, m_width, m_height, m_depth);
}
int Texture3D::GetMipMapCount() const
{
unsigned maxDimension = std::max(std::max(m_width, m_height), m_depth);
int mipMapCount = 0;
while (maxDimension != 0)
{
maxDimension >>= 1;
mipMapCount++;
}
return mipMapCount;
}
uint8_t* Texture3D::GetBufferForMipLevel(const int mipLevel, const int face)
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face == 0);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face != 0)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{
bufferOffset += GetSizeOfMipLevel(previousMipLevel);
}
return &m_data[bufferOffset];
}
const uint8_t* Texture3D::GetBufferForMipLevel(const int mipLevel, const int face) const
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face == 0);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face != 0)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{
bufferOffset += GetSizeOfMipLevel(previousMipLevel);
}
return &m_data[bufferOffset];
}
} // namespace image

View File

@@ -3,130 +3,133 @@
#include <cstdint> #include <cstdint>
enum class TextureType : std::uint8_t namespace image
{ {
T_2D, enum class TextureType : std::uint8_t
T_CUBE, {
T_3D T_2D,
}; T_CUBE,
T_3D
};
class Texture class Texture
{ {
protected: protected:
const ImageFormat* m_format; const ImageFormat* m_format;
bool m_has_mip_maps; bool m_has_mip_maps;
uint8_t* m_data; uint8_t* m_data;
Texture(const ImageFormat* format, bool mipMaps); Texture(const ImageFormat* format, bool mipMaps);
Texture(Texture&& other) noexcept; Texture(Texture&& other) noexcept;
Texture& operator=(Texture&& other) noexcept; Texture& operator=(Texture&& other) noexcept;
public: public:
Texture(const Texture& other) = delete; Texture(const Texture& other) = delete;
virtual ~Texture(); virtual ~Texture();
Texture& operator=(const Texture& other) = delete; Texture& operator=(const Texture& other) = delete;
[[nodiscard]] virtual TextureType GetTextureType() const = 0; [[nodiscard]] virtual TextureType GetTextureType() const = 0;
[[nodiscard]] const ImageFormat* GetFormat() const; [[nodiscard]] const ImageFormat* GetFormat() const;
[[nodiscard]] virtual unsigned GetWidth() const = 0; [[nodiscard]] virtual unsigned GetWidth() const = 0;
[[nodiscard]] virtual unsigned GetHeight() const = 0; [[nodiscard]] virtual unsigned GetHeight() const = 0;
[[nodiscard]] virtual unsigned GetDepth() const = 0; [[nodiscard]] virtual unsigned GetDepth() const = 0;
[[nodiscard]] virtual int GetFaceCount() const = 0; [[nodiscard]] virtual int GetFaceCount() const = 0;
void Allocate(); void Allocate();
[[nodiscard]] bool Empty() const; [[nodiscard]] bool Empty() const;
[[nodiscard]] virtual size_t GetSizeOfMipLevel(int mipLevel) const = 0; [[nodiscard]] virtual size_t GetSizeOfMipLevel(int mipLevel) const = 0;
[[nodiscard]] virtual uint8_t* GetBufferForMipLevel(int mipLevel, int face) = 0; [[nodiscard]] virtual uint8_t* GetBufferForMipLevel(int mipLevel, int face) = 0;
[[nodiscard]] virtual const uint8_t* GetBufferForMipLevel(int mipLevel, int face) const = 0; [[nodiscard]] virtual const uint8_t* GetBufferForMipLevel(int mipLevel, int face) const = 0;
[[nodiscard]] uint8_t* GetBufferForMipLevel(int mipLevel); [[nodiscard]] uint8_t* GetBufferForMipLevel(int mipLevel);
[[nodiscard]] const uint8_t* GetBufferForMipLevel(int mipLevel) const; [[nodiscard]] const uint8_t* GetBufferForMipLevel(int mipLevel) const;
[[nodiscard]] bool HasMipMaps() const; [[nodiscard]] bool HasMipMaps() const;
[[nodiscard]] virtual int GetMipMapCount() const = 0; [[nodiscard]] virtual int GetMipMapCount() const = 0;
}; };
class Texture2D : public Texture class Texture2D : public Texture
{ {
protected: protected:
unsigned m_width; unsigned m_width;
unsigned m_height; unsigned m_height;
public: public:
Texture2D(const ImageFormat* format, unsigned width, unsigned height); Texture2D(const ImageFormat* format, unsigned width, unsigned height);
Texture2D(const ImageFormat* format, unsigned width, unsigned height, bool mipMaps); Texture2D(const ImageFormat* format, unsigned width, unsigned height, bool mipMaps);
Texture2D(const Texture2D& other) = delete; Texture2D(const Texture2D& other) = delete;
Texture2D(Texture2D&& other) noexcept; Texture2D(Texture2D&& other) noexcept;
~Texture2D() override; ~Texture2D() override;
Texture2D& operator=(const Texture2D& other) = delete; Texture2D& operator=(const Texture2D& other) = delete;
Texture2D& operator=(Texture2D&& other) noexcept; Texture2D& operator=(Texture2D&& other) noexcept;
[[nodiscard]] TextureType GetTextureType() const override; [[nodiscard]] TextureType GetTextureType() const override;
[[nodiscard]] unsigned GetWidth() const override; [[nodiscard]] unsigned GetWidth() const override;
[[nodiscard]] unsigned GetHeight() const override; [[nodiscard]] unsigned GetHeight() const override;
[[nodiscard]] unsigned GetDepth() const override; [[nodiscard]] unsigned GetDepth() const override;
[[nodiscard]] int GetFaceCount() const override; [[nodiscard]] int GetFaceCount() const override;
[[nodiscard]] size_t GetSizeOfMipLevel(int mipLevel) const override; [[nodiscard]] size_t GetSizeOfMipLevel(int mipLevel) const override;
[[nodiscard]] uint8_t* GetBufferForMipLevel(int mipLevel, int face) override; [[nodiscard]] uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
[[nodiscard]] const uint8_t* GetBufferForMipLevel(int mipLevel, int face) const override; [[nodiscard]] const uint8_t* GetBufferForMipLevel(int mipLevel, int face) const override;
[[nodiscard]] int GetMipMapCount() const override; [[nodiscard]] int GetMipMapCount() const override;
}; };
class TextureCube final : public Texture2D class TextureCube final : public Texture2D
{ {
static const int FACE_COUNT; static const int FACE_COUNT;
public: public:
TextureCube(const ImageFormat* format, unsigned width, unsigned height); TextureCube(const ImageFormat* format, unsigned width, unsigned height);
TextureCube(const ImageFormat* format, unsigned width, unsigned height, bool mipMaps); TextureCube(const ImageFormat* format, unsigned width, unsigned height, bool mipMaps);
TextureCube(const TextureCube& other) = delete; TextureCube(const TextureCube& other) = delete;
TextureCube(TextureCube&& other) noexcept; TextureCube(TextureCube&& other) noexcept;
~TextureCube() override; ~TextureCube() override;
TextureCube& operator=(const TextureCube& other) = delete; TextureCube& operator=(const TextureCube& other) = delete;
TextureCube& operator=(TextureCube&& other) noexcept; TextureCube& operator=(TextureCube&& other) noexcept;
[[nodiscard]] TextureType GetTextureType() const override; [[nodiscard]] TextureType GetTextureType() const override;
[[nodiscard]] int GetFaceCount() const override; [[nodiscard]] int GetFaceCount() const override;
[[nodiscard]] uint8_t* GetBufferForMipLevel(int mipLevel, int face) override; [[nodiscard]] uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
[[nodiscard]] const uint8_t* GetBufferForMipLevel(int mipLevel, int face) const override; [[nodiscard]] const uint8_t* GetBufferForMipLevel(int mipLevel, int face) const override;
}; };
class Texture3D final : public Texture class Texture3D final : public Texture
{ {
unsigned m_width; unsigned m_width;
unsigned m_height; unsigned m_height;
unsigned m_depth; unsigned m_depth;
public: public:
Texture3D(const ImageFormat* format, unsigned width, unsigned height, unsigned depth); Texture3D(const ImageFormat* format, unsigned width, unsigned height, unsigned depth);
Texture3D(const ImageFormat* format, unsigned width, unsigned height, unsigned depth, bool mipMaps); Texture3D(const ImageFormat* format, unsigned width, unsigned height, unsigned depth, bool mipMaps);
Texture3D(const Texture3D& other) = delete; Texture3D(const Texture3D& other) = delete;
Texture3D(Texture3D&& other) noexcept; Texture3D(Texture3D&& other) noexcept;
~Texture3D() override; ~Texture3D() override;
Texture3D& operator=(const Texture3D& other) = delete; Texture3D& operator=(const Texture3D& other) = delete;
Texture3D& operator=(Texture3D&& other) noexcept; Texture3D& operator=(Texture3D&& other) noexcept;
[[nodiscard]] TextureType GetTextureType() const override; [[nodiscard]] TextureType GetTextureType() const override;
[[nodiscard]] unsigned GetWidth() const override; [[nodiscard]] unsigned GetWidth() const override;
[[nodiscard]] unsigned GetHeight() const override; [[nodiscard]] unsigned GetHeight() const override;
[[nodiscard]] unsigned GetDepth() const override; [[nodiscard]] unsigned GetDepth() const override;
[[nodiscard]] int GetFaceCount() const override; [[nodiscard]] int GetFaceCount() const override;
[[nodiscard]] size_t GetSizeOfMipLevel(int mipLevel) const override; [[nodiscard]] size_t GetSizeOfMipLevel(int mipLevel) const override;
[[nodiscard]] uint8_t* GetBufferForMipLevel(int mipLevel, int face) override; [[nodiscard]] uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
[[nodiscard]] const uint8_t* GetBufferForMipLevel(int mipLevel, int face) const override; [[nodiscard]] const uint8_t* GetBufferForMipLevel(int mipLevel, int face) const override;
[[nodiscard]] int GetMipMapCount() const override; [[nodiscard]] int GetMipMapCount() const override;
}; };
} // namespace image

View File

@@ -2,221 +2,224 @@
#include <cassert> #include <cassert>
constexpr uint64_t TextureConverter::Mask1(const unsigned length) namespace image
{ {
if (length >= sizeof(uint64_t) * 8) constexpr uint64_t TextureConverter::Mask1(const unsigned length)
return UINT64_MAX;
return UINT64_MAX >> (sizeof(uint64_t) * 8 - length);
}
void TextureConverter::SetPixelFunctions(const unsigned inBitCount, const unsigned outBitCount)
{
switch (inBitCount)
{ {
case 16: if (length >= sizeof(uint64_t) * 8)
m_read_pixel_func = [](const void* offset, unsigned bitCount) return UINT64_MAX;
{
return static_cast<uint64_t>(*static_cast<const uint16_t*>(offset));
};
break;
case 32: return UINT64_MAX >> (sizeof(uint64_t) * 8 - length);
m_read_pixel_func = [](const void* offset, unsigned bitCount) }
{
return static_cast<uint64_t>(*static_cast<const uint32_t*>(offset));
};
break;
case 64: void TextureConverter::SetPixelFunctions(const unsigned inBitCount, const unsigned outBitCount)
m_read_pixel_func = [](const void* offset, unsigned bitCount) {
switch (inBitCount)
{ {
return *static_cast<const uint64_t*>(offset); case 16:
};
break;
default:
if (inBitCount <= 64)
{
m_read_pixel_func = [](const void* offset, const unsigned bitCount)
{
uint64_t result = 0;
for (auto pixelOffset = 0u; pixelOffset < bitCount; pixelOffset += 8)
{
result |= (static_cast<uint64_t>(*(static_cast<const uint8_t*>(offset) + (pixelOffset / 8))) << pixelOffset);
}
return result;
};
}
else
{
assert(false);
m_read_pixel_func = [](const void* offset, unsigned bitCount) m_read_pixel_func = [](const void* offset, unsigned bitCount)
{ {
return 0ull; return static_cast<uint64_t>(*static_cast<const uint16_t*>(offset));
}; };
break;
case 32:
m_read_pixel_func = [](const void* offset, unsigned bitCount)
{
return static_cast<uint64_t>(*static_cast<const uint32_t*>(offset));
};
break;
case 64:
m_read_pixel_func = [](const void* offset, unsigned bitCount)
{
return *static_cast<const uint64_t*>(offset);
};
break;
default:
if (inBitCount <= 64)
{
m_read_pixel_func = [](const void* offset, const unsigned bitCount)
{
uint64_t result = 0;
for (auto pixelOffset = 0u; pixelOffset < bitCount; pixelOffset += 8)
{
result |= (static_cast<uint64_t>(*(static_cast<const uint8_t*>(offset) + (pixelOffset / 8))) << pixelOffset);
}
return result;
};
}
else
{
assert(false);
m_read_pixel_func = [](const void* offset, unsigned bitCount)
{
return 0ull;
};
}
break;
}
switch (outBitCount)
{
case 16:
m_write_pixel_func = [](void* offset, const uint64_t pixel, unsigned bitCount)
{
*static_cast<uint16_t*>(offset) = static_cast<uint16_t>(pixel);
};
break;
case 32:
m_write_pixel_func = [](void* offset, const uint64_t pixel, unsigned bitCount)
{
*static_cast<uint32_t*>(offset) = static_cast<uint32_t>(pixel);
};
break;
case 64:
m_write_pixel_func = [](void* offset, const uint64_t pixel, unsigned bitCount)
{
*static_cast<uint64_t*>(offset) = pixel;
};
break;
default:
if (inBitCount <= 64)
{
m_write_pixel_func = [](void* offset, const uint64_t pixel, const unsigned bitCount)
{
for (auto pixelOffset = 0u; pixelOffset < bitCount; pixelOffset += 8)
{
*(static_cast<uint8_t*>(offset) + (pixelOffset / 8)) = static_cast<uint8_t>(pixel >> pixelOffset);
}
};
}
else
{
assert(false);
m_write_pixel_func = [](void* offset, uint64_t pixel, unsigned bitCount) {};
}
break;
} }
break;
} }
switch (outBitCount) TextureConverter::TextureConverter(const Texture* inputTexture, const ImageFormat* targetFormat)
: m_input_texture(inputTexture),
m_output_texture(nullptr),
m_input_format(inputTexture->GetFormat()),
m_output_format(targetFormat)
{ {
case 16: }
m_write_pixel_func = [](void* offset, const uint64_t pixel, unsigned bitCount)
{
*static_cast<uint16_t*>(offset) = static_cast<uint16_t>(pixel);
};
break;
case 32: void TextureConverter::CreateOutputTexture()
m_write_pixel_func = [](void* offset, const uint64_t pixel, unsigned bitCount) {
switch (m_input_texture->GetTextureType())
{ {
*static_cast<uint32_t*>(offset) = static_cast<uint32_t>(pixel); case TextureType::T_2D:
}; m_output_texture =
break; std::make_unique<Texture2D>(m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(), m_input_texture->HasMipMaps());
break;
case 64: case TextureType::T_CUBE:
m_write_pixel_func = [](void* offset, const uint64_t pixel, unsigned bitCount) m_output_texture =
{ std::make_unique<TextureCube>(m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(), m_input_texture->HasMipMaps());
*static_cast<uint64_t*>(offset) = pixel; break;
};
break;
default: case TextureType::T_3D:
if (inBitCount <= 64) m_output_texture = std::make_unique<Texture3D>(
m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(), m_input_texture->GetDepth(), m_input_texture->HasMipMaps());
break;
default:
assert(false);
break;
}
m_output_texture->Allocate();
}
void TextureConverter::ReorderUnsignedToUnsigned() const
{
const auto* inputFormat = dynamic_cast<const ImageFormatUnsigned*>(m_input_format);
const auto* outputFormat = dynamic_cast<const ImageFormatUnsigned*>(m_output_format);
const auto mipCount = m_input_texture->HasMipMaps() ? m_input_texture->GetMipMapCount() : 1;
const auto rInputMask = inputFormat->HasR() ? Mask1(inputFormat->m_r_size) << inputFormat->m_r_offset : 0;
const auto gInputMask = inputFormat->HasG() ? Mask1(inputFormat->m_g_size) << inputFormat->m_g_offset : 0;
const auto bInputMask = inputFormat->HasB() ? Mask1(inputFormat->m_b_size) << inputFormat->m_b_offset : 0;
const auto aInputMask = inputFormat->HasA() ? Mask1(inputFormat->m_a_size) << inputFormat->m_a_offset : 0;
const bool rConvert = rInputMask != 0 && outputFormat->m_r_size > 0;
const bool gConvert = gInputMask != 0 && outputFormat->m_g_size > 0;
const bool bConvert = bInputMask != 0 && outputFormat->m_b_size > 0;
const bool aConvert = aInputMask != 0 && outputFormat->m_a_size > 0;
for (auto mipLevel = 0; mipLevel < mipCount; mipLevel++)
{ {
m_write_pixel_func = [](void* offset, const uint64_t pixel, const unsigned bitCount) const auto mipLevelSize = m_input_texture->GetSizeOfMipLevel(mipLevel) * m_input_texture->GetFaceCount();
const auto* inputBuffer = m_input_texture->GetBufferForMipLevel(mipLevel);
auto* outputBuffer = m_output_texture->GetBufferForMipLevel(mipLevel);
const auto inputBytePerPixel = inputFormat->m_bits_per_pixel / 8;
const auto outputBytePerPixel = outputFormat->m_bits_per_pixel / 8;
auto outputOffset = 0u;
for (auto inputOffset = 0u; inputOffset < mipLevelSize; inputOffset += inputBytePerPixel, outputOffset += outputBytePerPixel)
{ {
for (auto pixelOffset = 0u; pixelOffset < bitCount; pixelOffset += 8) uint64_t outPixel = 0;
{ const auto inPixel = m_read_pixel_func(&inputBuffer[inputOffset], inputFormat->m_bits_per_pixel);
*(static_cast<uint8_t*>(offset) + (pixelOffset / 8)) = static_cast<uint8_t>(pixel >> pixelOffset);
} if (rConvert)
}; outPixel |= (inPixel & rInputMask) >> inputFormat->m_r_offset << outputFormat->m_r_offset;
if (gConvert)
outPixel |= (inPixel & gInputMask) >> inputFormat->m_g_offset << outputFormat->m_g_offset;
if (bConvert)
outPixel |= (inPixel & bInputMask) >> inputFormat->m_b_offset << outputFormat->m_b_offset;
if (aConvert)
outPixel |= (inPixel & aInputMask) >> inputFormat->m_a_offset << outputFormat->m_a_offset;
m_write_pixel_func(&outputBuffer[outputOffset], outPixel, outputFormat->m_bits_per_pixel);
}
}
}
void TextureConverter::ConvertUnsignedToUnsigned()
{
const auto* inputFormat = dynamic_cast<const ImageFormatUnsigned*>(m_input_format);
const auto* outputFormat = dynamic_cast<const ImageFormatUnsigned*>(m_output_format);
assert(inputFormat->m_bits_per_pixel <= 64);
assert(outputFormat->m_bits_per_pixel <= 64);
SetPixelFunctions(inputFormat->m_bits_per_pixel, outputFormat->m_bits_per_pixel);
if (inputFormat->m_r_size == outputFormat->m_r_size && inputFormat->m_g_size == outputFormat->m_g_size
&& inputFormat->m_b_size == outputFormat->m_b_size && inputFormat->m_a_size == outputFormat->m_a_size)
{
ReorderUnsignedToUnsigned();
} }
else else
{ {
// Unsupported as of now
assert(false); assert(false);
m_write_pixel_func = [](void* offset, uint64_t pixel, unsigned bitCount) {};
} }
break;
}
}
TextureConverter::TextureConverter(const Texture* inputTexture, const ImageFormat* targetFormat)
: m_input_texture(inputTexture),
m_output_texture(nullptr),
m_input_format(inputTexture->GetFormat()),
m_output_format(targetFormat)
{
}
void TextureConverter::CreateOutputTexture()
{
switch (m_input_texture->GetTextureType())
{
case TextureType::T_2D:
m_output_texture =
std::make_unique<Texture2D>(m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(), m_input_texture->HasMipMaps());
break;
case TextureType::T_CUBE:
m_output_texture =
std::make_unique<TextureCube>(m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(), m_input_texture->HasMipMaps());
break;
case TextureType::T_3D:
m_output_texture = std::make_unique<Texture3D>(
m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(), m_input_texture->GetDepth(), m_input_texture->HasMipMaps());
break;
default:
assert(false);
break;
} }
m_output_texture->Allocate(); std::unique_ptr<Texture> TextureConverter::Convert()
}
void TextureConverter::ReorderUnsignedToUnsigned() const
{
const auto* inputFormat = dynamic_cast<const ImageFormatUnsigned*>(m_input_format);
const auto* outputFormat = dynamic_cast<const ImageFormatUnsigned*>(m_output_format);
const auto mipCount = m_input_texture->HasMipMaps() ? m_input_texture->GetMipMapCount() : 1;
const auto rInputMask = inputFormat->HasR() ? Mask1(inputFormat->m_r_size) << inputFormat->m_r_offset : 0;
const auto gInputMask = inputFormat->HasG() ? Mask1(inputFormat->m_g_size) << inputFormat->m_g_offset : 0;
const auto bInputMask = inputFormat->HasB() ? Mask1(inputFormat->m_b_size) << inputFormat->m_b_offset : 0;
const auto aInputMask = inputFormat->HasA() ? Mask1(inputFormat->m_a_size) << inputFormat->m_a_offset : 0;
const bool rConvert = rInputMask != 0 && outputFormat->m_r_size > 0;
const bool gConvert = gInputMask != 0 && outputFormat->m_g_size > 0;
const bool bConvert = bInputMask != 0 && outputFormat->m_b_size > 0;
const bool aConvert = aInputMask != 0 && outputFormat->m_a_size > 0;
for (auto mipLevel = 0; mipLevel < mipCount; mipLevel++)
{ {
const auto mipLevelSize = m_input_texture->GetSizeOfMipLevel(mipLevel) * m_input_texture->GetFaceCount(); CreateOutputTexture();
const auto* inputBuffer = m_input_texture->GetBufferForMipLevel(mipLevel);
auto* outputBuffer = m_output_texture->GetBufferForMipLevel(mipLevel);
const auto inputBytePerPixel = inputFormat->m_bits_per_pixel / 8; if (m_input_format->GetType() == ImageFormatType::UNSIGNED && m_output_format->GetType() == ImageFormatType::UNSIGNED)
const auto outputBytePerPixel = outputFormat->m_bits_per_pixel / 8;
auto outputOffset = 0u;
for (auto inputOffset = 0u; inputOffset < mipLevelSize; inputOffset += inputBytePerPixel, outputOffset += outputBytePerPixel)
{ {
uint64_t outPixel = 0; ConvertUnsignedToUnsigned();
const auto inPixel = m_read_pixel_func(&inputBuffer[inputOffset], inputFormat->m_bits_per_pixel);
if (rConvert)
outPixel |= (inPixel & rInputMask) >> inputFormat->m_r_offset << outputFormat->m_r_offset;
if (gConvert)
outPixel |= (inPixel & gInputMask) >> inputFormat->m_g_offset << outputFormat->m_g_offset;
if (bConvert)
outPixel |= (inPixel & bInputMask) >> inputFormat->m_b_offset << outputFormat->m_b_offset;
if (aConvert)
outPixel |= (inPixel & aInputMask) >> inputFormat->m_a_offset << outputFormat->m_a_offset;
m_write_pixel_func(&outputBuffer[outputOffset], outPixel, outputFormat->m_bits_per_pixel);
} }
else
{
// Unsupported as of now
assert(false);
}
return std::move(m_output_texture);
} }
} } // namespace image
void TextureConverter::ConvertUnsignedToUnsigned()
{
const auto* inputFormat = dynamic_cast<const ImageFormatUnsigned*>(m_input_format);
const auto* outputFormat = dynamic_cast<const ImageFormatUnsigned*>(m_output_format);
assert(inputFormat->m_bits_per_pixel <= 64);
assert(outputFormat->m_bits_per_pixel <= 64);
SetPixelFunctions(inputFormat->m_bits_per_pixel, outputFormat->m_bits_per_pixel);
if (inputFormat->m_r_size == outputFormat->m_r_size && inputFormat->m_g_size == outputFormat->m_g_size && inputFormat->m_b_size == outputFormat->m_b_size
&& inputFormat->m_a_size == outputFormat->m_a_size)
{
ReorderUnsignedToUnsigned();
}
else
{
// Unsupported as of now
assert(false);
}
}
std::unique_ptr<Texture> TextureConverter::Convert()
{
CreateOutputTexture();
if (m_input_format->GetType() == ImageFormatType::UNSIGNED && m_output_format->GetType() == ImageFormatType::UNSIGNED)
{
ConvertUnsignedToUnsigned();
}
else
{
// Unsupported as of now
assert(false);
}
return std::move(m_output_texture);
}

View File

@@ -5,27 +5,30 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
class TextureConverter namespace image
{ {
public: class TextureConverter
TextureConverter(const Texture* inputTexture, const ImageFormat* targetFormat); {
public:
TextureConverter(const Texture* inputTexture, const ImageFormat* targetFormat);
std::unique_ptr<Texture> Convert(); std::unique_ptr<Texture> Convert();
private: private:
static constexpr uint64_t Mask1(unsigned length); static constexpr uint64_t Mask1(unsigned length);
void SetPixelFunctions(unsigned inBitCount, unsigned outBitCount); void SetPixelFunctions(unsigned inBitCount, unsigned outBitCount);
void CreateOutputTexture(); void CreateOutputTexture();
void ReorderUnsignedToUnsigned() const; void ReorderUnsignedToUnsigned() const;
void ConvertUnsignedToUnsigned(); void ConvertUnsignedToUnsigned();
std::function<uint64_t(const void* offset, unsigned bitCount)> m_read_pixel_func; std::function<uint64_t(const void* offset, unsigned bitCount)> m_read_pixel_func;
std::function<void(void* offset, uint64_t pixel, unsigned bitCount)> m_write_pixel_func; std::function<void(void* offset, uint64_t pixel, unsigned bitCount)> m_write_pixel_func;
const Texture* m_input_texture; const Texture* m_input_texture;
std::unique_ptr<Texture> m_output_texture; std::unique_ptr<Texture> m_output_texture;
const ImageFormat* m_input_format; const ImageFormat* m_input_format;
const ImageFormat* m_output_format; const ImageFormat* m_output_format;
}; };
} // namespace image

View File

@@ -12,6 +12,7 @@
#include <iostream> #include <iostream>
using namespace IW3; using namespace IW3;
using namespace image;
namespace namespace
{ {
@@ -38,7 +39,7 @@ namespace
if (!file.IsOpen()) if (!file.IsOpen())
return AssetCreationResult::NoAction(); return AssetCreationResult::NoAction();
const auto texture = dds::LoadDds(*file.m_stream); const auto texture = image::LoadDds(*file.m_stream);
if (!texture) if (!texture)
{ {
con::error("Failed to load dds file for image asset \"{}\"", assetName); con::error("Failed to load dds file for image asset \"{}\"", assetName);
@@ -91,11 +92,11 @@ namespace
loadDef->levelCount = static_cast<char>(mipCount); loadDef->levelCount = static_cast<char>(mipCount);
loadDef->flags = 0; loadDef->flags = 0;
if (!texture->HasMipMaps()) if (!texture->HasMipMaps())
loadDef->flags |= iwi6::IMG_FLAG_NOMIPMAPS; loadDef->flags |= image::iwi6::IMG_FLAG_NOMIPMAPS;
if (texture->GetTextureType() == TextureType::T_CUBE) if (texture->GetTextureType() == TextureType::T_CUBE)
loadDef->flags |= iwi6::IMG_FLAG_CUBEMAP; loadDef->flags |= image::iwi6::IMG_FLAG_CUBEMAP;
if (texture->GetTextureType() == TextureType::T_3D) if (texture->GetTextureType() == TextureType::T_3D)
loadDef->flags |= iwi6::IMG_FLAG_VOLMAP; loadDef->flags |= image::iwi6::IMG_FLAG_VOLMAP;
loadDef->dimensions[0] = image->width; loadDef->dimensions[0] = image->width;
loadDef->dimensions[1] = image->height; loadDef->dimensions[1] = image->height;
loadDef->dimensions[2] = image->depth; loadDef->dimensions[2] = image->depth;

View File

@@ -37,7 +37,7 @@ namespace
file.m_stream->read(fileData.get(), fileSize); file.m_stream->read(fileData.get(), fileSize);
std::istringstream ss(std::string(fileData.get(), fileSize)); std::istringstream ss(std::string(fileData.get(), fileSize));
const auto texture = iwi::LoadIwi(ss); const auto texture = image::LoadIwi(ss);
if (!texture) if (!texture)
{ {
con::error("Failed to load texture from: {}", fileName); con::error("Failed to load texture from: {}", fileName);

View File

@@ -38,7 +38,7 @@ namespace
const auto dataHash = static_cast<unsigned>(crc32(0u, reinterpret_cast<const Bytef*>(fileData.get()), static_cast<unsigned>(fileSize))); const auto dataHash = static_cast<unsigned>(crc32(0u, reinterpret_cast<const Bytef*>(fileData.get()), static_cast<unsigned>(fileSize)));
std::istringstream ss(std::string(fileData.get(), fileSize)); std::istringstream ss(std::string(fileData.get(), fileSize));
const auto texture = iwi::LoadIwi(ss); const auto texture = image::LoadIwi(ss);
if (!texture) if (!texture)
{ {
con::error("Failed to load texture from: {}", fileName); con::error("Failed to load texture from: {}", fileName);

View File

@@ -0,0 +1,15 @@
#include "ImageLoaderCommon.h"
namespace image
{
std::optional<AssetCreationResult> CommonImageLoaderResult::GetResultIfCancelled() const
{
if (m_failure)
return AssetCreationResult::Failure();
if (!m_texture)
return AssetCreationResult::NoAction();
return std::nullopt;
}
} // namespace image

View File

@@ -0,0 +1,23 @@
#pragma once
#include "Asset/AssetCreationResult.h"
#include "Image/IwiTypes.h"
#include "Image/Texture.h"
#include <memory>
#include <optional>
#include <string>
namespace image
{
struct CommonImageLoaderResult
{
std::optional<AssetCreationResult> GetResultIfCancelled() const;
bool m_failure;
std::string m_iwi_path;
std::unique_ptr<Texture> m_texture;
};
CommonImageLoaderResult LoadImageCommon();
} // namespace image

View File

@@ -16,6 +16,7 @@
#include <format> #include <format>
using namespace IW3; using namespace IW3;
using namespace image;
namespace namespace
{ {
@@ -26,15 +27,15 @@ namespace
const auto& loadDef = *image.texture.loadDef; const auto& loadDef = *image.texture.loadDef;
textureLoader.Width(loadDef.dimensions[0]).Height(loadDef.dimensions[1]).Depth(loadDef.dimensions[2]); textureLoader.Width(loadDef.dimensions[0]).Height(loadDef.dimensions[1]).Depth(loadDef.dimensions[2]);
if (loadDef.flags & iwi6::IMG_FLAG_VOLMAP) if (loadDef.flags & image::iwi6::IMG_FLAG_VOLMAP)
textureLoader.Type(TextureType::T_3D); textureLoader.Type(TextureType::T_3D);
else if (loadDef.flags & iwi6::IMG_FLAG_CUBEMAP) else if (loadDef.flags & image::iwi6::IMG_FLAG_CUBEMAP)
textureLoader.Type(TextureType::T_CUBE); textureLoader.Type(TextureType::T_CUBE);
else else
textureLoader.Type(TextureType::T_2D); textureLoader.Type(TextureType::T_2D);
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format)); textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format));
textureLoader.HasMipMaps(!(loadDef.flags & iwi6::IMG_FLAG_NOMIPMAPS)); textureLoader.HasMipMaps(!(loadDef.flags & image::iwi6::IMG_FLAG_NOMIPMAPS));
return textureLoader.LoadTexture(loadDef.data); return textureLoader.LoadTexture(loadDef.data);
} }
@@ -48,7 +49,7 @@ namespace
return nullptr; return nullptr;
} }
return iwi::LoadIwi(*filePathImage.m_stream); return image::LoadIwi(*filePathImage.m_stream);
} }
std::unique_ptr<Texture> LoadImageData(ISearchPath& searchPath, const GfxImage& image) std::unique_ptr<Texture> LoadImageData(ISearchPath& searchPath, const GfxImage& image)

View File

@@ -2,7 +2,7 @@
#include "Dumping/AbstractAssetDumper.h" #include "Dumping/AbstractAssetDumper.h"
#include "Game/IW3/IW3.h" #include "Game/IW3/IW3.h"
#include "Image/IImageWriter.h" #include "Image/ImageWriter.h"
#include <memory> #include <memory>
@@ -17,6 +17,6 @@ namespace image
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW3::AssetImage::Type>& asset) override; void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW3::AssetImage::Type>& asset) override;
private: private:
std::unique_ptr<IImageWriter> m_writer; std::unique_ptr<ImageWriter> m_writer;
}; };
} // namespace image } // namespace image

View File

@@ -13,6 +13,7 @@
#include <format> #include <format>
using namespace IW4; using namespace IW4;
using namespace image;
namespace namespace
{ {
@@ -23,15 +24,15 @@ namespace
const auto& loadDef = *image.texture.loadDef; const auto& loadDef = *image.texture.loadDef;
textureLoader.Width(image.width).Height(image.height).Depth(image.depth); textureLoader.Width(image.width).Height(image.height).Depth(image.depth);
if ((loadDef.flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_3D) if ((loadDef.flags & image::iwi8::IMG_FLAG_MAPTYPE_MASK) == image::iwi8::IMG_FLAG_MAPTYPE_3D)
textureLoader.Type(TextureType::T_3D); textureLoader.Type(TextureType::T_3D);
else if ((loadDef.flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_CUBE) else if ((loadDef.flags & image::iwi8::IMG_FLAG_MAPTYPE_MASK) == image::iwi8::IMG_FLAG_MAPTYPE_CUBE)
textureLoader.Type(TextureType::T_CUBE); textureLoader.Type(TextureType::T_CUBE);
else else
textureLoader.Type(TextureType::T_2D); textureLoader.Type(TextureType::T_2D);
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format)); textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format));
textureLoader.HasMipMaps(!(loadDef.flags & iwi8::IMG_FLAG_NOMIPMAPS)); textureLoader.HasMipMaps(!(loadDef.flags & image::iwi8::IMG_FLAG_NOMIPMAPS));
return textureLoader.LoadTexture(loadDef.data); return textureLoader.LoadTexture(loadDef.data);
} }
@@ -45,7 +46,7 @@ namespace
return nullptr; return nullptr;
} }
return iwi::LoadIwi(*filePathImage.m_stream); return image::LoadIwi(*filePathImage.m_stream);
} }
std::unique_ptr<Texture> LoadImageData(ISearchPath& searchPath, const GfxImage& image) std::unique_ptr<Texture> LoadImageData(ISearchPath& searchPath, const GfxImage& image)

View File

@@ -2,7 +2,7 @@
#include "Dumping/AbstractAssetDumper.h" #include "Dumping/AbstractAssetDumper.h"
#include "Game/IW4/IW4.h" #include "Game/IW4/IW4.h"
#include "Image/IImageWriter.h" #include "Image/ImageWriter.h"
#include <memory> #include <memory>
@@ -17,6 +17,6 @@ namespace image
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW4::AssetImage::Type>& asset) override; void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW4::AssetImage::Type>& asset) override;
private: private:
std::unique_ptr<IImageWriter> m_writer; std::unique_ptr<ImageWriter> m_writer;
}; };
} // namespace image } // namespace image

View File

@@ -13,6 +13,7 @@
#include <format> #include <format>
using namespace IW5; using namespace IW5;
using namespace image;
namespace namespace
{ {
@@ -24,15 +25,15 @@ namespace
textureLoader.Width(image.width).Height(image.height).Depth(image.depth); textureLoader.Width(image.width).Height(image.height).Depth(image.depth);
if ((loadDef.flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_3D) if ((loadDef.flags & image::iwi8::IMG_FLAG_MAPTYPE_MASK) == image::iwi8::IMG_FLAG_MAPTYPE_3D)
textureLoader.Type(TextureType::T_3D); textureLoader.Type(TextureType::T_3D);
else if ((loadDef.flags & iwi8::IMG_FLAG_MAPTYPE_MASK) == iwi8::IMG_FLAG_MAPTYPE_CUBE) else if ((loadDef.flags & image::iwi8::IMG_FLAG_MAPTYPE_MASK) == image::iwi8::IMG_FLAG_MAPTYPE_CUBE)
textureLoader.Type(TextureType::T_CUBE); textureLoader.Type(TextureType::T_CUBE);
else else
textureLoader.Type(TextureType::T_2D); textureLoader.Type(TextureType::T_2D);
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format)); textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format));
textureLoader.HasMipMaps(!(loadDef.flags & iwi8::IMG_FLAG_NOMIPMAPS)); textureLoader.HasMipMaps(!(loadDef.flags & image::iwi8::IMG_FLAG_NOMIPMAPS));
return textureLoader.LoadTexture(loadDef.data); return textureLoader.LoadTexture(loadDef.data);
} }
@@ -46,7 +47,7 @@ namespace
return nullptr; return nullptr;
} }
return iwi::LoadIwi(*filePathImage.m_stream); return image::LoadIwi(*filePathImage.m_stream);
} }
std::unique_ptr<Texture> LoadImageData(ISearchPath& searchPath, const GfxImage& image) std::unique_ptr<Texture> LoadImageData(ISearchPath& searchPath, const GfxImage& image)

View File

@@ -2,7 +2,7 @@
#include "Dumping/AbstractAssetDumper.h" #include "Dumping/AbstractAssetDumper.h"
#include "Game/IW5/IW5.h" #include "Game/IW5/IW5.h"
#include "Image/IImageWriter.h" #include "Image/ImageWriter.h"
#include <memory> #include <memory>
@@ -17,6 +17,6 @@ namespace image
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::AssetImage::Type>& asset) override; void DumpAsset(AssetDumpingContext& context, const XAssetInfo<IW5::AssetImage::Type>& asset) override;
private: private:
std::unique_ptr<IImageWriter> m_writer; std::unique_ptr<ImageWriter> m_writer;
}; };
} // namespace image } // namespace image

View File

@@ -13,6 +13,7 @@
#include <format> #include <format>
using namespace T5; using namespace T5;
using namespace image;
namespace namespace
{ {
@@ -23,15 +24,15 @@ namespace
const auto& loadDef = *image.texture.loadDef; const auto& loadDef = *image.texture.loadDef;
textureLoader.Width(image.width).Height(image.height).Depth(image.depth); textureLoader.Width(image.width).Height(image.height).Depth(image.depth);
if (loadDef.flags & iwi13::IMG_FLAG_VOLMAP) if (loadDef.flags & image::iwi13::IMG_FLAG_VOLMAP)
textureLoader.Type(TextureType::T_3D); textureLoader.Type(TextureType::T_3D);
else if (loadDef.flags & iwi13::IMG_FLAG_CUBEMAP) else if (loadDef.flags & image::iwi13::IMG_FLAG_CUBEMAP)
textureLoader.Type(TextureType::T_CUBE); textureLoader.Type(TextureType::T_CUBE);
else else
textureLoader.Type(TextureType::T_2D); textureLoader.Type(TextureType::T_2D);
textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format)); textureLoader.Format(static_cast<oat::D3DFORMAT>(loadDef.format));
textureLoader.HasMipMaps(!(loadDef.flags & iwi13::IMG_FLAG_NOMIPMAPS)); textureLoader.HasMipMaps(!(loadDef.flags & image::iwi13::IMG_FLAG_NOMIPMAPS));
return textureLoader.LoadTexture(loadDef.data); return textureLoader.LoadTexture(loadDef.data);
} }
@@ -45,7 +46,7 @@ namespace
return nullptr; return nullptr;
} }
return iwi::LoadIwi(*filePathImage.m_stream); return image::LoadIwi(*filePathImage.m_stream);
} }
std::unique_ptr<Texture> LoadImageData(ISearchPath& searchPath, const GfxImage& image) std::unique_ptr<Texture> LoadImageData(ISearchPath& searchPath, const GfxImage& image)

View File

@@ -2,7 +2,7 @@
#include "Dumping/AbstractAssetDumper.h" #include "Dumping/AbstractAssetDumper.h"
#include "Game/T5/T5.h" #include "Game/T5/T5.h"
#include "Image/IImageWriter.h" #include "Image/ImageWriter.h"
#include <memory> #include <memory>
@@ -17,6 +17,6 @@ namespace image
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<T5::AssetImage::Type>& asset) override; void DumpAsset(AssetDumpingContext& context, const XAssetInfo<T5::AssetImage::Type>& asset) override;
private: private:
std::unique_ptr<IImageWriter> m_writer; std::unique_ptr<ImageWriter> m_writer;
}; };
} // namespace image } // namespace image

View File

@@ -14,6 +14,7 @@
#include <format> #include <format>
using namespace T6; using namespace T6;
using namespace image;
namespace namespace
{ {
@@ -24,15 +25,15 @@ namespace
const auto& loadDef = *image.texture.loadDef; const auto& loadDef = *image.texture.loadDef;
textureLoader.Width(image.width).Height(image.height).Depth(image.depth); textureLoader.Width(image.width).Height(image.height).Depth(image.depth);
if (loadDef.flags & iwi27::IMG_FLAG_VOLMAP) if (loadDef.flags & image::iwi27::IMG_FLAG_VOLMAP)
textureLoader.Type(TextureType::T_3D); textureLoader.Type(TextureType::T_3D);
else if (loadDef.flags & iwi27::IMG_FLAG_CUBEMAP) else if (loadDef.flags & image::iwi27::IMG_FLAG_CUBEMAP)
textureLoader.Type(TextureType::T_CUBE); textureLoader.Type(TextureType::T_CUBE);
else else
textureLoader.Type(TextureType::T_2D); textureLoader.Type(TextureType::T_2D);
textureLoader.Format(static_cast<oat::DXGI_FORMAT>(loadDef.format)); textureLoader.Format(static_cast<oat::DXGI_FORMAT>(loadDef.format));
textureLoader.HasMipMaps(!(loadDef.flags & iwi27::IMG_FLAG_NOMIPMAPS)); textureLoader.HasMipMaps(!(loadDef.flags & image::iwi27::IMG_FLAG_NOMIPMAPS));
return textureLoader.LoadTexture(loadDef.data); return textureLoader.LoadTexture(loadDef.data);
} }
@@ -46,7 +47,7 @@ namespace
if (ipakStream) if (ipakStream)
{ {
auto loadedTexture = iwi::LoadIwi(*ipakStream); auto loadedTexture = image::LoadIwi(*ipakStream);
ipakStream->close(); ipakStream->close();
if (loadedTexture != nullptr) if (loadedTexture != nullptr)
@@ -63,7 +64,7 @@ namespace
return nullptr; return nullptr;
} }
return iwi::LoadIwi(*filePathImage.m_stream); return image::LoadIwi(*filePathImage.m_stream);
} }
std::unique_ptr<Texture> LoadImageData(ISearchPath& searchPath, const GfxImage& image) std::unique_ptr<Texture> LoadImageData(ISearchPath& searchPath, const GfxImage& image)

View File

@@ -2,7 +2,7 @@
#include "Dumping/AbstractAssetDumper.h" #include "Dumping/AbstractAssetDumper.h"
#include "Game/T6/T6.h" #include "Game/T6/T6.h"
#include "Image/IImageWriter.h" #include "Image/ImageWriter.h"
#include <memory> #include <memory>
@@ -17,6 +17,6 @@ namespace image
void DumpAsset(AssetDumpingContext& context, const XAssetInfo<T6::AssetImage::Type>& asset) override; void DumpAsset(AssetDumpingContext& context, const XAssetInfo<T6::AssetImage::Type>& asset) override;
private: private:
std::unique_ptr<IImageWriter> m_writer; std::unique_ptr<ImageWriter> m_writer;
}; };
} // namespace image } // namespace image