Esempio n. 1
0
        public void SetFlags(DXGI_FORMAT Format)
        {
            header.flags = (uint)(DDSD.CAPS | DDSD.HEIGHT | DDSD.WIDTH | DDSD.PIXELFORMAT | DDSD.MIPMAPCOUNT | DDSD.LINEARSIZE);
            header.caps  = (uint)DDSCAPS.TEXTURE;
            if (header.mipmapCount > 1)
            {
                header.caps |= (uint)(DDSCAPS.COMPLEX | DDSCAPS.MIPMAP);
            }

            switch (Format)
            {
            case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM:
            case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
                header.ddspf.flags       = (uint)(DDPF.RGB | DDPF.ALPHAPIXELS);
                header.ddspf.RGBBitCount = 0x8 * 4;
                header.ddspf.RBitMask    = 0x000000FF;
                header.ddspf.GBitMask    = 0x0000FF00;
                header.ddspf.BBitMask    = 0x00FF0000;
                header.ddspf.ABitMask    = 0xFF000000;
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB:
            case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM:
                header.ddspf.flags  = (uint)DDPF.FOURCC;
                header.ddspf.fourCC = FOURCC_DXT1;
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM_SRGB:
            case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM:
                header.ddspf.flags  = (uint)DDPF.FOURCC;
                header.ddspf.fourCC = FOURCC_DXT3;
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB:
            case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM:
                header.ddspf.flags  = (uint)DDPF.FOURCC;
                header.ddspf.fourCC = FOURCC_DXT5;
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM:
            case DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM:
            case DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM:
            case DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM:
            case DXGI_FORMAT.DXGI_FORMAT_BC6H_UF16:
            case DXGI_FORMAT.DXGI_FORMAT_BC6H_SF16:
            case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM:
            case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB:
                header.ddspf.flags  = (uint)DDPF.FOURCC;
                header.ddspf.fourCC = FOURCC_DX10;
                if (DX10header == null)
                {
                    DX10header = new DX10Header();
                }

                IsDX10 = true;
                DX10header.DXGI_Format = Format;
                break;
            }
        }
Esempio n. 2
0
 private void ReadDX10Header(BinaryDataReader reader)
 {
     DX10header             = new DX10Header();
     DX10header.DXGI_Format = reader.ReadEnum <DXGI_FORMAT>(true);
     DX10header.ResourceDim = reader.ReadUInt32();
     DX10header.miscFlag    = reader.ReadUInt32();
     DX10header.arrayFlag   = reader.ReadUInt32();
     DX10header.miscFlags2  = reader.ReadUInt32();
 }
Esempio n. 3
0
        public void Load(Stream stream)
        {
            Name = FileInfo.FileName;
            using (var reader = new FileReader(stream))
            {
                MainHeader = reader.ReadStruct <Header>();
                PfHeader   = reader.ReadStruct <DDSPFHeader>();
                if (IsDX10)
                {
                    Dx10Header = reader.ReadStruct <DX10Header>();
                }

                byte[] Components = new byte[4] {
                    0, 1, 2, 3
                };

                bool Compressed   = false;
                bool HasLuminance = false;
                bool HasAlpha     = false;
                bool IsRGB        = false;

                switch (PfHeader.Flags)
                {
                case 4:
                    Compressed = true;
                    break;

                case 2:
                case (uint)DDPF.LUMINANCE:
                    HasLuminance = true;
                    break;

                case (uint)DDPF.RGB:
                    IsRGB = true;
                    break;

                case 0x41:
                    IsRGB    = true;
                    HasAlpha = true;
                    break;
                }

                ToGenericFormat();

                if (!IsDX10 && !this.IsBCNCompressed())
                {
                    Platform.OutputFormat = DDS_RGBA.GetUncompressedType(this, Components, IsRGB, HasAlpha, HasLuminance, PfHeader);
                }

                Depth      = 1;
                Width      = MainHeader.Width;
                Height     = MainHeader.Height;
                MipCount   = MainHeader.MipCount == 0 ? 1 : MainHeader.MipCount;
                ArrayCount = IsCubeMap ? (uint)6 : 1;
            }
        }
