ObjWriting: Implement writing textures as DDS files

This commit is contained in:
Jan 2020-02-22 01:34:27 +01:00
parent 000022afe9
commit 5ef1e585c6
7 changed files with 536 additions and 23 deletions

View File

@ -0,0 +1,107 @@
#pragma once
#include <cstdint>
#include <dxgiformat.h>
namespace dds
{
constexpr uint32_t MakeFourCc(const char c0, const char c1, const char c2, const char c3)
{
return static_cast<uint32_t>(c0)
| static_cast<uint32_t>(c1) << 8
| static_cast<uint32_t>(c2) << 16
| static_cast<uint32_t>(c3) << 24;
}
enum DDP_FLAGS
{
DDPF_ALPHAPIXELS = 0x1,
DDPF_ALPHA = 0x2,
DDPF_FOURCC = 0x4,
DDPF_RGB = 0x40,
DDPF_YUV = 0x200,
DDPF_LUMINANCE = 0x20000
};
struct DDS_PIXELFORMAT
{
uint32_t dwSize;
uint32_t dwFlags;
uint32_t dwFourCC;
uint32_t dwRGBBitCount;
uint32_t dwRBitMask;
uint32_t dwGBitMask;
uint32_t dwBBitMask;
uint32_t dwABitMask;
};
enum DDS_HEADER_FLAGS
{
DDSD_CAPS = 0x1,
DDSD_HEIGHT = 0x2,
DDSD_WIDTH = 0x4,
DDSD_PITCH = 0x8,
DDSD_PIXELFORMAT = 0x1000,
DDSD_MIPMAPCOUNT = 0x20000,
DDSD_LINEARSIZE = 0x80000,
DDSD_DEPTH = 0x800000,
};
enum DDS_HEADER_CAPS
{
DDSCAPS_COMPLEX = 0x8,
DDSCAPS_TEXTURE = 0x1000,
DDSCAPS_MIPMAP = 0x400000,
};
enum DDS_HEADER_CAPS2
{
DDSCAPS2_CUBEMAP = 0x200,
DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
DDSCAPS2_VOLUME = 0x200000,
};
struct DDS_HEADER
{
uint32_t dwSize;
uint32_t dwFlags;
uint32_t dwHeight;
uint32_t dwWidth;
uint32_t dwPitchOrLinearSize;
uint32_t dwDepth;
uint32_t dwMipMapCount;
uint32_t dwReserved1[11];
DDS_PIXELFORMAT ddspf;
uint32_t dwCaps;
uint32_t dwCaps2;
uint32_t dwCaps3;
uint32_t dwCaps4;
uint32_t dwReserved2;
};
enum DDS_DIMENSION
{
DDS_DIMENSION_TEXTURE1D = 0x2,
DDS_DIMENSION_TEXTURE2D,
DDS_DIMENSION_TEXTURE3D
};
enum DDS_RESOURCE_MISC
{
DDS_RESOURCE_MISC_TEXTURECUBE = 0x4
};
struct DDS_HEADER_DXT10
{
DXGI_FORMAT dxgiFormat;
DDS_DIMENSION resourceDimension;
uint32_t miscFlag;
uint32_t arraySize;
uint32_t miscFlags2;
};
}

View File

