protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { Texture2D texture = null; SurfaceFormat surfaceFormat; if (reader.version < 5) { SurfaceFormatLegacy legacyFormat = (SurfaceFormatLegacy)reader.ReadInt32(); switch (legacyFormat) { case SurfaceFormatLegacy.Dxt1: surfaceFormat = SurfaceFormat.Dxt1; break; case SurfaceFormatLegacy.Dxt3: surfaceFormat = SurfaceFormat.Dxt3; break; case SurfaceFormatLegacy.Dxt5: surfaceFormat = SurfaceFormat.Dxt5; break; case SurfaceFormatLegacy.Color: surfaceFormat = SurfaceFormat.Color; break; default: throw new NotSupportedException("Unsupported legacy surface format."); } } else { surfaceFormat = (SurfaceFormat)reader.ReadInt32(); } int width = (reader.ReadInt32()); int height = (reader.ReadInt32()); int levelCount = (reader.ReadInt32()); int levelCountOutput = levelCount; // If the system does not fully support Power of Two textures, // skip any mip maps supplied with any non PoT textures. if (levelCount > 1 && !reader.GraphicsDevice.GraphicsCapabilities.SupportsNonPowerOfTwo && (!MathHelper.IsPowerOfTwo(width) || !MathHelper.IsPowerOfTwo(height))) { levelCountOutput = 1; System.Diagnostics.Debug.WriteLine( "Device does not support non Power of Two textures. Skipping mipmaps."); } SurfaceFormat convertedFormat = surfaceFormat; switch (surfaceFormat) { #if IOS // At the moment. If a DXT Texture comes in on iOS, it's really a PVR compressed // texture. We need to use this hack until the content pipeline is implemented. // For now DXT5 means we're using 4bpp PVRCompression and DXT3 means 2bpp. Look at // PvrtcBitmapContent.cs for more information.: case SurfaceFormat.Dxt3: convertedFormat = SurfaceFormat.RgbaPvrtc2Bpp; break; case SurfaceFormat.Dxt5: convertedFormat = SurfaceFormat.RgbaPvrtc4Bpp; break; #else case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsDxt1) { convertedFormat = SurfaceFormat.Color; } break; case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc) { convertedFormat = SurfaceFormat.Color; } break; #endif case SurfaceFormat.NormalizedByte4: convertedFormat = SurfaceFormat.Color; break; } if (existingInstance == null) { texture = new Texture2D(reader.GraphicsDevice, width, height, levelCountOutput > 1, convertedFormat); } else { texture = existingInstance; } for (int level = 0; level < levelCount; level++) { int levelDataSizeInBytes = (reader.ReadInt32()); byte[] levelData = reader.ReadBytes(levelDataSizeInBytes); int levelWidth = width >> level; int levelHeight = height >> level; if (level >= levelCountOutput) { continue; } //Convert the image data if required switch (surfaceFormat) { #if !IOS case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsDxt1) { levelData = DxtUtil.DecompressDxt1(levelData, levelWidth, levelHeight); } break; case SurfaceFormat.Dxt3: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc) { levelData = DxtUtil.DecompressDxt3(levelData, levelWidth, levelHeight); } break; case SurfaceFormat.Dxt5: if (!reader.GraphicsDevice.GraphicsCapabilities.SupportsS3tc) { levelData = DxtUtil.DecompressDxt5(levelData, levelWidth, levelHeight); } break; #endif case SurfaceFormat.Bgr565: { /* * // BGR -> BGR * int offset = 0; * for (int y = 0; y < levelHeight; y++) * { * for (int x = 0; x < levelWidth; x++) * { * ushort pixel = BitConverter.ToUInt16(levelData, offset); * pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12)); * levelData[offset] = (byte)(pixel); * levelData[offset + 1] = (byte)(pixel >> 8); * offset += 2; * } * } */ } break; case SurfaceFormat.Bgra5551: { #if OPENGL // Shift the channels to suit OPENGL int offset = 0; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { ushort pixel = BitConverter.ToUInt16(levelData, offset); pixel = (ushort)(((pixel & 0x7FFF) << 1) | ((pixel & 0x8000) >> 15)); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } #endif } break; case SurfaceFormat.Bgra4444: { #if OPENGL // Shift the channels to suit OPENGL int offset = 0; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { ushort pixel = BitConverter.ToUInt16(levelData, offset); pixel = (ushort)(((pixel & 0x0FFF) << 4) | ((pixel & 0xF000) >> 12)); levelData[offset] = (byte)(pixel); levelData[offset + 1] = (byte)(pixel >> 8); offset += 2; } } #endif } break; case SurfaceFormat.NormalizedByte4: { int bytesPerPixel = surfaceFormat.GetSize(); int pitch = levelWidth * bytesPerPixel; for (int y = 0; y < levelHeight; y++) { for (int x = 0; x < levelWidth; x++) { int color = BitConverter.ToInt32(levelData, y * pitch + x * bytesPerPixel); levelData[y * pitch + x * 4] = (byte)(((color >> 16) & 0xff)); //R:=W levelData[y * pitch + x * 4 + 1] = (byte)(((color >> 8) & 0xff)); //G:=V levelData[y * pitch + x * 4 + 2] = (byte)(((color) & 0xff)); //B:=U levelData[y * pitch + x * 4 + 3] = (byte)(((color >> 24) & 0xff)); //A:=Q } } } break; } texture.SetData(level, null, levelData, 0, levelData.Length); } return(texture); }
protected internal override Texture2D Read(ContentReader reader, Texture2D existingInstance) { Texture2D texture = null; SurfaceFormat surfaceFormat; if (reader.version < 5) { SurfaceFormatLegacy legacyFormat = (SurfaceFormatLegacy)reader.ReadInt32(); switch (legacyFormat) { case SurfaceFormatLegacy.Dxt1: surfaceFormat = SurfaceFormat.Dxt1; break; case SurfaceFormatLegacy.Dxt3: surfaceFormat = SurfaceFormat.Dxt3; break; case SurfaceFormatLegacy.Dxt5: surfaceFormat = SurfaceFormat.Dxt5; break; case SurfaceFormatLegacy.Color: surfaceFormat = SurfaceFormat.Color; break; default: throw new NotSupportedException("Unsupported legacy surface format."); } } else { surfaceFormat = (SurfaceFormat)reader.ReadInt32(); } int width = (reader.ReadInt32()); int height = (reader.ReadInt32()); int levelCount = (reader.ReadInt32()); int levelCountOutput = levelCount; SurfaceFormat convertedFormat = surfaceFormat; switch (surfaceFormat) { case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: convertedFormat = SurfaceFormat.Color; break; case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt5: convertedFormat = SurfaceFormat.Color; break; case SurfaceFormat.NormalizedByte4: convertedFormat = SurfaceFormat.Color; break; } UnityEngine.Texture2D unityTexture = new UnityEngine.Texture2D(width, height, XnaToUnity.TextureFormat(convertedFormat), levelCountOutput > 1); for (int level = 0; level < levelCount; level++) { int levelDataSizeInBytes = (reader.ReadInt32()); byte[] levelData = reader.ReadBytes(levelDataSizeInBytes); int levelWidth = width >> level; int levelHeight = height >> level; if (level >= levelCountOutput) { continue; } //Convert the image data if required switch (surfaceFormat) { case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1a: levelData = DxtUtil.DecompressDxt1(levelData, levelWidth, levelHeight); break; case SurfaceFormat.Dxt3: levelData = DxtUtil.DecompressDxt3(levelData, levelWidth, levelHeight); break; case SurfaceFormat.Dxt5: levelData = DxtUtil.DecompressDxt5(levelData, levelWidth, levelHeight); break; } // un-premultiply alpha (instead do it in the shader) for (int i = 0; i < levelData.Length; i += 4) { float r = levelData[i + 0] / 255.0f; float g = levelData[i + 1] / 255.0f; float b = levelData[i + 2] / 255.0f; float a = levelData[i + 3] / 255.0f; levelData[i + 0] = (byte)(r / a * 255.0f); levelData[i + 1] = (byte)(g / a * 255.0f); levelData[i + 2] = (byte)(b / a * 255.0f); //levelData[i + 0] = 0; //levelData[i + 1] = 255; //levelData[i + 2] = 0; //levelData[i + 3] = 255; } // swap rows because unity textures are laid out bottom-top instead of top-bottom int rowSize = width * 4; byte[] temp = new byte[rowSize]; for (int i = 0; i < levelData.Length / 2; i += rowSize) { for (int j = 0; j < rowSize; j++) { temp[j] = levelData[i + j]; } int p = levelData.Length - (i + rowSize); for (int j = 0; j < rowSize; j++) { levelData[i + j] = levelData[p + j]; } for (int j = 0; j < rowSize; j++) { levelData[p + j] = temp[j]; } } UnityEngine.Color[] unityColors = new UnityEngine.Color[levelData.Length * 4]; unityTexture.SetPixels(XnaToUnity.Color(levelData, ref unityColors), level); unityTexture.Apply(); texture = new Texture2D(unityTexture); } return(texture); }