Esempio n. 4
0
        private void WriteDX10Header(BinaryDataWriter writer)
        {
            if (DX10header == null)
            {
                DX10header = new DX10Header();
            }

            writer.Write((uint)DX10header.DXGI_Format);
            writer.Write(DX10header.ResourceDim);
            writer.Write(DX10header.miscFlag);
            writer.Write(DX10header.arrayFlag);
            writer.Write(DX10header.miscFlags2);
        }
Esempio n. 5
0
        public void Load(Stream stream)
        {
            using (var reader = new FileReader(stream))
            {
                MainHeader = reader.ReadStruct <Header>();
                PfHeader   = reader.ReadStruct <DDSPFHeader>();
                if (IsDX10)
                {
                    Dx10Header = reader.ReadStruct <DX10Header>();
                }

                int Dx10Size = Dx10Header != null ? 20 : 0;

                reader.TemporarySeek((int)(4 + MainHeader.Size + Dx10Size), SeekOrigin.Begin);
                ImageData = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));
            }
        }
 /// <summary>
 /// Encodes the DDS Header and if DX10, the DX10 Header
 /// </summary>
 /// <param name="header">DDS Header</param>
 /// <param name="dx10Header">DX10 Header</param>
 /// <returns>Resulting DDS File Header in bytes</returns>
 public static byte[] EncodeDDSHeader(DDSHeader header, DX10Header dx10Header)
 {
     // Create stream
     using (var output = new BinaryWriter(new MemoryStream()))
     {
         // Write DDS Magic
         output.Write(DDSHeader.DDSMagic);
         // Write Header
         output.Write(StructToBytes(header));
         // Check for DX10 Header
         if (header.PixelFormat.FourCC == PixelFormats.DX10.FourCC)
         {
             // Write Header
             output.Write(StructToBytes(dx10Header));
         }
         // Done
         return(((MemoryStream)(output.BaseStream)).ToArray());
     }
 }
