示例#1
0
        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);
        }
示例#2
0
        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);
        }