diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 50d7786d..04e88c80 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -127,6 +127,8 @@ + + diff --git a/FModel/PakReader/Textures/BC/Detex.cs b/FModel/PakReader/Textures/BC/Detex.cs new file mode 100644 index 00000000..bcd032aa --- /dev/null +++ b/FModel/PakReader/Textures/BC/Detex.cs @@ -0,0 +1,106 @@ +using System; +using System.IO; +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security.Cryptography; + +namespace PakReader.Textures.BC +{ + public static class Detex + { + private const string DETEX_DLL_NAME = "Detex.dll"; + + static Detex() + { + PrepareDllFile(); + } + + [StructLayout(LayoutKind.Sequential)] + private unsafe struct detexTexture + { + public uint format; + public byte* data; + public int width; + public int height; + public int width_in_blocks; + public int height_in_blocks; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte[] DecodeDetexLinear(byte[] inp, int width, int height, bool isFloat, DetexTextureFormat inputFormat, + DetexPixelFormat outputPixelFormat, int blockSizeX = 4, int blockSizeY = 4) + { + var dst = new byte[width * height * (isFloat ? 16 : 4)]; + DecodeDetexLinear(inp, dst, width, height, inputFormat, outputPixelFormat, blockSizeX, blockSizeY); + return dst; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool DecodeDetexLinear(byte[] inp, byte[] dst, int width, int height, DetexTextureFormat inputFormat, DetexPixelFormat outputPixelFormat, int blockSizeX = 4, int blockSizeY = 4) + { + unsafe + { + detexTexture tex; + tex.format = (uint) inputFormat; + tex.data = (byte*) Unsafe.AsPointer(ref inp[0]); + tex.width = width; + tex.height = height; + tex.width_in_blocks = width / 4; + tex.height_in_blocks = height / 4; + return detexDecompressTextureLinear(&tex, (byte*) Unsafe.AsPointer(ref dst[0]), + (uint) outputPixelFormat); + } + } + + public static byte[] DecodeBC6H(byte[] inp, int width, int height) + { + const int PIXEL_SIZE = 16; + var dst = new byte[width * height * PIXEL_SIZE]; + + DecodeDetexLinear(inp, dst, width, height, DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC_FLOAT, + DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBX8); + + return dst; + } + + [DllImport(DETEX_DLL_NAME)] + private static extern unsafe bool detexDecompressTextureLinear(detexTexture* texture, byte* pixelBuffer, + uint pixelFormat); + + private static void PrepareDllFile() + { + using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("FModel.Resources.Detex.dll"); + if (stream == null) + throw new MissingManifestResourceException("Couldn't find Detex.dll in Embedded Resources"); + var ba = new byte[(int) stream.Length]; + stream.Read(ba, 0, (int) stream.Length); + + bool fileOk; + var dllFile = DETEX_DLL_NAME; + + using (var sha1 = new SHA1CryptoServiceProvider()) + { + var fileHash = BitConverter.ToString(sha1.ComputeHash(ba)).Replace("-", string.Empty); + + if (File.Exists(dllFile)) + { + var bb = File.ReadAllBytes(dllFile); + var fileHash2 = BitConverter.ToString(sha1.ComputeHash(bb)).Replace("-", string.Empty); + + fileOk = fileHash == fileHash2; + } + else + { + fileOk = false; + } + } + + if (!fileOk) + { + File.WriteAllBytes(dllFile, ba); + } + } + } +} \ No newline at end of file diff --git a/FModel/PakReader/Textures/BC/DetexCompressedTextureFormatIndex.cs b/FModel/PakReader/Textures/BC/DetexCompressedTextureFormatIndex.cs new file mode 100644 index 00000000..88d1b30c --- /dev/null +++ b/FModel/PakReader/Textures/BC/DetexCompressedTextureFormatIndex.cs @@ -0,0 +1,39 @@ +namespace PakReader.Textures.BC +{ + internal enum DetexCompressedTextureFormatIndex : uint + { + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_UNCOMPRESSED = 0, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1 = 1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_DXT1 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_S3TC = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1A, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_DXT1A = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1A, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_DXT3 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC3, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_DXT5 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC3, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC4_UNORM = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC4_SNORM = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC5_UNORM = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC5_SNORM = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_FLOAT, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC6H_UF16 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_FLOAT, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_SIGNED_FLOAT, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC6H_SF16 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_SIGNED_FLOAT, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC7 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC1, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2_PUNCHTHROUGH, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2_EAC, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_R11, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_SIGNED_R11, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_RG11, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_SIGNED_RG11, + DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ASTC_4X4, + } +} \ No newline at end of file diff --git a/FModel/PakReader/Textures/BC/DetexPixelFormat.cs b/FModel/PakReader/Textures/BC/DetexPixelFormat.cs new file mode 100644 index 00000000..9dcc2f0b --- /dev/null +++ b/FModel/PakReader/Textures/BC/DetexPixelFormat.cs @@ -0,0 +1,361 @@ +namespace PakReader.Textures.BC +{ + public enum DetexPixelFormat : uint + { + /* The format has 16-bit components. */ + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT = 0x1, + + /* The format has 32-bit components. */ + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT = 0x2, + + /* The format has an alpha component. */ + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT = 0x4, + + /* The sequential component order is RGB. */ + DETEX_PIXEL_FORMAT_RGB_COMPONENT_ORDER_BIT = 0x0, + + /* The sequential component order is BGR. */ + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT = 0x8, + + /* The format has one component. */ + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS = 0x0, + + /* The format has two components. */ + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS = 0x10, + + /* The format has three components. */ + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS = 0x20, + + /* The format has four components. */ + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS = 0x30, + + /* The format is stored as 8-bit pixels. */ + DETEX_PIXEL_FORMAT_8BIT_PIXEL_BITS = 0x000, + + /* The format is stored as 16-bit pixels. */ + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS = 0x100, + + /* The format is stored as 24-bit pixels. */ + DETEX_PIXEL_FORMAT_24BIT_PIXEL_BITS = 0x200, + + /* The format is stored as 32-bit pixels. */ + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS = 0x300, + + /* The format is stored as 48-bit pixels. */ + DETEX_PIXEL_FORMAT_48BIT_PIXEL_BITS = 0x500, + + /* The format is stored as 64-bit pixels. */ + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS = 0x700, + + /* The format is stored as 96-bit pixels. */ + DETEX_PIXEL_FORMAT_96BIT_PIXEL_BITS = 0xB00, + + /* The format is stored as 128-bit pixels. */ + DETEX_PIXEL_FORMAT_128BIT_PIXEL_BITS = 0xF00, + + /* The format has signed integer components. */ + DETEX_PIXEL_FORMAT_SIGNED_BIT = 0x1000, + + /* The format has (half-)float components. */ + DETEX_PIXEL_FORMAT_FLOAT_BIT = 0x2000, + + /* The fomat is HDR (high dynamic range). */ + DETEX_PIXEL_FORMAT_HDR_BIT = 0x4000, + + DETEX_PIXEL_FORMAT_RGBA8 = ( + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_BGRA8 = ( + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_RGBX8 = ( + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_BGRX8 = ( + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_RGB8 = ( + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_24BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_BGR8 = ( + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_24BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_R8 = ( + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_8BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_SIGNED_R8 = ( + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_8BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_SIGNED_BIT + ), + + DETEX_PIXEL_FORMAT_RG8 = ( + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_SIGNED_RG8 = ( + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_SIGNED_BIT + ), + + DETEX_PIXEL_FORMAT_R16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_SIGNED_R16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_SIGNED_BIT + ), + + DETEX_PIXEL_FORMAT_RG16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_SIGNED_RG16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_SIGNED_BIT + ), + + DETEX_PIXEL_FORMAT_RGB16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_48BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_RGBX16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_RGBA16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS + ), + + DETEX_PIXEL_FORMAT_FLOAT_R16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_R16_HDR = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_16BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RG16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RG16_HDR = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RGBX16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RGBX16_HDR = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RGBA16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RGBA16_HDR = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RGB16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_48BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RGB16_HDR = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_48BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_BGRX16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_BGRX16_HDR = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + + DETEX_PIXEL_FORMAT_SIGNED_FLOAT_RGBX16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_SIGNED_BIT | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_SIGNED_FLOAT_BGRX16 = ( + DETEX_PIXEL_FORMAT_16BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_BGR_COMPONENT_ORDER_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_SIGNED_BIT | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_R32 = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_R32_HDR = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_32BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RG32 = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RG32_HDR = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_TWO_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_64BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RGB32 = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_96BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RGB32_HDR = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_96BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RGBX32 = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_128BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RGBX32_HDR = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_THREE_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_128BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RGBA32 = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_128BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT + ), + + DETEX_PIXEL_FORMAT_FLOAT_RGBA32_HDR = ( + DETEX_PIXEL_FORMAT_32BIT_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_FOUR_COMPONENTS_BITS | + DETEX_PIXEL_FORMAT_128BIT_PIXEL_BITS | + DETEX_PIXEL_FORMAT_FLOAT_BIT | + DETEX_PIXEL_FORMAT_HDR_BIT + ), + + DETEX_PIXEL_FORMAT_A8 = ( + DETEX_PIXEL_FORMAT_ALPHA_COMPONENT_BIT | + DETEX_PIXEL_FORMAT_ONE_COMPONENT_BITS | + DETEX_PIXEL_FORMAT_8BIT_PIXEL_BITS + ), + } +} \ No newline at end of file diff --git a/FModel/PakReader/Textures/BC/DetexTextureFormat.cs b/FModel/PakReader/Textures/BC/DetexTextureFormat.cs new file mode 100644 index 00000000..23247a13 --- /dev/null +++ b/FModel/PakReader/Textures/BC/DetexTextureFormat.cs @@ -0,0 +1,119 @@ +namespace PakReader.Textures.BC +{ + public enum DetexTextureFormat : uint + { + DETEX_TEXTURE_FORMAT_PIXEL_FORMAT_MASK = 0x0000FFFF, + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT = 0x00800000, + + DETEX_TEXTURE_FORMAT_BC1 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1 << 24) | + DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBX8 + ), + + DETEX_TEXTURE_FORMAT_BC1A = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1A << 24) | + DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8 + ), + + DETEX_TEXTURE_FORMAT_BC2 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC2 << 24) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8 + ), + + DETEX_TEXTURE_FORMAT_BC3 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC3 << 24) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8 + ), + + DETEX_TEXTURE_FORMAT_RGTC1 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC1 << 24) | + DetexPixelFormat.DETEX_PIXEL_FORMAT_R8 + ), + + DETEX_TEXTURE_FORMAT_SIGNED_RGTC1 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC1 << 24) | + DetexPixelFormat.DETEX_PIXEL_FORMAT_SIGNED_R16 + ), + + DETEX_TEXTURE_FORMAT_RGTC2 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC2 << 24) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DetexPixelFormat.DETEX_PIXEL_FORMAT_RG8 + ), + + DETEX_TEXTURE_FORMAT_SIGNED_RGTC2 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC2 << 24) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DetexPixelFormat.DETEX_PIXEL_FORMAT_SIGNED_RG16 + ), + + DETEX_TEXTURE_FORMAT_BPTC_FLOAT = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_FLOAT << 24) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DetexPixelFormat.DETEX_PIXEL_FORMAT_FLOAT_RGBX16 + ), + + DETEX_TEXTURE_FORMAT_BPTC_SIGNED_FLOAT = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_SIGNED_FLOAT << 24) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DetexPixelFormat.DETEX_PIXEL_FORMAT_SIGNED_FLOAT_RGBX16 + ), + + DETEX_TEXTURE_FORMAT_BPTC = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC << 24) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8 + ), + + DETEX_TEXTURE_FORMAT_ETC1 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC1 << 24) | + DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBX8 + ), + + DETEX_TEXTURE_FORMAT_ETC2 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2 << 24) | + DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBX8 + ), + + DETEX_TEXTURE_FORMAT_ETC2_PUNCHTHROUGH = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2_PUNCHTHROUGH << 24) | + DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8 + ), + + DETEX_TEXTURE_FORMAT_ETC2_EAC = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2_EAC << 24) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8 + ), + + DETEX_TEXTURE_FORMAT_EAC_R11 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_R11 << 24) | + DetexPixelFormat.DETEX_PIXEL_FORMAT_R16 + ), + + DETEX_TEXTURE_FORMAT_EAC_SIGNED_R11 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_SIGNED_R11 << 24) | + DetexPixelFormat.DETEX_PIXEL_FORMAT_SIGNED_R16 + ), + + DETEX_TEXTURE_FORMAT_EAC_RG11 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_RG11 << 24) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DetexPixelFormat.DETEX_PIXEL_FORMAT_RG16 + ), + + DETEX_TEXTURE_FORMAT_EAC_SIGNED_RG11 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_SIGNED_RG11 << 24) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DetexPixelFormat.DETEX_PIXEL_FORMAT_SIGNED_RG16 + ), + + DETEX_TEXTURE_FORMAT_ASTC_4X4 = ( + (DetexCompressedTextureFormatIndex.DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ASTC_4X4 << 24) | + DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT | + DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8 + ), + } +} \ No newline at end of file diff --git a/FModel/PakReader/Textures/TextureDecoder.cs b/FModel/PakReader/Textures/TextureDecoder.cs index d929915c..6c0a557d 100644 --- a/FModel/PakReader/Textures/TextureDecoder.cs +++ b/FModel/PakReader/Textures/TextureDecoder.cs @@ -50,6 +50,37 @@ namespace PakReader.Textures data = sequence; colorType = SKColorType.RgbaF16; break; + case EPixelFormat.PF_BC7: + data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: false, + inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC, + outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8); + colorType = SKColorType.Rgba8888; + break; + case EPixelFormat.PF_BC6H: + data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: true, + inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_BPTC_FLOAT, + outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBX8); // Not sure whether that works, would actually be DETEX_PIXEL_FORMAT_FLOAT_RGBX32 + data = Detex.DecodeBC6H(sequence, width, height); + colorType = SKColorType.Rgb888x; + break; + case EPixelFormat.PF_ETC1: + data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: false, + inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC1, + outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8); + colorType = SKColorType.Rgba8888; + break; + case EPixelFormat.PF_ETC2_RGB: + data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: false, + inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2, + outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8); + colorType = SKColorType.Rgba8888; + break; + case EPixelFormat.PF_ETC2_RGBA: + data = Detex.DecodeDetexLinear(sequence, width, height, isFloat: false, + inputFormat: DetexTextureFormat.DETEX_TEXTURE_FORMAT_ETC2_EAC, + outputPixelFormat: DetexPixelFormat.DETEX_PIXEL_FORMAT_RGBA8); + colorType = SKColorType.Rgba8888; + break; default: throw new NotImplementedException($"Cannot decode {format} format"); } diff --git a/FModel/Resources/Detex.dll b/FModel/Resources/Detex.dll new file mode 100644 index 00000000..a05872ba Binary files /dev/null and b/FModel/Resources/Detex.dll differ