Esempio n. 7
0
        public void SetFlags(DXGI_FORMAT Format)
        {
            header.flags = (uint)(DDSD.CAPS | DDSD.HEIGHT | DDSD.WIDTH | DDSD.PIXELFORMAT | DDSD.MIPMAPCOUNT | DDSD.LINEARSIZE);
            header.caps  = (uint)DDSCAPS.TEXTURE;
            if (header.mipmapCount > 1)
            {
                header.caps |= (uint)(DDSCAPS.COMPLEX | DDSCAPS.MIPMAP);
            }

            switch (Format)
            {
            case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM:
            case DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
                header.ddspf.flags       = (uint)(DDPF.RGB | DDPF.ALPHAPIXELS);
                header.ddspf.RGBBitCount = 0x8 * 4;
                header.ddspf.RBitMask    = 0x000000FF;
                header.ddspf.GBitMask    = 0x0000FF00;
                header.ddspf.BBitMask    = 0x00FF0000;
                header.ddspf.ABitMask    = 0xFF000000;
                pixelInternalFormat      = PixelInternalFormat.SrgbAlpha;
                pixelFormat = OpenTK.Graphics.OpenGL.PixelFormat.Rgba;
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM_SRGB:
            case DXGI_FORMAT.DXGI_FORMAT_BC1_UNORM:
                header.ddspf.flags  = (uint)DDPF.FOURCC;
                header.ddspf.fourCC = FOURCC_DXT1;
                pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM_SRGB:
            case DXGI_FORMAT.DXGI_FORMAT_BC2_UNORM:
                header.ddspf.flags  = (uint)DDPF.FOURCC;
                header.ddspf.fourCC = FOURCC_DXT3;
                pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM_SRGB:
            case DXGI_FORMAT.DXGI_FORMAT_BC3_UNORM:
                header.ddspf.flags  = (uint)DDPF.FOURCC;
                header.ddspf.fourCC = FOURCC_DXT5;
                pixelInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC4_UNORM:
            case DXGI_FORMAT.DXGI_FORMAT_BC4_SNORM:
                pixelInternalFormat = PixelInternalFormat.CompressedRedRgtc1;
                break;

            case DXGI_FORMAT.DXGI_FORMAT_BC5_UNORM:
            case DXGI_FORMAT.DXGI_FORMAT_BC5_SNORM:
            case DXGI_FORMAT.DXGI_FORMAT_BC6H_UF16:
            case DXGI_FORMAT.DXGI_FORMAT_BC6H_SF16:
            case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM:
            case DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM_SRGB:
                header.ddspf.flags  = (uint)DDPF.FOURCC;
                header.ddspf.fourCC = FOURCC_DX10;
                if (DX10header == null)
                {
                    DX10header = new DX10Header();
                }

                IsDX10 = true;
                DX10header.DXGI_Format = Format;
                break;
            }
        }
        /// <summary>
        /// Generates a DDS Header, and if requires, a DX10 Header
        /// </summary>
        /// <param name="metaData">Meta Data</param>
        /// <param name="flags">Flags</param>
        /// <param name="header">DDS Header Output</param>
        /// <param name="dx10Header">DX10 Header Output</param>
        public static void GenerateDDSHeader(TexMetadata metaData, DDSFlags flags, out DDSHeader header, out DX10Header dx10Header)
        {
            // Check array size
            if (metaData.ArraySize > 1)
            {
                // Check if we have an array and whether we're cube maps/non-2D
                if (metaData.ArraySize != 6 || metaData.Dimension != TexDimension.TEXTURE2D || !metaData.IsCubeMap())
                {
                    // Texture1D arrays, Texture2D arrays, and Cubemap arrays must be stored using 'DX10' extended header
                    flags |= DDSFlags.FORCEDX10EXT;
                }
            }

            // Check for DX10 Ext
            if (flags.HasFlag(DDSFlags.FORCEDX10EXTMISC2))
            {
                flags |= DDSFlags.FORCEDX10EXT;
            }
            // Create DDS Header
            header = new DDSHeader
            {
                // Set Data
                Size        = (uint)Marshal.SizeOf <DDSHeader>(),
                Flags       = DDSHeader.HeaderFlags.TEXTURE,
                Caps        = (uint)DDSHeader.SurfaceFlags.TEXTURE,
                PixelFormat = new DDSHeader.DDSPixelFormat(0, 0, 0, 0, 0, 0, 0, 0)
            };
            // Create DX10 Header
            dx10Header = new DX10Header();
            // Switch format
            switch (metaData.Format)
            {
            case DXGIFormat.R8G8B8A8UNORM:
                header.PixelFormat = PixelFormats.A8B8G8R8;
                break;

            case DXGIFormat.R16G16UNORM:
                header.PixelFormat = PixelFormats.G16R16;
                break;

            case DXGIFormat.R8G8UNORM:
                header.PixelFormat = PixelFormats.A8L8;
                break;

            case DXGIFormat.R16UNORM:
                header.PixelFormat = PixelFormats.L16;
                break;

            case DXGIFormat.R8UNORM:
                header.PixelFormat = PixelFormats.L8;
                break;

            case DXGIFormat.A8UNORM:
                header.PixelFormat = PixelFormats.A8;
                break;

            case DXGIFormat.R8G8B8G8UNORM:
                header.PixelFormat = PixelFormats.R8G8B8G8;
                break;

            case DXGIFormat.G8R8G8B8UNORM:
                header.PixelFormat = PixelFormats.G8R8G8B8;
                break;

            case DXGIFormat.BC1UNORM:
                header.PixelFormat = PixelFormats.DXT1;
                break;

            case DXGIFormat.BC2UNORM:
                header.PixelFormat = metaData.IsPMAlpha() ? (PixelFormats.DXT2) : (PixelFormats.DXT3);
                break;

            case DXGIFormat.BC3UNORM:
                header.PixelFormat = metaData.IsPMAlpha() ? (PixelFormats.DXT4) : (PixelFormats.DXT5);
                break;

            case DXGIFormat.BC4UNORM:
                header.PixelFormat = PixelFormats.BC4UNORM;
                break;

            case DXGIFormat.BC4SNORM:
                header.PixelFormat = PixelFormats.BC4SNORM;
                break;

            case DXGIFormat.BC5UNORM:
                header.PixelFormat = PixelFormats.BC5UNORM;
                break;

            case DXGIFormat.BC5SNORM:
                header.PixelFormat = PixelFormats.BC5SNORM;
                break;

            case DXGIFormat.B5G6R5UNORM:
                header.PixelFormat = PixelFormats.R5G6B5;
                break;

            case DXGIFormat.B5G5R5A1UNORM:
                header.PixelFormat = PixelFormats.A1R5G5B5;
                break;

            case DXGIFormat.R8G8SNORM:
                header.PixelFormat = PixelFormats.V8U8;
                break;

            case DXGIFormat.R8G8B8A8SNORM:
                header.PixelFormat = PixelFormats.Q8W8V8U8;
                break;

            case DXGIFormat.R16G16SNORM:
                header.PixelFormat = PixelFormats.V16U16;
                break;

            case DXGIFormat.B8G8R8A8UNORM:
                header.PixelFormat = PixelFormats.A8R8G8B8;
                break;

            case DXGIFormat.B8G8R8X8UNORM:
                header.PixelFormat = PixelFormats.X8R8G8B8;
                break;

            case DXGIFormat.B4G4R4A4UNORM:
                header.PixelFormat = PixelFormats.A4R4G4B4;
                break;

            case DXGIFormat.YUY2:
                header.PixelFormat = PixelFormats.YUY2;
                break;

            // Legacy D3DX formats using D3DFMT enum value as FourCC
            case DXGIFormat.R32G32B32A32FLOAT:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 116;      // D3DFMTA32B32G32R32F
                break;

            case DXGIFormat.R16G16B16A16FLOAT:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 113;      // D3DFMTA16B16G16R16F
                break;

            case DXGIFormat.R16G16B16A16UNORM:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 36;      // D3DFMTA16B16G16R16
                break;

            case DXGIFormat.R16G16B16A16SNORM:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 110;      // D3DFMTQ16W16V16U16
                break;

            case DXGIFormat.R32G32FLOAT:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 115;      // D3DFMTG32R32F
                break;

            case DXGIFormat.R16G16FLOAT:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 112;      // D3DFMTG16R16F
                break;

            case DXGIFormat.R32FLOAT:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 114;      // D3DFMTR32F
                break;

            case DXGIFormat.R16FLOAT:
                header.PixelFormat.Flags = PixelFormats.DDSFOURCC; header.PixelFormat.FourCC = 111;      // D3DFMTR16F
                break;

            default:
                break;
            }
            // Check for mips
            if (metaData.MipLevels > 0)
            {
                // Set flag
                header.Flags |= DDSHeader.HeaderFlags.MIPMAP;
                // Check size
                if (metaData.MipLevels > UInt16.MaxValue)
                {
                    throw new ArgumentException(String.Format("Too many mipmaps: {0}. Max: {1}", metaData.MipLevels, UInt16.MaxValue));
                }
                // Set
                header.MipMapCount = (uint)metaData.MipLevels;
                // Check count
                if (header.MipMapCount > 1)
                {
                    header.Caps |= (uint)DDSHeader.SurfaceFlags.MIPMAP;
                }
            }

            // Switch Dimension
            switch (metaData.Dimension)
            {
            case TexDimension.TEXTURE1D:
            {
                // Check size
                if (metaData.Width > Int32.MaxValue)
                {
                    throw new ArgumentException(String.Format("Image Width too large: {0}. Max: {1}", metaData.Width, Int32.MaxValue));
                }
                // Set
                header.Width  = (uint)metaData.Width;
                header.Height = header.Depth = 1;
                // Check size
                break;
            }

            case TexDimension.TEXTURE2D:
            {
                // Check size
                if (metaData.Width > Int32.MaxValue || metaData.Height > Int32.MaxValue)
                {
                    throw new ArgumentException(String.Format("Image Width and/or Height too large: {0}x{1}. Max: {2}",
                                                              metaData.Width,
                                                              metaData.Height,
                                                              Int32.MaxValue));
                }
                // Set
                header.Width  = (uint)metaData.Width;
                header.Height = (uint)metaData.Height;
                header.Depth  = 1;
                // Check size
                break;
            }

            case TexDimension.TEXTURE3D:
            {
                // Check size
                if (metaData.Width > Int32.MaxValue || metaData.Height > Int32.MaxValue)
                {
                    throw new ArgumentException(String.Format("Image Width and/or Height too large: {0}x{1}. Max: {2}",
                                                              metaData.Width,
                                                              metaData.Height,
                                                              Int32.MaxValue));
                }
                // Check size
                if (metaData.Depth > UInt16.MaxValue)
                {
                    throw new ArgumentException(String.Format("Image Depth too large: {0}. Max: {1}", metaData.Depth, UInt16.MaxValue));
                }
                // Set
                header.Flags |= DDSHeader.HeaderFlags.VOLUME;
                header.Caps2 |= 0x00200000;
                header.Width  = (uint)metaData.Width;
                header.Height = (uint)metaData.Height;
                header.Depth  = (uint)metaData.Depth;
                // Check size
                break;
            }

            default:
                throw new ArgumentException("Invalid Texture Dimension.");
            }
            // Calculate the Pitch
            ComputePitch(metaData.Format, metaData.Width, metaData.Height, out long rowPitch, out long slicePitch, CPFLAGS.NONE);
            // Validate results
            if (slicePitch > UInt32.MaxValue || rowPitch > UInt32.MaxValue)
            {
                throw new ArgumentException("Failed to calculate row and/or slice pitch, values returned were too large");
            }
            // Check is it compressed
            if (IsCompressed(metaData.Format))
            {
                header.Flags            |= DDSHeader.HeaderFlags.LINEARSIZE;
                header.PitchOrLinearSize = (uint)slicePitch;
            }
            else
            {
                header.Flags            |= DDSHeader.HeaderFlags.PITCH;
                header.PitchOrLinearSize = (uint)rowPitch;
            }

            // Check for do we need to create the DX10 Header
            if (header.PixelFormat.Size == 0)
            {
                // Check size
                if (metaData.ArraySize > UInt16.MaxValue)
                {
                    throw new ArgumentException(String.Format("Array Size too large: {0}. Max: {1}", metaData.ArraySize, UInt16.MaxValue));
                }
                // Set Pixel format
                header.PixelFormat = PixelFormats.DX10;
                // Set Data
                dx10Header.Format            = metaData.Format;
                dx10Header.ResourceDimension = metaData.Dimension;
                dx10Header.MiscFlag          = metaData.MiscFlags & ~TexMiscFlags.TEXTURECUBE;
                dx10Header.ArraySize         = (uint)metaData.ArraySize;
                // Check for Cube Maps
                if (metaData.MiscFlags.HasFlag(TexMiscFlags.TEXTURECUBE))
                {
                    // Check array size, must be a multiple of 6 for cube maps
                    if ((metaData.ArraySize % 6) != 0)
                    {
                        throw new ArgumentException("Array size must be a multiple of 6");
                    }
                    // Set Flag
                    dx10Header.MiscFlag  |= TexMiscFlags.TEXTURECUBE;
                    dx10Header.ArraySize /= 6;
                }
                // Check for mist flags
                if (flags.HasFlag(DDSFlags.FORCEDX10EXTMISC2))
                {
                    // This was formerly 'reserved'. D3DX10 and D3DX11 will fail if this value is anything other than 0
                    dx10Header.MiscFlags2 = (uint)metaData.MiscFlags2;
                }
            }
        }
