Files
unity/inc/dds_defs.h
T
Alexander Suvorov bec4114bea Add compression support for ETC2A textures
This change makes it possible to use Crunch algorithms for ETC textures with Alpha channel.

Explanation:

For simplicity, Crunch algorithms currently do not use ETC2 specific modes (T, H or P). For this reason, the currently used ETC2A compression format is technically equivalent to ETC1 + Alpha. Note that ETC2 encoding is a superset of ETC1, so any texture, which consists of ETC1 color blocks and ETC2 Alpha blocks, can be correctly decoded by an ETC2A (ETC2_RGBA8) decoder.

Compression scheme for ETC2 Alpha blocks is equivalent to the compression scheme for DXT5 Alpha blocks. ETC2 Alpha endpoint clusterization is performed based on the very same output of the Alpha palettizer which is used for DXT5 Alpha. The only part which is actually different is the Alpha endpoint optimization step.

In order to perform ETC2 Alpha encoding, we can first run the already existing algorithm for DXT5 Alpha endpoint optimization, in order to obtain the initial approximate solution. Then the approximate solution is refined based on the ETC2 Alpha modifier table. When performing raw ETC2A encoding, all the 16 ETC2 Alpha modifiers are used during optimization. However, when performing ETC2A quantization, for performance reasons, only 2 Alpha modifiers are currently used (modifier 13, which allows to perform precise approximation on short Alpha intervals, and modifier 11, which has more or less regularly distributed values, and is used for large Alpha intervals).

For compatibility reasons, ETC2 color compression wrappers have also been added to the code, though, as has been mentioned before, at the current moment ETC2 specific modes are not used, so ETC2 color compression is currently equivalent to ETC1 compression.

The ETC decoder functionality has been significantly extended, Crunch is now capable to decode ETC2 and ETC2A textures (input ETC2 textures can have T, H or P blocks).

In order to use ETC2A compression, use the -ETC2A command line option (i.e. "crunch_x64.exe -ETC2A input.png"). By default, compressed ETC2A textures will be decompressed into KTX file format.

DXT Testing:

The modified algorithm has been tested on the Kodak test set using 64-bit build with default settings (running on Windows 10, i7-4790, 3.6GHz). All the decompressed test images are identical to the images being compressed and decompressed using original version of Crunch (revision ea9b8d8).

[Compressing Kodak set without mipmaps using DXT1 encoding]
Original: 1582222 bytes / 28.880 sec
Modified: 1468204 bytes / 13.288 sec
Improvement: 7.21% (compression ratio) / 53.99% (compression time)

[Compressing Kodak set with mipmaps using DXT1 encoding]
Original: 2065243 bytes / 36.936 sec
Modified: 1914805 bytes / 18.044 sec
Improvement: 7.28% (compression ratio) / 51.15% (compression time)

ETC Testing:

The modified algorithm has been tested on the Kodak test set using 64-bit build with default settings (running on Windows 10, i7-4790, 3.6GHz). The ETC1 quantization parameters have been selected in such a way, so that ETC1 compression gives approximately the same average Luma PSNR as the corresponding DXT1 compression (which is equal to 34.044 dB for the Kodak test set compressed without mipmaps using DXT1 encoding and default quality settings).

[Compressing Kodak set without mipmaps using ETC1 encoding]
Total size: 1607858 bytes
Total time: 17.361 sec
Average bitrate: 1.363 bpp
Average Luma PSNR: 34.050 dB
2017-08-04 16:56:10 +02:00

148 lines
5.0 KiB
C++