@ -18,12 +18,28 @@ DXGI_FORMAT ImageFormat::GetDxgiFormat() const
}
ImageFormatUnsigned::ImageFormatUnsigned(const ImageFormatId id, const DXGI_FORMAT dxgiFormat,
const unsigned bitPerPixel, const unsigned rOffset, const unsigned rSize,
const unsigned bitsPerPixel, const unsigned rOffset, const unsigned rSize,
const unsigned gOffset, const unsigned gSize, const unsigned bOffset,
const unsigned bSize, const unsigned aOffset, const unsigned aSize)
: ImageFormat(id, dxgiFormat)
{
m_bit_per_pixel = bitPerPixel;
m_bits_per_pixel = bitsPerPixel;
m_r_offset = rOffset;
m_r_size = rSize;
m_r_mask = (UINT64_MAX << rOffset) & ~(UINT64_MAX << (rOffset + rSize));
m_g_offset = gOffset;
m_g_size = gSize;
m_g_mask = (UINT64_MAX << gOffset) & ~(UINT64_MAX << (gOffset + gSize));
m_b_offset = bOffset;
m_b_size = bSize;
m_b_mask = (UINT64_MAX << bOffset) & ~(UINT64_MAX << (bOffset + bSize));
m_a_offset = aOffset;
m_a_size = aSize;
m_a_mask = (UINT64_MAX << aOffset) & ~(UINT64_MAX << (aOffset + aSize));
}
ImageFormatType ImageFormatUnsigned::GetType() const
@ -45,7 +61,12 @@ size_t ImageFormatUnsigned::GetSizeOfMipLevel(const unsigned mipLevel, const uns
if (mipDepth == 0)
mipDepth = 1;
return mipWidth * mipHeight * mipDepth * m_bit_per_pixel / 8;
return mipWidth * mipHeight * mipDepth * m_bits_per_pixel / 8;
}
size_t ImageFormatUnsigned::GetPitch(const unsigned width) const
{
return (width * m_bits_per_pixel + 7) / 8;
}
ImageFormatBlockCompressed::ImageFormatBlockCompressed(const ImageFormatId id, const DXGI_FORMAT dxgiFormat,
@ -82,6 +103,11 @@ size_t ImageFormatBlockCompressed::GetSizeOfMipLevel(const unsigned mipLevel, co
return blockCount * m_bits_per_block / 8;
}
size_t ImageFormatBlockCompressed::GetPitch(const unsigned width) const
{
return (width + m_block_size - 1) / m_block_size * (m_bits_per_block / 8);
}
const ImageFormatUnsigned ImageFormat::FORMAT_R8_G8_B8(ImageFormatId::R8_G8_B8, DXGI_FORMAT_UNKNOWN,
24, 0, 8, 8, 8, 16, 8, 0, 0);
const ImageFormatUnsigned ImageFormat::FORMAT_R8_G8_B8_A8(ImageFormatId::R8_G8_B8_A8, DXGI_FORMAT_R8G8B8A8_UNORM,

View File

@ -1,5 +1,6 @@
#pragma once
#include <cstdint>
#include <dxgiformat.h>
enum class ImageFormatId
@ -42,6 +43,7 @@ public:
virtual ImageFormatType GetType() const = 0;
virtual size_t GetSizeOfMipLevel(unsigned mipLevel, unsigned width, unsigned height, unsigned depth) const = 0;
virtual size_t GetPitch(unsigned width) const = 0;
static const ImageFormatUnsigned FORMAT_R8_G8_B8;
static const ImageFormatUnsigned FORMAT_R8_G8_B8_A8;
@ -56,25 +58,39 @@ public:
class ImageFormatUnsigned final : public ImageFormat
{
unsigned m_bit_per_pixel;
public:
ImageFormatUnsigned(ImageFormatId id, DXGI_FORMAT dxgiFormat, unsigned bitPerPixel, unsigned rOffset,
unsigned m_bits_per_pixel;
unsigned m_r_offset;
unsigned m_r_size;
uint64_t m_r_mask;
unsigned m_g_offset;
unsigned m_g_size;
uint64_t m_g_mask;
unsigned m_b_offset;
unsigned m_b_size;
uint64_t m_b_mask;
unsigned m_a_offset;
unsigned m_a_size;
uint64_t m_a_mask;
ImageFormatUnsigned(ImageFormatId id, DXGI_FORMAT dxgiFormat, unsigned bitsPerPixel, unsigned rOffset,
unsigned rSize, unsigned gOffset, unsigned gSize, unsigned bOffset, unsigned bSize,
unsigned aOffset, unsigned aSize);
ImageFormatType GetType() const override;
size_t GetSizeOfMipLevel(unsigned mipLevel, unsigned width, unsigned height, unsigned depth) const override;
size_t GetPitch(unsigned width) const override;
};
class ImageFormatBlockCompressed final : public ImageFormat
{
public:
unsigned m_block_size;
unsigned m_bits_per_block;
public:
ImageFormatBlockCompressed(ImageFormatId id, DXGI_FORMAT dxgiFormat, unsigned blockSize, unsigned bitsPerBlock);
ImageFormatType GetType() const override;
size_t GetSizeOfMipLevel(unsigned mipLevel, unsigned width, unsigned height, unsigned depth) const override;
size_t GetPitch(unsigned width) const override;
};

View File

@ -50,7 +50,7 @@ void Texture::Allocate()
for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++)
{
storageRequirement += GetSizeOfMipLevel(currentMipLevel);
storageRequirement += GetSizeOfMipLevel(currentMipLevel) * GetFaceCount();
}
if (storageRequirement > 0)
@ -70,6 +70,11 @@ bool Texture::HasMipMaps() const
return m_has_mip_maps;
}
uint8_t* Texture::GetBufferForMipLevel(const int mipLevel)
{
return GetBufferForMipLevel(mipLevel, 0);
}
// ==============================================
// ================ Texture2D ===================
// ==============================================
@ -106,6 +111,11 @@ Texture2D& Texture2D::operator=(Texture2D&& other) noexcept
return *this;
}
Texture::Type Texture2D::GetType() const
{
return Type::TYPE_2D;
}
unsigned Texture2D::GetWidth() const
{
return m_width;
@ -116,6 +126,16 @@ 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);
@ -136,15 +156,19 @@ int Texture2D::GetMipMapCount() const
return mipMapCount;
}
uint8_t* Texture2D::GetBufferForMipLevel(const int mipLevel)
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;
@ -189,9 +213,40 @@ TextureCube& TextureCube::operator=(TextureCube&& other) noexcept
return *this;
}
size_t TextureCube::GetSizeOfMipLevel(const int mipLevel) const
Texture::Type TextureCube::GetType() const
{
return m_format->GetSizeOfMipLevel(mipLevel, m_width, m_height, 1) * FACE_COUNT;
return Type::TYPE_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];
}
// ==============================================
@ -235,6 +290,11 @@ Texture3D& Texture3D::operator=(Texture3D&& other) noexcept
return *this;
}
Texture::Type Texture3D::GetType() const
{
return Type::TYPE_3D;
}
unsigned Texture3D::GetWidth() const
{
return m_width;
@ -250,6 +310,11 @@ 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);
@ -270,15 +335,19 @@ int Texture3D::GetMipMapCount() const
return mipMapCount;
}
uint8_t* Texture3D::GetBufferForMipLevel(const int mipLevel)
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;