Esempio n. 9
0
 public DDS()
 {
     MainHeader = new Header();
     PfHeader   = new DDSPFHeader();
     Dx10Header = new DX10Header();
 }
Esempio n. 10
0
        // Methods
        public override void Load(Stream fileStream)
        {
            // Signature
            var reader = new ExtendedBinaryReader(
                fileStream, Encoding.ASCII, false);

            string sig = reader.ReadSignature(4);

            if (sig != Signature)
            {
                throw new InvalidSignatureException(Signature, sig);
            }

            // Header
            Header = new DDSHeader()
            {
                Size  = reader.ReadUInt32(),
                Flags = reader.ReadUInt32()
            };

            if (!Header.HasFlag(DDSHeader.FLAGS.CAPS) ||
                !Header.HasFlag(DDSHeader.FLAGS.WIDTH) ||
                !Header.HasFlag(DDSHeader.FLAGS.HEIGHT) ||
                !Header.HasFlag(DDSHeader.FLAGS.PIXEL_FORMAT))
            {
                throw new Exception(
                          "Could not load DDS file. Required header flags are missing!");
            }

            Height = reader.ReadUInt32();
            Width  = reader.ReadUInt32();

            Header.PitchOrLinearSize = reader.ReadUInt32();
            Header.Depth             = reader.ReadUInt32();
            Header.MipmapCount       = reader.ReadUInt32();

            reader.JumpAhead(44); // Skip past padding
            Header.PixelFormat = new DDSPixelFormat(reader);

            Header.Caps  = reader.ReadUInt32();
            Header.Caps2 = reader.ReadUInt32();
            Header.Caps3 = reader.ReadUInt32();
            Header.Caps4 = reader.ReadUInt32();

            reader.JumpTo(Header.Size + 4, true);

            // Depth
            uint depth = 1;

            if (Header.HasFlag(DDSHeader.FLAGS.DEPTH) &&
                Header.HasFlag(DDSHeader.CAPS2.VOLUME))
            {
                depth = Header.Depth;

                // TODO
                throw new NotImplementedException(
                          "Reading 3D textures from DDS files is not yet supported.");
            }
            else if (Header.HasFlag(DDSHeader.CAPS2.CUBEMAP))
            {
                depth = 6;

                // TODO
                throw new NotImplementedException(
                          "Reading DDS cubemaps is not yet supported.");
            }

            // MipMaps
            uint mipmapCount = 1;

            if (Header.HasFlag(DDSHeader.FLAGS.MIPMAP_COUNT) &&
                Header.HasFlag(DDSHeader.CAPS.MIPMAP))
            {
                mipmapCount = Header.MipmapCount;
            }

            MipmapCount = mipmapCount;

            // Caps
            if (!Header.HasFlag(DDSHeader.CAPS.TEXTURE))
            {
                throw new Exception(
                          "Could not load DDS file. Required CAPS flag is missing!");
            }
            // TODO

            // Caps2
            // TODO

            // DX10 Header/Pixel Format
            uint pixelsPerBlock = 16;
            byte blockSize;

            if (Header.PixelFormat.HasFlag(DDSPixelFormat.FLAGS.FOURCC))
            {
                switch ((DDSPixelFormat.FOURCCS)Header.PixelFormat.FourCC)
                {
                // DX10 Header
                case DDSPixelFormat.FOURCCS.DX10:
                {
                    var dx10Header = new DX10Header(reader);
                    depth = dx10Header.ArraySize;

                    switch ((DX10Header.DXGI_FORMATS)dx10Header.DXGIFormat)
                    {
                    // BC1
                    case DX10Header.DXGI_FORMATS.BC1_TYPELESS:
                    case DX10Header.DXGI_FORMATS.BC1_UNORM:
                        CompressionFormat = CompressionFormats.RGB_S3TC_DXT1_EXT;
                        blockSize         = 8;
                        break;

                    // BC3
                    case DX10Header.DXGI_FORMATS.BC3_TYPELESS:
                    case DX10Header.DXGI_FORMATS.BC3_UNORM:
                        CompressionFormat = CompressionFormats.RGBA_S3TC_DXT3_EXT;
                        blockSize         = 16;
                        break;

                    // BC5
                    case DX10Header.DXGI_FORMATS.BC5_TYPELESS:
                    case DX10Header.DXGI_FORMATS.BC5_SNORM:
                    case DX10Header.DXGI_FORMATS.BC5_UNORM:
                        CompressionFormat = CompressionFormats.RGBA_S3TC_DXT5_EXT;
                        blockSize         = 16;
                        break;

                    // BC7
                    case DX10Header.DXGI_FORMATS.BC7_TYPELESS:
                    case DX10Header.DXGI_FORMATS.BC7_UNORM:
                        CompressionFormat = CompressionFormats.RGBA_BPTC_UNORM_EXT;
                        blockSize         = 16;
                        break;

                    case DX10Header.DXGI_FORMATS.BC7_UNORM_SRGB:
                        CompressionFormat = CompressionFormats.SRGB_ALPHA_BPTC_UNORM_EXT;
                        blockSize         = 16;
                        break;

                    // TODO: Add support for BC1 SRGB, BC2, BC3 SRGB, BC4, and BC6
                    default:
                        throw new NotImplementedException(string.Format(
                                                              "Reading DX10 DXGI type \"{0}\" is not yet supported.",
                                                              dx10Header.DXGIFormat));
                    }

                    break;
                }

                // DXT1
                case DDSPixelFormat.FOURCCS.DXT1:
                    CompressionFormat = CompressionFormats.RGB_S3TC_DXT1_EXT;
                    blockSize         = 8;
                    break;

                // DXT3
                case DDSPixelFormat.FOURCCS.DXT3:
                    CompressionFormat = CompressionFormats.RGBA_S3TC_DXT3_EXT;
                    blockSize         = 16;
                    break;

                // DXT5
                case DDSPixelFormat.FOURCCS.DXT5:
                case DDSPixelFormat.FOURCCS.ATI2:
                case DDSPixelFormat.FOURCCS.BC5S:
                    CompressionFormat = CompressionFormats.RGBA_S3TC_DXT5_EXT;
                    blockSize         = 16;
                    break;

                // TODO: Add support for DXT2 and DXT4
                default:
                    throw new NotImplementedException(string.Format("{0} \"{1}\" {2}",
                                                                    "Reading DDS files with FOURCC",
                                                                    Header.PixelFormat.FourCC,
                                                                    "is not yet supported."));
                }
            }
            else
            {
                if (!Header.PixelFormat.HasFlag(DDSPixelFormat.FLAGS.RGB))
                {
                    throw new NotImplementedException(
                              "Reading DDS files without RGB data is not yet supported.");
                }

                if (Header.PixelFormat.RGBBitCount % 8 != 0)
                {
                    throw new InvalidDataException(
                              "RGBBitCount must be divisible by 8.");
                }

                if (Header.PixelFormat.RGBBitCount > 32)
                {
                    throw new InvalidDataException(
                              "RGBBitCount must be less than or equal to 32.");
                }

                if (Header.PixelFormat.RGBBitCount != 32)
                {
                    throw new NotImplementedException(
                              "Reading DDS files with non 32-bit data is not yet supported.");
                }

                pixelsPerBlock    = 1;
                CompressionFormat = CompressionFormats.None;
                blockSize         = (byte)(Header.PixelFormat.RGBBitCount / 8);
                PixelFormat       = PixelFormats.RGBA;
            }

            // Whether or not uncompressed pixels need to be re-arranged to RGBA
            bool isARGB = (CompressionFormat == CompressionFormats.None &&
                           Header.PixelFormat.RGBBitCount == 32 &&
                           Header.PixelFormat.ABitMask == 0xFF000000 &&
                           Header.PixelFormat.RBitMask == 0xFF0000 &&
                           Header.PixelFormat.GBitMask == 0xFF00 &&
                           Header.PixelFormat.BBitMask == 0xFF);

            // Data
            uint width = Width, height = Height;

            ColorData = new byte[mipmapCount * depth][];

            for (uint slice = 0; slice < depth; ++slice)
            {
                for (uint level = 0; level < mipmapCount; ++level)
                {
                    // Pad out width/height to 4x4 blocks
                    if (CompressionFormat != CompressionFormats.None)
                    {
                        if (width % 4 != 0)
                        {
                            width = ((width / 4) + 1) * 4;
                        }

                        if (height % 4 != 0)
                        {
                            height = ((height / 4) + 1) * 4;
                        }
                    }

                    // Compute size of this block
                    uint size = ((width * height) / pixelsPerBlock) * blockSize;

                    // Re-arrange uncompressed pixels to RGBA8 format if necessary
                    if (isARGB)
                    {
                        uint p;
                        ColorData[level] = new byte[size];

                        for (uint i = 0; i < size; i += 4)
                        {
                            // Convert from ARGB8 to RGBA8
                            p = reader.ReadUInt32();
                            ColorData[level][i]     = (byte)((p & Header.PixelFormat.RBitMask) >> 16);
                            ColorData[level][i + 1] =
                                (byte)((p & Header.PixelFormat.GBitMask) >> 8);

                            ColorData[level][i + 2] = (byte)(p & Header.PixelFormat.BBitMask);
                            ColorData[level][i + 3] =
                                (byte)((p & Header.PixelFormat.ABitMask) >> 24);
                        }
                    }

                    // Otherwise, simply read the block
                    else
                    {
                        ColorData[level] = reader.ReadBytes((int)size);
                    }

                    // Divide width/height by 2 for the next mipmap
                    width  /= 2;
                    height /= 2;
                }
            }
        }
