mirror of https://github.com/axmolengine/axmol.git
263 lines
6.3 KiB
C++
263 lines
6.3 KiB
C++
#ifndef __DISABLED_DEFAULT_TEXTURE_LOADER__
|
|
|
|
#include "EffekseerRenderer.DDSTextureLoader.h"
|
|
#include <stdint.h>
|
|
|
|
namespace EffekseerRenderer
|
|
{
|
|
|
|
enum class DdsDx10Format : uint32_t
|
|
{
|
|
R8G8B8A8_UNORM = 28,
|
|
R8G8B8A8_UNORM_SRGB = 29,
|
|
BC1_UNORM = 71,
|
|
BC1_UNORM_SRGB = 72,
|
|
BC2_UNORM = 74,
|
|
BC2_UNORM_SRGB = 75,
|
|
BC3_UNORM = 77,
|
|
BC3_UNORM_SRGB = 78,
|
|
BC4_UNORM = 80,
|
|
BC4_SNORM = 81,
|
|
BC5_UNORM = 83,
|
|
BC5_SNORM = 84,
|
|
};
|
|
|
|
constexpr uint32_t MakeFourCC(const char v1, const char v2, const char v3, const char v4)
|
|
{
|
|
return ((static_cast<uint32_t>(v1)) | (static_cast<uint32_t>(v2) << 8) | (static_cast<uint32_t>(v3) << 16) | (static_cast<uint32_t>(v4) << 24));
|
|
}
|
|
|
|
bool DDSTextureLoader::Load(const void* data, int32_t size)
|
|
{
|
|
textures_.clear();
|
|
|
|
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;
|
|
};
|
|
|
|
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 dwCaps1;
|
|
uint32_t dwCaps2;
|
|
uint32_t dwReserved2[3];
|
|
};
|
|
|
|
struct DDS_HEADER_DXT10
|
|
{
|
|
DdsDx10Format dxgiFormat;
|
|
uint32_t resourceDimension;
|
|
uint32_t miscFlag;
|
|
uint32_t arraySize;
|
|
uint32_t miscFlags2;
|
|
};
|
|
|
|
auto p = (uint8_t*)data;
|
|
//const uint32_t FOURCC_DXT1 = 0x31545844; //(MAKEFOURCC('D','X','T','1'))
|
|
//const uint32_t FOURCC_DXT3 = 0x33545844; //(MAKEFOURCC('D','X','T','3'))
|
|
//const uint32_t FOURCC_DXT5 = 0x35545844; //(MAKEFOURCC('D','X','T','5'))
|
|
|
|
const uint32_t FOURCC_DXT1 = MakeFourCC('D', 'X', 'T', '1');
|
|
const uint32_t FOURCC_DXT3 = MakeFourCC('D', 'X', 'T', '3');
|
|
const uint32_t FOURCC_DXT5 = MakeFourCC('D', 'X', 'T', '5');
|
|
assert(FOURCC_DXT1 == 0x31545844);
|
|
assert(FOURCC_DXT3 == 0x33545844);
|
|
assert(FOURCC_DXT5 == 0x35545844);
|
|
|
|
if (size < 4 + sizeof(DDS_HEADER))
|
|
return false;
|
|
|
|
if (p[0] == 'D' && p[1] == 'D' && p[2] == 'S' && p[3] == ' ')
|
|
{
|
|
p += 4;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
DDS_HEADER dds;
|
|
memcpy(&dds, p, sizeof(DDS_HEADER));
|
|
p += sizeof(DDS_HEADER);
|
|
|
|
DDS_HEADER_DXT10 dds_dxt10;
|
|
|
|
bool hasDX10Flag = false;
|
|
if (dds.ddspf.dwFourCC == MakeFourCC('D', 'X', '1', '0'))
|
|
{
|
|
hasDX10Flag = true;
|
|
memcpy(&dds_dxt10, p, sizeof(DDS_HEADER_DXT10));
|
|
p += sizeof(DDS_HEADER_DXT10);
|
|
}
|
|
|
|
const auto detectFormat = [&]() -> Effekseer::Backend::TextureFormatType {
|
|
if (hasDX10Flag)
|
|
{
|
|
if (dds_dxt10.dxgiFormat == DdsDx10Format::R8G8B8A8_UNORM)
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::R8G8B8A8_UNORM;
|
|
}
|
|
else if (dds_dxt10.dxgiFormat == DdsDx10Format::R8G8B8A8_UNORM_SRGB)
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::R8G8B8A8_UNORM_SRGB;
|
|
}
|
|
else if (dds_dxt10.dxgiFormat == DdsDx10Format::BC1_UNORM)
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::BC1;
|
|
}
|
|
else if (dds_dxt10.dxgiFormat == DdsDx10Format::BC1_UNORM_SRGB)
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::BC1_SRGB;
|
|
}
|
|
else if (dds_dxt10.dxgiFormat == DdsDx10Format::BC2_UNORM)
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::BC2;
|
|
}
|
|
else if (dds_dxt10.dxgiFormat == DdsDx10Format::BC2_UNORM_SRGB)
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::BC2_SRGB;
|
|
}
|
|
else if (dds_dxt10.dxgiFormat == DdsDx10Format::BC3_UNORM)
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::BC3;
|
|
}
|
|
else if (dds_dxt10.dxgiFormat == DdsDx10Format::BC3_UNORM_SRGB)
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::BC3_SRGB;
|
|
}
|
|
else
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::Unknown;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dds.ddspf.dwRGBBitCount == 32 && dds.ddspf.dwRBitMask == 0x000000FF && dds.ddspf.dwGBitMask == 0x0000FF00 &&
|
|
dds.ddspf.dwBBitMask == 0x00FF0000 && dds.ddspf.dwABitMask == 0xFF000000)
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::R8G8B8A8_UNORM;
|
|
}
|
|
if (dds.ddspf.dwFourCC == FOURCC_DXT1)
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::BC1;
|
|
}
|
|
else if (dds.ddspf.dwFourCC == FOURCC_DXT3)
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::BC2;
|
|
}
|
|
else if (dds.ddspf.dwFourCC == FOURCC_DXT5)
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::BC3;
|
|
}
|
|
else
|
|
{
|
|
return Effekseer::Backend::TextureFormatType::Unknown;
|
|
}
|
|
}
|
|
};
|
|
|
|
auto format = detectFormat();
|
|
int32_t blockSize = 0;
|
|
bool isCompressed = false;
|
|
|
|
if (format == Effekseer::Backend::TextureFormatType::R8G8B8A8_UNORM ||
|
|
format == Effekseer::Backend::TextureFormatType::R8G8B8A8_UNORM_SRGB)
|
|
{
|
|
textureFormatType = Effekseer::TextureFormatType::ABGR8;
|
|
blockSize = 4;
|
|
isCompressed = false;
|
|
}
|
|
else if (format == Effekseer::Backend::TextureFormatType::BC1 ||
|
|
format == Effekseer::Backend::TextureFormatType::BC1_SRGB)
|
|
{
|
|
textureFormatType = Effekseer::TextureFormatType::BC1;
|
|
blockSize = 8;
|
|
isCompressed = true;
|
|
}
|
|
else if (format == Effekseer::Backend::TextureFormatType::BC2 ||
|
|
format == Effekseer::Backend::TextureFormatType::BC2_SRGB)
|
|
{
|
|
textureFormatType = Effekseer::TextureFormatType::BC2;
|
|
blockSize = 16;
|
|
isCompressed = true;
|
|
}
|
|
else if (format == Effekseer::Backend::TextureFormatType::BC3 ||
|
|
format == Effekseer::Backend::TextureFormatType::BC3_SRGB)
|
|
{
|
|
textureFormatType = Effekseer::TextureFormatType::BC3;
|
|
blockSize = 16;
|
|
isCompressed = true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
backendTextureFormatType = format;
|
|
textures_.reserve(dds.dwMipMapCount);
|
|
|
|
int32_t width = static_cast<int32_t>(dds.dwWidth);
|
|
int32_t height = static_cast<int32_t>(dds.dwHeight);
|
|
|
|
for (size_t i = 0; i < dds.dwMipMapCount; i++)
|
|
{
|
|
int32_t textureSize{};
|
|
|
|
if (isCompressed)
|
|
{
|
|
textureSize = ((width + 3) / 4) * ((height + 3) / 4) * blockSize;
|
|
}
|
|
else
|
|
{
|
|
textureSize = width * height * blockSize;
|
|
}
|
|
|
|
::Effekseer::CustomVector<uint8_t> textureData;
|
|
textureData.resize(textureSize);
|
|
|
|
memcpy(textureData.data(), p, textureData.size());
|
|
textures_.emplace_back(Texture{width, height, std::move(textureData)});
|
|
|
|
if (width > 1)
|
|
width = (width >> 1);
|
|
else
|
|
width = 1;
|
|
|
|
if (height > 1)
|
|
height = (height >> 1);
|
|
else
|
|
height = 1;
|
|
|
|
p += textureSize;
|
|
}
|
|
|
|
textureWidth = static_cast<int32_t>(dds.dwWidth);
|
|
textureHeight = static_cast<int32_t>(dds.dwHeight);
|
|
|
|
return true;
|
|
}
|
|
|
|
void DDSTextureLoader::Unload()
|
|
{
|
|
textures_.clear();
|
|
}
|
|
|
|
} // namespace EffekseerRenderer
|
|
|
|
#endif |