// File: dds_defs.h
// DX9 .DDS file header definitions.
#ifndef CRNLIB_DDS_DEFS_H
#define CRNLIB_DDS_DEFS_H
#include "crnlib.h"
#define CRNLIB_PIXEL_FMT_FOURCC(a, b, c, d) ((a) | ((b) << 8U) | ((c) << 16U) | ((d) << 24U))
namespace crnlib {
enum pixel_format {
PIXEL_FMT_INVALID = 0,
PIXEL_FMT_DXT1 = CRNLIB_PIXEL_FMT_FOURCC('D', 'X', 'T', '1'),
PIXEL_FMT_DXT2 = CRNLIB_PIXEL_FMT_FOURCC('D', 'X', 'T', '2'),
PIXEL_FMT_DXT3 = CRNLIB_PIXEL_FMT_FOURCC('D', 'X', 'T', '3'),
PIXEL_FMT_DXT4 = CRNLIB_PIXEL_FMT_FOURCC('D', 'X', 'T', '4'),
PIXEL_FMT_DXT5 = CRNLIB_PIXEL_FMT_FOURCC('D', 'X', 'T', '5'),
PIXEL_FMT_3DC = CRNLIB_PIXEL_FMT_FOURCC('A', 'T', 'I', '2'), // DXN_YX
PIXEL_FMT_DXN = CRNLIB_PIXEL_FMT_FOURCC('A', '2', 'X', 'Y'), // DXN_XY
PIXEL_FMT_DXT5A = CRNLIB_PIXEL_FMT_FOURCC('A', 'T', 'I', '1'), // ATI1N, http://developer.amd.com/media/gpu_assets/Radeon_X1x00_Programming_Guide.pdf
// Non-standard, crnlib-specific pixel formats (some of these are supported by ATI's Compressonator)
PIXEL_FMT_DXT5_CCxY = CRNLIB_PIXEL_FMT_FOURCC('C', 'C', 'x', 'Y'),
PIXEL_FMT_DXT5_xGxR = CRNLIB_PIXEL_FMT_FOURCC('x', 'G', 'x', 'R'),
PIXEL_FMT_DXT5_xGBR = CRNLIB_PIXEL_FMT_FOURCC('x', 'G', 'B', 'R'),
PIXEL_FMT_DXT5_AGBR = CRNLIB_PIXEL_FMT_FOURCC('A', 'G', 'B', 'R'),
PIXEL_FMT_DXT1A = CRNLIB_PIXEL_FMT_FOURCC('D', 'X', '1', 'A'),
PIXEL_FMT_ETC1 = CRNLIB_PIXEL_FMT_FOURCC('E', 'T', 'C', '1'),
PIXEL_FMT_ETC2 = CRNLIB_PIXEL_FMT_FOURCC('E', 'T', 'C', '2'),
PIXEL_FMT_ETC2A = CRNLIB_PIXEL_FMT_FOURCC('E', 'T', '2', 'A'),
PIXEL_FMT_R8G8B8 = CRNLIB_PIXEL_FMT_FOURCC('R', 'G', 'B', 'x'),
PIXEL_FMT_L8 = CRNLIB_PIXEL_FMT_FOURCC('L', 'x', 'x', 'x'),
PIXEL_FMT_A8 = CRNLIB_PIXEL_FMT_FOURCC('x', 'x', 'x', 'A'),
PIXEL_FMT_A8L8 = CRNLIB_PIXEL_FMT_FOURCC('L', 'x', 'x', 'A'),
PIXEL_FMT_A8R8G8B8 = CRNLIB_PIXEL_FMT_FOURCC('R', 'G', 'B', 'A')
};
const crn_uint32 cDDSMaxImageDimensions = 8192U;
// Total size of header is sizeof(uint32)+cDDSSizeofDDSurfaceDesc2;
const crn_uint32 cDDSSizeofDDSurfaceDesc2 = 124;
// "DDS "
const crn_uint32 cDDSFileSignature = 0x20534444;
struct DDCOLORKEY {
crn_uint32 dwUnused0;
crn_uint32 dwUnused1;
};
struct DDPIXELFORMAT {
crn_uint32 dwSize;
crn_uint32 dwFlags;
crn_uint32 dwFourCC;
crn_uint32 dwRGBBitCount; // ATI compressonator and crnlib will place a FOURCC code here for swizzled/cooked DXTn formats
crn_uint32 dwRBitMask;
crn_uint32 dwGBitMask;
crn_uint32 dwBBitMask;
crn_uint32 dwRGBAlphaBitMask;
};
struct DDSCAPS2 {
crn_uint32 dwCaps;
crn_uint32 dwCaps2;
crn_uint32 dwCaps3;
crn_uint32 dwCaps4;
};
struct DDSURFACEDESC2 {
crn_uint32 dwSize;
crn_uint32 dwFlags;
crn_uint32 dwHeight;
crn_uint32 dwWidth;
union {
crn_int32 lPitch;
crn_uint32 dwLinearSize;
};
crn_uint32 dwBackBufferCount;
crn_uint32 dwMipMapCount;
crn_uint32 dwAlphaBitDepth;
crn_uint32 dwUnused0;
crn_uint32 lpSurface;
DDCOLORKEY unused0;
DDCOLORKEY unused1;
DDCOLORKEY unused2;
DDCOLORKEY unused3;
DDPIXELFORMAT ddpfPixelFormat;
DDSCAPS2 ddsCaps;
crn_uint32 dwUnused1;
};
const crn_uint32 DDSD_CAPS = 0x00000001;
const crn_uint32 DDSD_HEIGHT = 0x00000002;
const crn_uint32 DDSD_WIDTH = 0x00000004;
const crn_uint32 DDSD_PITCH = 0x00000008;
const crn_uint32 DDSD_BACKBUFFERCOUNT = 0x00000020;
const crn_uint32 DDSD_ZBUFFERBITDEPTH = 0x00000040;
const crn_uint32 DDSD_ALPHABITDEPTH = 0x00000080;
const crn_uint32 DDSD_LPSURFACE = 0x00000800;
const crn_uint32 DDSD_PIXELFORMAT = 0x00001000;
const crn_uint32 DDSD_CKDESTOVERLAY = 0x00002000;
const crn_uint32 DDSD_CKDESTBLT = 0x00004000;
const crn_uint32 DDSD_CKSRCOVERLAY = 0x00008000;
const crn_uint32 DDSD_CKSRCBLT = 0x00010000;
const crn_uint32 DDSD_MIPMAPCOUNT = 0x00020000;
const crn_uint32 DDSD_REFRESHRATE = 0x00040000;
const crn_uint32 DDSD_LINEARSIZE = 0x00080000;
const crn_uint32 DDSD_TEXTURESTAGE = 0x00100000;
const crn_uint32 DDSD_FVF = 0x00200000;
const crn_uint32 DDSD_SRCVBHANDLE = 0x00400000;
const crn_uint32 DDSD_DEPTH = 0x00800000;
const crn_uint32 DDSD_ALL = 0x00fff9ee;
const crn_uint32 DDPF_ALPHAPIXELS = 0x00000001;
const crn_uint32 DDPF_ALPHA = 0x00000002;
const crn_uint32 DDPF_FOURCC = 0x00000004;
const crn_uint32 DDPF_PALETTEINDEXED8 = 0x00000020;
const crn_uint32 DDPF_RGB = 0x00000040;
const crn_uint32 DDPF_LUMINANCE = 0x00020000;
const crn_uint32 DDSCAPS_COMPLEX = 0x00000008;
const crn_uint32 DDSCAPS_TEXTURE = 0x00001000;
const crn_uint32 DDSCAPS_MIPMAP = 0x00400000;
const crn_uint32 DDSCAPS2_CUBEMAP = 0x00000200;
const crn_uint32 DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400;
const crn_uint32 DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800;
const crn_uint32 DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000;
const crn_uint32 DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000;
const crn_uint32 DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000;
const crn_uint32 DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000;
const crn_uint32 DDSCAPS2_VOLUME = 0x00200000;
} // namespace crnlib
#endif // CRNLIB_DDS_DEFS_H