Esempio n. 11
0
        public void SetFlags(TexFormat format, bool isDX10, bool isCubemap)
        {
            var dxgiFormat = (DXGI_FORMAT)format;

            MainHeader.Flags = (uint)(DDSD.CAPS | DDSD.HEIGHT | DDSD.WIDTH | DDSD.PIXELFORMAT | DDSD.MIPMAPCOUNT | DDSD.LINEARSIZE);
            PfHeader.Caps1   = (uint)DDSCAPS.TEXTURE;
            if (MainHeader.MipCount > 1)
            {
                PfHeader.Caps1 |= (uint)(DDSCAPS.COMPLEX | DDSCAPS.MIPMAP);
            }

            if (isCubemap)
            {
                PfHeader.Caps2 |= (uint)(DDSCAPS2.CUBEMAP | DDSCAPS2.CUBEMAP_POSITIVEX | DDSCAPS2.CUBEMAP_NEGATIVEX |
                                         DDSCAPS2.CUBEMAP_POSITIVEY | DDSCAPS2.CUBEMAP_NEGATIVEY |
                                         DDSCAPS2.CUBEMAP_POSITIVEZ | DDSCAPS2.CUBEMAP_NEGATIVEZ);
            }
            if (isDX10)
            {
                PfHeader.Flags  = (uint)DDPF.FOURCC;
                PfHeader.FourCC = FOURCC_DX10;

                Dx10Header.DxgiFormat = (uint)dxgiFormat;
                if (isCubemap)
                {
                    Dx10Header.ArrayCount = (ArrayCount / 6);
                    Dx10Header.MiscFlags1 = 0x4;
                }
                return;
            }

            var masks = DDS_RGBA.GetMasks(format);

            PfHeader.RBitMask = masks[0];
            PfHeader.GBitMask = masks[1];
            PfHeader.BBitMask = masks[2];
            PfHeader.ABitMask = masks[3];

            PfHeader.RgbBitCount = 0x8 * TextureFormatHelper.GetBytesPerPixel(format);
            PfHeader.Flags       = (uint)(DDPF.RGB | DDPF.ALPHAPIXELS);

            switch (format)
            {
            case TexFormat.RGBA8_UNORM:
            case TexFormat.RGB8_SRGB:
                break;

            case TexFormat.RGB565_UNORM:
                PfHeader.Flags = (uint)(DDPF.RGB | DDPF.ALPHAPIXELS);
                break;

            case TexFormat.BC1_SRGB:
            case TexFormat.BC1_UNORM:
                PfHeader.Flags  = (uint)DDPF.FOURCC;
                PfHeader.FourCC = FOURCC_DXT1;
                break;

            case TexFormat.BC2_SRGB:
            case TexFormat.BC2_UNORM:
                PfHeader.Flags  = (uint)DDPF.FOURCC;
                PfHeader.FourCC = FOURCC_DXT3;
                break;

            case TexFormat.BC3_SRGB:
            case TexFormat.BC3_UNORM:
                PfHeader.Flags  = (uint)DDPF.FOURCC;
                PfHeader.FourCC = FOURCC_DXT5;
                break;

            case TexFormat.BC4_UNORM:
                PfHeader.Flags  = (uint)DDPF.FOURCC;
                PfHeader.FourCC = FOURCC_BC4U;
                break;

            case TexFormat.BC4_SNORM:
                PfHeader.Flags  = (uint)DDPF.FOURCC;
                PfHeader.FourCC = FOURCC_BC4S;
                break;

            case TexFormat.BC5_UNORM:
                PfHeader.Flags  = (uint)DDPF.FOURCC;
                PfHeader.FourCC = FOURCC_BC5U;
                break;

            case TexFormat.BC5_SNORM:
                PfHeader.Flags  = (uint)DDPF.FOURCC;
                PfHeader.FourCC = FOURCC_BC5S;
                break;

            case TexFormat.BC6H_SF16:
            case TexFormat.BC6H_UF16:
            case TexFormat.BC7_UNORM:
            case TexFormat.BC7_SRGB:
                PfHeader.Flags  = (uint)DDPF.FOURCC;
                PfHeader.FourCC = FOURCC_DX10;
                if (Dx10Header == null)
                {
                    Dx10Header = new DX10Header();
                }

                Dx10Header.DxgiFormat = (uint)dxgiFormat;
                break;
            }
        }