View File

@ -4,6 +4,14 @@
class Texture
{
public:
enum class Type
{
TYPE_2D,
TYPE_CUBE,
TYPE_3D
};
protected:
const ImageFormat* m_format;
bool m_has_mip_maps;
@ -21,12 +29,19 @@ public:
Texture& operator=(const Texture& other) = delete;
const ImageFormat* GetFormat() const;
virtual Type GetType() const = 0;
virtual unsigned GetWidth() const = 0;
virtual unsigned GetHeight() const = 0;
virtual unsigned GetDepth() const = 0;
virtual int GetFaceCount() const = 0;
void Allocate();
bool Empty() const;
virtual size_t GetSizeOfMipLevel(int mipLevel) const = 0;
virtual uint8_t* GetBufferForMipLevel(int mipLevel) = 0;
virtual uint8_t* GetBufferForMipLevel(int mipLevel, int face) = 0;
uint8_t* GetBufferForMipLevel(int mipLevel);
bool HasMipMaps() const;
virtual int GetMipMapCount() const = 0;
@ -48,11 +63,15 @@ public:
Texture2D& operator=(const Texture2D& other) = delete;
Texture2D& operator=(Texture2D&& other) noexcept;
unsigned GetWidth() const;
unsigned GetHeight() const;
Type GetType() const override;
unsigned GetWidth() const override;
unsigned GetHeight() const override;
unsigned GetDepth() const override;
int GetFaceCount() const override;
size_t GetSizeOfMipLevel(int mipLevel) const override;
uint8_t* GetBufferForMipLevel(int mipLevel) override;
uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
int GetMipMapCount() const override;
};
@ -71,7 +90,11 @@ public:
TextureCube& operator=(const TextureCube& other) = delete;
TextureCube& operator=(TextureCube&& other) noexcept;
size_t GetSizeOfMipLevel(int mipLevel) const override;
Type GetType() const override;
int GetFaceCount() const override;
uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
};
class Texture3D final : public Texture
@ -90,12 +113,15 @@ public:
Texture3D& operator=(const Texture3D& other) = delete;
Texture3D& operator=(Texture3D&& other) noexcept;
unsigned GetWidth() const;
unsigned GetHeight() const;
unsigned GetDepth() const;
Type GetType() const override;
unsigned GetWidth() const override;
unsigned GetHeight() const override;
unsigned GetDepth() const override;
int GetFaceCount() const override;
size_t GetSizeOfMipLevel(int mipLevel) const override;
uint8_t* GetBufferForMipLevel(int mipLevel) override;
uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
int GetMipMapCount() const override;
};

