private static void WriteHeader(Stream stream, DDS_HEADER header, DDS_HEADER_DXT10 dxt10header) { stream.Write(BitConverter.GetBytes(DDS_MAGIC), 0, 4); stream.WriteStruct(header); if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', '1', '0')) { stream.WriteStruct(dxt10header); } }
private static (DDS_HEADER, DDS_HEADER_DXT10) GenerateHeader(DDSMetadata metadata) { var height = metadata.Height; var width = metadata.Width; var mipscount = metadata.Mipscount; var iscubemap = metadata.Iscubemap; var format = metadata.Format; bool dxt10 = false; var ddspf = new DDS_PIXELFORMAT() { dwSize = PIXELFORMAT_SIZE, dwFlags = 0, dwFourCC = 0, dwRGBBitCount = 0, dwRBitMask = 0, dwGBitMask = 0, dwBBitMask = 0, dwABitMask = 0 }; var header = new DDS_HEADER() { dwSize = HEADER_SIZE, dwFlags = DDS_HEADER_FLAGS_TEXTURE, dwHeight = height, dwWidth = width, dwPitchOrLinearSize = 0, dwDepth = 0, dwMipMapCount = 0, dwReserved1 = 0, dwReserved2 = 0, dwReserved3 = 0, dwReserved4 = 0, dwReserved5 = 0, dwReserved6 = 0, dwReserved7 = 0, dwReserved8 = 0, dwReserved9 = 0, dwReserved10 = 0, dwReserved11 = 0, ddspf = ddspf, dwCaps = DDSCAPS_TEXTURE, dwCaps2 = 0, dwCaps3 = 0, dwCaps4 = 0, dwReserved12 = 0, }; var dxt10header = new DDS_HEADER_DXT10() { dxgiFormat = 0, resourceDimension = D3D10_RESOURCE_DIMENSION.D3D10_RESOURCE_DIMENSION_TEXTURE2D, miscFlag = 0, arraySize = metadata.Slicecount, miscFlags2 = 0 }; if (mipscount > 0) { header.dwMipMapCount = mipscount; } // pixelformat { // dwFourCC switch (format) { case EFormat.R8G8B8A8_UNORM: SetPixelmask(DDSPF_A8R8G8B8, ref ddspf); break; case EFormat.BC1_UNORM: ddspf.dwFourCC = MAKEFOURCC('D', 'X', 'T', '1'); break; case EFormat.BC2_UNORM: ddspf.dwFourCC = MAKEFOURCC('D', 'X', 'T', '3'); break; case EFormat.BC3_UNORM: ddspf.dwFourCC = MAKEFOURCC('D', 'X', 'T', '5'); break; case EFormat.BC4_UNORM: ddspf.dwFourCC = MAKEFOURCC('B', 'C', '4', 'U'); break; case EFormat.BC5_UNORM: ddspf.dwFourCC = MAKEFOURCC('B', 'C', '5', 'U'); break; case EFormat.BC7_UNORM: dxt10 = true; break; //case EFormat.R32G32B32A32_FLOAT: //case EFormat.R16G16B16A16_FLOAT: //case EFormat.BC6H_UF16: default: throw new MissingFormatException($"Missing Format: {format}"); } if (dxt10) { ddspf.dwFourCC = MAKEFOURCC('D', 'X', '1', '0'); } // dwflags if (ddspf.dwABitMask != 0) // check this { ddspf.dwFlags |= DDPF_ALPHAPIXELS; } /*if (ddspf.dwABitMask != 0) * ddspf.dwFlags |= DDPF_ALPHA;*///old if (ddspf.dwFourCC != 0) { ddspf.dwFlags |= DDPF_FOURCC; } if (ddspf.dwRGBBitCount != 0 && (ddspf.dwRBitMask != 0 || ddspf.dwGBitMask != 0 || ddspf.dwBBitMask != 0)) { ddspf.dwFlags |= DDPF_RGB; } if (metadata.Normal) { ddspf.dwFlags |= DDPF_NORMAL; //custom nv flag } header.ddspf = ddspf; } // dwPitchOrLinearSize uint p = 0; switch (format) { case EFormat.R8G8B8A8_UNORM: var bpp = ddspf.dwRGBBitCount; header.dwPitchOrLinearSize = (width * bpp + 7) / 8; header.dwFlags |= DDSD_PITCH; break; case EFormat.BC1_UNORM: case EFormat.BC4_UNORM: p = width * height / 2; //max(1,width ?4)x max(1,height ?4)x 8 (DXT1) header.dwPitchOrLinearSize = (uint)(p); header.dwFlags |= DDSD_LINEARSIZE; break; case EFormat.BC2_UNORM: case EFormat.BC3_UNORM: case EFormat.BC5_UNORM: case EFormat.BC7_UNORM: p = width * height; //max(1,width ?4)x max(1,height ?4)x 16 (DXT2-5) header.dwPitchOrLinearSize = (uint)(p); header.dwFlags |= DDSD_LINEARSIZE; break; //case EFormat.BC6H_UF16: //case EFormat.R32G32B32A32_FLOAT: //case EFormat.R16G16B16A16_FLOAT: default: throw new MissingFormatException($"Missing Format: {format}"); } // unused R8G8_B8G8, G8R8_G8B8, legacy UYVY-packed, and legacy YUY2-packed formats, // header.dwPitchOrLinearSize = ((width + 1) >> 1) * 4; // depth //if (slicecount > 0 && !iscubemap) // header.dwDepth = slicecount; // caps if (iscubemap || mipscount > 0) { header.dwCaps |= DDSCAPS_COMPLEX; } if (mipscount > 0) { header.dwCaps |= DDSCAPS_MIPMAP; } // caps2 if (iscubemap) { header.dwCaps2 |= DDSCAPS2_CUBEMAP_ALL_FACES | DDSCAPS2_CUBEMAP; } //if (slicecount > 0) // header.dwCaps2 |= DDSCAPS2_VOLUME; // flags //if (slicecount > 0) // header.dwFlags |= DDSD_DEPTH; if (mipscount > 0) { header.dwFlags |= DDSD_MIPMAPCOUNT; } // DXT10 if (dxt10) { // dxgiFormat switch (format) { case EFormat.BC7_UNORM: { dxt10header.dxgiFormat = DXGI_FORMAT.DXGI_FORMAT_BC7_UNORM; break; } default: { throw new MissingFormatException($"Missing Format: {format}"); } } // resourceDimension //if (slicecount > 0) // dxt10header.resourceDimension = D3D10_RESOURCE_DIMENSION.D3D10_RESOURCE_DIMENSION_TEXTURE3D; //misc flag if (iscubemap) { dxt10header.miscFlag |= DDS_RESOURCE_MISC_TEXTURECUBE; } if (mipscount > 0) { dxt10header.miscFlag |= D3D10_RESOURCE_MISC_GENERATE_MIPS; } // array size if (iscubemap) { dxt10header.arraySize = metadata.Slicecount; } // miscFlags2 } return(header, dxt10header); }