private static Texture CreateTextureFromDds( GraphicsDevice graphicsDevice, DdsFile ddsFile) { var mipMapData = new TextureMipMapData[ddsFile.Header.MipMapCount]; for (var i = 0; i < ddsFile.Header.MipMapCount; i++) { mipMapData[i] = new TextureMipMapData { Data = ddsFile.MipMaps[i].Data, BytesPerRow = (int)ddsFile.MipMaps[i].RowPitch }; } var width = (int)ddsFile.Header.Width; var height = (int)ddsFile.Header.Height; // BC3 texture dimensions need to be aligned to a multiple of 4. if (ddsFile.ImageFormat == DdsImageFormat.Bc3) { width = Math.Max(width, 4); height = Math.Max(height, 4); } return(Texture.CreateTexture2D( graphicsDevice, ddsFile.PixelFormat, width, height, mipMapData)); }
public static TextureMipMapData[] GenerateMipMaps( int width, int height, byte[] rgbaData) { var numLevels = CalculateMipMapCount(width, height); var mipMapData = new TextureMipMapData[numLevels]; int previousWidth = -1, previousHeight = -1; for (int level = 0; level < numLevels; level++) { if (level > 0) { var levelData = new byte[width * height * ByteRgba.BytesPerPixel]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int previousLevelX = x * (previousWidth / width); int previousLevelY = y * (previousHeight / height); var moreDetailedMipLevel = mipMapData[level - 1]; var c00 = ByteRgba.FromByteArray(moreDetailedMipLevel.Data, previousLevelX, previousLevelY, previousWidth); var c10 = ByteRgba.FromByteArray(moreDetailedMipLevel.Data, ClampToDimension(previousLevelX + 1, previousWidth), previousLevelY, previousWidth); var c01 = ByteRgba.FromByteArray(moreDetailedMipLevel.Data, previousLevelX, ClampToDimension(previousLevelY + 1, previousHeight), previousWidth); var c11 = ByteRgba.FromByteArray(moreDetailedMipLevel.Data, ClampToDimension(previousLevelX + 1, previousWidth), ClampToDimension(previousLevelY + 1, previousHeight), previousWidth); var interpolatedColor = ByteRgba.Average(c00, c10, c01, c11); interpolatedColor.CopyTo(levelData, x, y, width); } } mipMapData[level] = new TextureMipMapData { Data = levelData, BytesPerRow = width * ByteRgba.BytesPerPixel }; } else { mipMapData[level] = new TextureMipMapData { Data = rgbaData, BytesPerRow = width * ByteRgba.BytesPerPixel }; } previousWidth = width; previousHeight = height; width = Math.Max((int)Math.Floor(width / 2.0), 1); height = Math.Max((int)Math.Floor(height / 2.0), 1); } return(mipMapData); }
private uint GetTextureIndex(Texture texture) { if (!_nameToTextureIndex.TryGetValue(texture, out var result)) { if (_nextTextureIndex == MaxTextures || texture.Width != texture.Height || texture.Width != TextureSize) { throw new InvalidOperationException(); } result = _nextTextureIndex; _nameToTextureIndex.Add(texture, _nextTextureIndex); var commandList = _graphicsDevice.ResourceFactory.CreateCommandList(); commandList.Begin(); for (var mipLevel = 0u; mipLevel < TextureMipLevels; mipLevel++) { var mipSize = TextureMipMapData.CalculateMipSize(mipLevel, TextureSize); commandList.CopyTexture( texture, 0, 0, 0, mipLevel, 0, TextureArray, 0, 0, 0, mipLevel, _nextTextureIndex, mipSize, mipSize, 1, 1); } commandList.End(); _graphicsDevice.SubmitCommands(commandList); _graphicsDevice.DisposeWhenIdle(commandList); _graphicsDevice.WaitForIdle(); _nextTextureIndex++; } return(result); }
private static Texture CreateTextureFromDds( GraphicsDevice graphicsDevice, ResourceUploadBatch uploadBatch, DdsFile ddsFile) { var mipMapData = new TextureMipMapData[ddsFile.Header.MipMapCount]; for (var i = 0; i < ddsFile.Header.MipMapCount; i++) { mipMapData[i] = new TextureMipMapData { Data = ddsFile.MipMaps[i].Data, BytesPerRow = (int)ddsFile.MipMaps[i].RowPitch }; } return(Texture.CreateTexture2D( graphicsDevice, uploadBatch, ToPixelFormat(ddsFile.ImageFormat), (int)ddsFile.Header.Width, (int)ddsFile.Header.Height, mipMapData)); }
public static DdsFile FromStream(Stream stream) { using (var reader = new BinaryReader(stream, Encoding.ASCII, true)) { var magic = reader.ReadFourCc(); if (magic != "DDS ") { throw new InvalidDataException(); } var header = DdsHeader.Parse(reader); DdsImageFormat imageFormat; if (header.PixelFormat.Flags.HasFlag(DdsPixelFormatFlags.FourCc)) { imageFormat = GetImageFormat(header.PixelFormat.FourCc); } else if (header.PixelFormat.Flags.HasFlag(DdsPixelFormatFlags.BumpDuDv)) { imageFormat = DdsImageFormat.Rg8SNorm; } else if (header.PixelFormat.Flags.HasFlag(DdsPixelFormatFlags.Rgb)) { imageFormat = DdsImageFormat.Rgba8; } else { throw new InvalidDataException(); } var dimension = DdsTextureDimension.Texture2D; var arraySize = 1u; if (header.Flags.HasFlag(DdsHeaderFlags.Depth) && header.Caps2.HasFlag(DdsCaps2.Volume)) { dimension = DdsTextureDimension.Texture3D; } else if (header.Caps2.HasFlag(DdsCaps2.CubeMap)) { dimension = DdsTextureDimension.TextureCube; if (!header.Caps2.HasFlag(DdsCaps2.AllCubeMapFaces)) { throw new InvalidDataException(); } arraySize = 6; } var isCompressed = imageFormat == DdsImageFormat.Bc1 || imageFormat == DdsImageFormat.Bc2 || imageFormat == DdsImageFormat.Bc3; var mipMapCount = header.MipMapCount; if (mipMapCount == 0) { mipMapCount = 1; } var mipMaps = new TextureMipMapData[mipMapCount * arraySize]; for (var arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) { var width = header.Width; var height = header.Height; if (isCompressed) { // Ensure width and height are multiple of 4. width = (width + 3) / 4 * 4; height = (height + 3) / 4 * 4; } var depth = Math.Max(header.Depth, 1); for (var i = 0; i < mipMapCount; i++) { var surfaceInfo = GetSurfaceInfo(width, height, imageFormat, header); var numSurfaceBytes = surfaceInfo.NumBytes * depth; var mipMapData = reader.ReadBytes((int)numSurfaceBytes); if (mipMapData.Length != numSurfaceBytes) { throw new InvalidDataException(); } // Set alpha bytes for 32-bit rgb images that don't include alpha data. if (imageFormat == DdsImageFormat.Rgba8 && !header.PixelFormat.Flags.HasFlag(DdsPixelFormatFlags.AlphaPixels)) { for (var j = 0; j < mipMapData.Length; j += 4) { mipMapData[j + 3] = 255; } } mipMaps[(arrayIndex * mipMapCount) + i] = new TextureMipMapData( mipMapData, surfaceInfo.RowBytes, surfaceInfo.NumBytes, width, height); width >>= 1; height >>= 1; depth >>= 1; if (isCompressed) { // Round width and height down to multiple of 4. width -= width % 4; height -= height % 4; width = Math.Max(width, 4); height = Math.Max(height, 4); } else { width = Math.Max(width, 1); height = Math.Max(height, 1); } depth = Math.Max(depth, 1); } } return(new DdsFile { Header = header, Dimension = dimension, ImageFormat = imageFormat, ArraySize = arraySize, MipMapCount = mipMapCount, MipMaps = mipMaps }); } }