View File

@ -1,11 +1,278 @@
#include "DdsWriter.h"
#include <cassert>
#include "Image/DdsTypes.h"
using namespace dds;
class DdsWriterInternal
{
static constexpr uint32_t DDS_MAGIC = MakeFourCc('D', 'D', 'S', ' ');
static constexpr uint32_t DDS_PF_DXT10_EXTENSION = MakeFourCc('D', 'X', '1', '0');
static constexpr uint32_t DDS_PF_BC1 = MakeFourCc('D', 'X', 'T', '1');
static constexpr uint32_t DDS_PF_BC2 = MakeFourCc('D', 'X', 'T', '3');
static constexpr uint32_t DDS_PF_BC3 = MakeFourCc('D', 'X', 'T', '5');
public:
enum class ImageFormatSupportStatus
{
UNSUPPORTED,
SUPPORTED_WITH_SIMPLE_HEADER,
SUPPORTED_WITH_DXT10_HEADER
};
private:
FileAPI::IFile* m_file;
Texture* m_texture;
ImageFormatSupportStatus m_support_status;
void PrepareHeader(DDS_HEADER* header) const
{
header->dwSize = sizeof DDS_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->GetType() == Texture::Type::TYPE_3D)
header->dwFlags |= DDSD_DEPTH;
header->dwWidth = m_texture->GetWidth();
header->dwHeight = m_texture->GetHeight();
header->dwDepth = m_texture->GetDepth();
header->dwPitchOrLinearSize = m_texture->GetFormat()->GetPitch(m_texture->GetWidth());
header->dwMipMapCount = m_texture->HasMipMaps() ? m_texture->GetMipMapCount() : 1;
memset(header->dwReserved1, 0, sizeof DDS_HEADER::dwReserved1);
header->dwCaps = DDSCAPS_TEXTURE;
if (m_texture->HasMipMaps())
header->dwCaps |= DDSCAPS_MIPMAP;
if (m_texture->GetType() == Texture::Type::TYPE_CUBE || m_texture->HasMipMaps())
header->dwCaps |= DDSCAPS_COMPLEX;
header->dwCaps2 = 0;
if (m_texture->GetType() == Texture::Type::TYPE_CUBE)
{
header->dwCaps2 |=
DDSCAPS2_CUBEMAP
| DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_NEGATIVEX
| DDSCAPS2_CUBEMAP_POSITIVEY | DDSCAPS2_CUBEMAP_NEGATIVEY
| DDSCAPS2_CUBEMAP_POSITIVEZ | DDSCAPS2_CUBEMAP_NEGATIVEZ;
}
else if (m_texture->GetType() == Texture::Type::TYPE_3D)
{
header->dwCaps2 |= DDSCAPS2_VOLUME;
}
header->dwCaps3 = 0;
header->dwCaps4 = 0;
header->dwReserved2 = 0;
}
void SetPixelFormat(DDS_PIXELFORMAT* pixelFormat) const
{
pixelFormat->dwSize = sizeof DDS_PIXELFORMAT;
pixelFormat->dwFlags = 0;
const auto* imageFormat = m_texture->GetFormat();
switch (imageFormat->GetType())
{
case ImageFormatType::UNSIGNED:
{
const auto* imageFormatUnsigned = dynamic_cast<const ImageFormatUnsigned*>(imageFormat);
if (imageFormatUnsigned->m_r_size == 0
&& imageFormatUnsigned->m_g_size == 0
&& imageFormatUnsigned->m_b_size == 0
&& imageFormatUnsigned->m_a_size > 0)
{
pixelFormat->dwFlags |= DDPF_ALPHA;
}
else
{
if (imageFormatUnsigned->m_r_size > 0
&& imageFormatUnsigned->m_g_size == 0
&& imageFormatUnsigned->m_b_size == 0)
{
pixelFormat->dwFlags |= DDPF_LUMINANCE;
}
else if (imageFormatUnsigned->m_r_size > 0
|| imageFormatUnsigned->m_g_size > 0
|| imageFormatUnsigned->m_b_size > 0)
{
pixelFormat->dwFlags |= DDPF_RGB;
}
if (imageFormatUnsigned->m_a_size > 0)
{
pixelFormat->dwFlags |= DDPF_ALPHAPIXELS;
}
}
pixelFormat->dwRGBBitCount = imageFormatUnsigned->m_bits_per_pixel;
pixelFormat->dwRBitMask = static_cast<uint32_t>(imageFormatUnsigned->m_r_mask);
pixelFormat->dwGBitMask = static_cast<uint32_t>(imageFormatUnsigned->m_g_mask);
pixelFormat->dwBBitMask = static_cast<uint32_t>(imageFormatUnsigned->m_b_mask);
pixelFormat->dwABitMask = static_cast<uint32_t>(imageFormatUnsigned->m_a_mask);
}
break;
case ImageFormatType::BLOCK_COMPRESSED:
{
pixelFormat->dwFlags |= DDPF_FOURCC;
pixelFormat->dwRGBBitCount = 0;
pixelFormat->dwRBitMask = 0;
pixelFormat->dwGBitMask = 0;
pixelFormat->dwBBitMask = 0;
pixelFormat->dwABitMask = 0;
switch (imageFormat->GetId())
{
case ImageFormatId::BC1:
pixelFormat->dwFourCC = DDS_PF_BC1;
break;
case ImageFormatId::BC2:
pixelFormat->dwFourCC = DDS_PF_BC2;
break;
case ImageFormatId::BC3:
pixelFormat->dwFourCC = DDS_PF_BC3;
break;
default:
assert(false);
break;
}
}
break;
default:
break;
}
}
static void MarkHeaderAsExtendedByHeaderDxt10(DDS_PIXELFORMAT* pixelFormat)
{
pixelFormat->dwSize = sizeof DDS_PIXELFORMAT;
pixelFormat->dwFlags = DDPF_FOURCC;
pixelFormat->dwFourCC = DDS_PF_DXT10_EXTENSION;
pixelFormat->dwRGBBitCount = 0;
pixelFormat->dwRBitMask = 0;
pixelFormat->dwGBitMask = 0;
pixelFormat->dwBBitMask = 0;
pixelFormat->dwABitMask = 0;
}
void PrepareHeaderDxt10(DDS_HEADER_DXT10* header)
{
header->dxgiFormat = m_texture->GetFormat()->GetDxgiFormat();
switch (m_texture->GetType())
{
case Texture::Type::TYPE_2D:
case Texture::Type::TYPE_CUBE:
header->resourceDimension = DDS_DIMENSION_TEXTURE2D;
break;
case Texture::Type::TYPE_3D:
header->resourceDimension = DDS_DIMENSION_TEXTURE3D;
break;
}
header->miscFlag = 0;
if (m_texture->GetType() == Texture::Type::TYPE_CUBE)
header->miscFlag |= DDS_RESOURCE_MISC_TEXTURECUBE;
header->arraySize = m_texture->GetFaceCount();
header->miscFlags2 = 0;
}
public:
static ImageFormatSupportStatus GetSupportStatusForImageFormat(const ImageFormat* format)
{
assert(format != nullptr);
if (auto* imageFormatUnsigned = dynamic_cast<const ImageFormatUnsigned*>(format))
{
if (imageFormatUnsigned->m_bits_per_pixel <= sizeof uint32_t * 8)
return ImageFormatSupportStatus::SUPPORTED_WITH_SIMPLE_HEADER;
}
else
{
switch (format->GetId())
{
case ImageFormatId::BC1:
case ImageFormatId::BC2:
case ImageFormatId::BC3:
return ImageFormatSupportStatus::SUPPORTED_WITH_SIMPLE_HEADER;
default:
break;
}
}
return format->GetDxgiFormat() != DXGI_FORMAT_UNKNOWN
? ImageFormatSupportStatus::SUPPORTED_WITH_DXT10_HEADER
: ImageFormatSupportStatus::UNSUPPORTED;
}
DdsWriterInternal(FileAPI::IFile* file, Texture* texture)
{
m_file = file;
m_texture = texture;
m_support_status = GetSupportStatusForImageFormat(texture->GetFormat());
}
bool DumpImage()
{
if (m_file->Write(&DDS_MAGIC, sizeof uint32_t, 1) != 1)
return false;
DDS_HEADER ddsHeader{};
PrepareHeader(&ddsHeader);
if (m_support_status == ImageFormatSupportStatus::SUPPORTED_WITH_SIMPLE_HEADER)
{
SetPixelFormat(&ddsHeader.ddspf);
if (m_file->Write(&ddsHeader, sizeof DDS_HEADER, 1) != 1)
return false;
}
else if (m_support_status == ImageFormatSupportStatus::SUPPORTED_WITH_DXT10_HEADER)
{
DDS_HEADER_DXT10 ddsHeaderDxt10{};
MarkHeaderAsExtendedByHeaderDxt10(&ddsHeader.ddspf);
PrepareHeaderDxt10(&ddsHeaderDxt10);
if (m_file->Write(&ddsHeader, sizeof DDS_HEADER, 1) != 1
|| m_file->Write(&ddsHeaderDxt10, sizeof DDS_HEADER_DXT10, 1) != 1)
return false;
}
const int mipCount = m_texture->HasMipMaps() ? m_texture->GetMipMapCount() : 1;
for (int face = 0; face < m_texture->GetFaceCount(); face++)
{
for (int mipLevel = 0; mipLevel < mipCount; mipLevel++)
{
const size_t sizeOfMipLevel = m_texture->GetSizeOfMipLevel(mipLevel);
if (m_file->Write(m_texture->GetBufferForMipLevel(mipLevel, face), 1, sizeOfMipLevel) != sizeOfMipLevel)
return false;
}
}
return true;
}
};
DdsWriter::~DdsWriter()
= default;
bool DdsWriter::SupportsImageFormat(const ImageFormat* imageFormat)
{
return true;
return DdsWriterInternal::GetSupportStatusForImageFormat(imageFormat)
!= DdsWriterInternal::ImageFormatSupportStatus::UNSUPPORTED;
}
std::string DdsWriter::GetFileExtension()
@ -15,4 +282,6 @@ std::string DdsWriter::GetFileExtension()
void DdsWriter::DumpImage(FileAPI::IFile* file, Texture* texture)
{
DdsWriterInternal writer(file, texture);
writer.DumpImage();
}

View File

@ -8,5 +8,5 @@ public:
bool SupportsImageFormat(const ImageFormat * imageFormat) override;
std::string GetFileExtension() override;
void DumpImage(FileAPI::IFile * file, Texture * texture) override;
void DumpImage(FileAPI::IFile* file, Texture* texture) override;
};