Ejemplo n.º 1
0
        internal static void ChangeTextureToRequestedFormat(TextureContent texture,
                                                            Type originalType,
                                                            TextureProcessorOutputFormat textureFormat)
        {
            switch (textureFormat)
            {
                case TextureProcessorOutputFormat.NoChange:
                    if (originalType == null)
                    {
                        break;
                    }
                    texture.ConvertBitmapType(originalType);
                    return;

                case TextureProcessorOutputFormat.Color:
                    texture.ConvertBitmapType(typeof (PixelBitmapContent<Color>));
                    return;

                case TextureProcessorOutputFormat.DxtCompressed:
                    BestGuessCompress(texture);
                    break;

                default:
                    return;
            }
        }
        public override TextureContent Process(TextureContent input, ContentProcessorContext context)
        {
            input.ConvertBitmapType(typeof(PixelBitmapContent<Color>));

            foreach (MipmapChain mipChain in input.Faces)
            {
                foreach (PixelBitmapContent<Color> bitmap in mipChain)
                {
                    for (int y = 0; y < bitmap.Height; y++)
                    {
                        for (int x = 0; x < bitmap.Width; x++)
                        {
                            Color c = bitmap.GetPixel(x, y);

                            c.R = (byte)(c.R * c.A / 255);
                            c.G = (byte)(c.G * c.A / 255);
                            c.B = (byte)(c.B * c.A / 255);

                            bitmap.SetPixel(x, y, c);
                        }
                    }
                }
            }

            return base.Process(input, context);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Compresses TextureContent in a format appropriate to the platform
        /// </summary>
        public static void CompressTexture(GraphicsProfile profile, TextureContent content, TextureProcessorOutputFormat format, ContentProcessorContext context, bool generateMipmaps, bool sharpAlpha)
        {
            format = GetTextureFormatForPlatform(format, context.TargetPlatform);

            // Make sure we're in a floating point format
            content.ConvertBitmapType(typeof(PixelBitmapContent <Vector4>));

            switch (format)
            {
            case TextureProcessorOutputFormat.AtcCompressed:
                CompressAti(content, generateMipmaps);
                break;

            case TextureProcessorOutputFormat.Color16Bit:
                CompressColor16Bit(content, generateMipmaps);
                break;

            case TextureProcessorOutputFormat.DxtCompressed:
                CompressDxt(profile, content, generateMipmaps, sharpAlpha);
                break;

            case TextureProcessorOutputFormat.Etc1Compressed:
                CompressEtc1(content, generateMipmaps);
                break;

            case TextureProcessorOutputFormat.PvrCompressed:
                CompressPvrtc(content, generateMipmaps);
                break;
            }
        }
Ejemplo n.º 4
0
        public static void CompressDxt(GraphicsProfile profile, TextureContent content, bool generateMipMaps, bool isSpriteFont)
        {
            var face = content.Faces[0][0];

            if (profile == GraphicsProfile.Reach)
            {
                if (!IsPowerOfTwo(face.Width) || !IsPowerOfTwo(face.Height))
                {
                    throw new PipelineException("DXT compression requires width and height must be powers of two in Reach graphics profile.");
                }
            }

            // Test the alpha channel to figure out if we have alpha.
            var alphaRange = CalculateAlphaRange(face);

            if (isSpriteFont)
            {
                CompressFontDXT3(content, generateMipMaps);
            }
            else if (alphaRange == AlphaRange.Opaque)
            {
                Compress(typeof(Dxt1BitmapContent), content, generateMipMaps);
            }
            else if (alphaRange == AlphaRange.Cutout)
            {
                Compress(typeof(Dxt3BitmapContent), content, generateMipMaps);
            }
            else
            {
                Compress(typeof(Dxt5BitmapContent), content, generateMipMaps);
            }
        }
Ejemplo n.º 5
0
        private static void CompressPvrtc(TextureContent content, bool generateMipmaps, bool premultipliedAlpha)
        {
            // TODO: Once uncompressed mipmap generation is supported, first use NVTT to generate mipmaps,
            // then compress them withthe PVRTC tool, so we have the same implementation of mipmap generation
            // across platforms.

            // Calculate number of mip levels
            var width             = content.Faces[0][0].Height;
            var height            = content.Faces[0][0].Width;
            var numberOfMipLevels = 1;

            if (generateMipmaps)
            {
                while (height != 1 || width != 1)
                {
                    height = Math.Max(height / 2, 1);
                    width  = Math.Max(width / 2, 1);
                    numberOfMipLevels++;
                }
            }

            IntPtr dataSizesPtr = IntPtr.Zero;
            var    texDataPtr   = ManagedPVRTC.ManagedPVRTC.CompressTexture(content.Faces[0][0].GetPixelData(),
                                                                            content.Faces[0][0].Height,
                                                                            content.Faces[0][0].Width,
                                                                            numberOfMipLevels,
                                                                            premultipliedAlpha,
                                                                            true,
                                                                            ref dataSizesPtr);

            // Store the size of each mip level
            var dataSizesArray = new int[numberOfMipLevels];

            Marshal.Copy(dataSizesPtr, dataSizesArray, 0, dataSizesArray.Length);

            var levelSize = 0;

            byte[] levelData;
            var    sourceWidth  = content.Faces[0][0].Width;
            var    sourceHeight = content.Faces[0][0].Height;

            content.Faces[0].Clear();

            for (int x = 0; x < numberOfMipLevels; x++)
            {
                levelSize = dataSizesArray[x];
                levelData = new byte[levelSize];

                Marshal.Copy(texDataPtr, levelData, 0, levelSize);

                var levelWidth  = Math.Max(sourceWidth >> x, 1);
                var levelHeight = Math.Max(sourceHeight >> x, 1);

                var bmpContent = new PvrtcBitmapContent(4, sourceWidth, sourceHeight);
                bmpContent.SetPixelData(levelData);
                content.Faces[0].Add(bmpContent);

                texDataPtr = IntPtr.Add(texDataPtr, levelSize);
            }
        }
        private TextureContent GenerateCubemap(TextureContent input, ContentProcessorContext context)
        {
            if (input.Faces[1].Count != 0)
            {
                //its already a cubemap
                return base.Process(input, context);
            }
            TextureCubeContent cubeContent = new TextureCubeContent();
            // Convert the input data to Color format, for ease of processing.
            input.ConvertBitmapType(typeof(PixelBitmapContent<Color>));

            int height = input.Faces[0][0].Height;
            int width = input.Faces[0][0].Width / 6;

            //split the image into 6 pieces, setup: X+,X-, Y+,Y-, Z+, Z-
            cubeContent.Faces[(int)CubeMapFace.PositiveX] = CreateFace(input.Faces[0][0], width, height, 0);
            cubeContent.Faces[(int)CubeMapFace.NegativeX] = CreateFace(input.Faces[0][0], width, height, width * 1);
            cubeContent.Faces[(int)CubeMapFace.PositiveY] = CreateFace(input.Faces[0][0], width, height, width * 2);
            cubeContent.Faces[(int)CubeMapFace.NegativeY] = CreateFace(input.Faces[0][0], width, height, width * 3);
            cubeContent.Faces[(int)CubeMapFace.PositiveZ] = CreateFace(input.Faces[0][0], width, height, width * 4);
            cubeContent.Faces[(int)CubeMapFace.NegativeZ] = CreateFace(input.Faces[0][0], width, height, width * 5);

            // Calculate mipmap data.
            cubeContent.GenerateMipmaps(true);

            // Compress the cubemap into DXT1 format.
            cubeContent.ConvertBitmapType(typeof(Dxt1BitmapContent));
            return cubeContent;
        }
Ejemplo n.º 7
0
        static void Compress(Type targetType, TextureContent content, bool generateMipMaps)
        {
            var wh = new object[2];

            if (generateMipMaps)
            {
                for (int i = 0; i < content.Faces.Count; ++i)
                {
                    // Only generate mipmaps if there are none already
                    if (content.Faces[i].Count == 1)
                    {
                        var src = content.Faces[i][0];
                        var w   = src.Width;
                        var h   = src.Height;

                        content.Faces[i].Clear();
                        wh[0] = w;
                        wh[1] = h;
                        var dest = (BitmapContent)Activator.CreateInstance(targetType, wh);
                        BitmapContent.Copy(src, dest);
                        content.Faces[i].Add(dest);
                        while (w > 1 && h > 1)
                        {
                            if (w > 1)
                            {
                                w = w >> 1;
                            }
                            if (h > 1)
                            {
                                h = h >> 1;
                            }
                            wh[0] = w;
                            wh[1] = h;
                            dest  = (BitmapContent)Activator.CreateInstance(targetType, wh);
                            BitmapContent.Copy(src, dest);
                            content.Faces[i].Add(dest);
                        }
                    }
                    else
                    {
                        // Convert the existing mipmaps
                        var chain = content.Faces[i];
                        for (int j = 0; j < chain.Count; ++j)
                        {
                            var src = chain[j];
                            wh[0] = src.Width;
                            wh[1] = src.Height;
                            var dest = (BitmapContent)Activator.CreateInstance(targetType, wh);
                            BitmapContent.Copy(src, dest);
                            chain[j] = dest;
                        }
                    }
                }
            }
            else
            {
                // Converts all existing faces and mipmaps
                content.ConvertBitmapType(targetType);
            }
        }
Ejemplo n.º 8
0
        public static void CompressPvrtc(TextureContent content, bool generateMipMaps)
        {
            // Calculate number of mip levels
            var width  = content.Faces[0][0].Height;
            var height = content.Faces[0][0].Width;

            if (!IsPowerOfTwo(width) || !IsPowerOfTwo(height))
            {
                throw new PipelineException("PVR compression requires width and height must be powers of two.");
            }

            if (width != height)
            {
                throw new PipelineException("PVR compression requires square textures.");
            }

            var face = content.Faces[0][0];

            var alphaRange = CalculateAlphaRange(face);

            if (alphaRange == AlphaRange.Opaque)
            {
                Compress(typeof(PvrtcRgb4BitmapContent), content, generateMipMaps);
            }
            else
            {
                Compress(typeof(PvrtcRgba4BitmapContent), content, generateMipMaps);
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Compresses TextureContent in a format appropriate to the platform
        /// </summary>
        public static void CompressTexture(TextureContent content, TargetPlatform platform, bool premultipliedAlpha)
        {
            // TODO: At the moment, only DXT compression from windows machine is supported
            // Add more here as they become available.
            switch (platform)
            {
            case TargetPlatform.Windows:
            case TargetPlatform.WindowsPhone:
            case TargetPlatform.WindowsPhone8:
            case TargetPlatform.WindowsStoreApp:
            case TargetPlatform.Ouya:
            case TargetPlatform.Android:
            case TargetPlatform.Linux:
            case TargetPlatform.MacOSX:
            case TargetPlatform.NativeClient:
            case TargetPlatform.Xbox360:
                CompressDXT(content);
                break;

            case TargetPlatform.iOS:
                CompressPVRTC(content, premultipliedAlpha);
                break;

            default:
                throw new NotImplementedException(string.Format("Texture Compression it not implemented for {0}", platform));
            }
        }
Ejemplo n.º 10
0
		public override TextureContent Process( TextureContent input, ContentProcessorContext context )
		{
			logger = context.Logger;
			logger.LogMessage( "sending texture to base TextureProcessor for initial processing" );

			var textureContent = base.Process( input, context );
			var bmp = (PixelBitmapContent<Color>)textureContent.Faces[0][0];
			var destData = bmp.getData();

			// process the data
			if( flattenImage )
			{
				logger.LogMessage( "flattening image" );
				destData = TextureUtils.createFlatHeightmap( destData, opaqueColor, transparentColor );
			}

			if( blurType != BlurType.None )
			{
				logger.LogMessage( "blurring image width blurDeviation: {0}", blurDeviation );
				if( blurType == BlurType.Color )
					destData = TextureUtils.createBlurredTexture( destData, bmp.Width, bmp.Height, (double)blurDeviation );
				else
					destData = TextureUtils.createBlurredGrayscaleTexture( destData, bmp.Width, bmp.Height, (double)blurDeviation );
			}

			logger.LogMessage( "generating normal map with {0}", edgeDetectionFilter );
			destData = TextureUtils.createNormalMap( destData, edgeDetectionFilter, bmp.Width, bmp.Height, normalStrength, invertX, invertY );

			bmp.setData( destData );

			return textureContent;
		}
Ejemplo n.º 11
0
        public static void CompressPvrtc(ContentProcessorContext context, TextureContent content, bool isSpriteFont)
        {
            // If sharp alpha is required (for a font texture page), use 16-bit color instead of PVR
            if (isSpriteFont)
            {
                CompressColor16Bit(context, content);
                return;
            }

            // Calculate number of mip levels
            var width  = content.Faces[0][0].Height;
            var height = content.Faces[0][0].Width;

            if (!IsPowerOfTwo(width) || !IsPowerOfTwo(height) || (width != height))
            {
                context.Logger.LogWarning(null, content.Identity, "PVR compression requires width and height to be powers of two and equal. Falling back to 16-bit color.");
                CompressColor16Bit(context, content);
                return;
            }

            var face = content.Faces[0][0];

            var alphaRange = CalculateAlphaRange(face);

            if (alphaRange == AlphaRange.Opaque)
            {
                content.ConvertBitmapType(typeof(PvrtcRgb4BitmapContent));
            }
            else
            {
                content.ConvertBitmapType(typeof(PvrtcRgba4BitmapContent));
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Compresses TextureContent in a format appropriate to the platform
        /// </summary>
        public static void CompressTexture(GraphicsProfile profile, TextureContent content, ContentProcessorContext context, bool generateMipmaps, bool premultipliedAlpha)
        {
            // TODO: At the moment, only DXT compression from windows machine is supported
            //       Add more here as they become available.
            switch (context.TargetPlatform)
            {
            case TargetPlatform.Windows:
            case TargetPlatform.WindowsPhone:
            case TargetPlatform.WindowsPhone8:
            case TargetPlatform.WindowsStoreApp:
            case TargetPlatform.Ouya:
            case TargetPlatform.Android:
            case TargetPlatform.Linux:
            case TargetPlatform.MacOSX:
            case TargetPlatform.NativeClient:
            case TargetPlatform.Xbox360:
                context.Logger.LogMessage("Using DXT Compression");
                CompressDxt(profile, content, generateMipmaps);
                break;

            case TargetPlatform.iOS:
                context.Logger.LogMessage("Using PVRTC Compression");
                CompressPvrtc(content, generateMipmaps, premultipliedAlpha);
                break;

            default:
                throw new NotImplementedException(string.Format("Texture Compression it not implemented for {0}", context.TargetPlatform));
            }
        }
Ejemplo n.º 13
0
        static public void CompressEtc1(ContentProcessorContext context, TextureContent content, bool isSpriteFont)
        {
            // If sharp alpha is required (for a font texture page), use 16-bit color instead of PVR
            if (isSpriteFont)
            {
                CompressColor16Bit(context, content);
                return;
            }

            var face       = content.Faces[0][0];
            var alphaRange = CalculateAlphaRange(face);

            // Use BGRA4444 for textures with non-opaque alpha values
            if (alphaRange != AlphaRange.Opaque)
            {
                content.ConvertBitmapType(typeof(PixelBitmapContent <Bgra4444>));
            }
            else
            {
                // PVR SGX does not handle non-POT ETC1 textures.
                // https://code.google.com/p/libgdx/issues/detail?id=1310
                // Since we already enforce POT for PVR and DXT in Reach, we will also enforce POT for ETC1
                if (!IsPowerOfTwo(face.Width) || !IsPowerOfTwo(face.Height))
                {
                    context.Logger.LogWarning(null, content.Identity, "ETC1 compression requires width and height to be powers of two due to hardware restrictions on some devices. Falling back to BGR565.");
                    content.ConvertBitmapType(typeof(PixelBitmapContent <Bgr565>));
                }
                else
                {
                    content.ConvertBitmapType(typeof(Etc1BitmapContent));
                }
            }
        }
Ejemplo n.º 14
0
 private static void BestGuessCompress(TextureContent texture)
 {
     texture.ConvertBitmapType(typeof (PixelBitmapContent<Color>));
     if (!(texture is Texture3DContent))
     {
         texture.ConvertBitmapType(HasFractionalAlpha(texture)
                                       ? typeof (Dxt5BitmapContent)
                                       : typeof (Dxt1BitmapContent));
     }
 }
        public override TextureContent Process(TextureContent input, ContentProcessorContext context)
        {
            // Fallback if we aren't buiding for iOS.
            var platform = ContentHelper.GetMonoGamePlatform();
            if (platform != MonoGamePlatform.iOS)
                return base.Process(input, context);

            // Only go this path if we are compressing the texture
            if (TextureFormat != TextureProcessorOutputFormat.DxtCompressed)
                return base.Process(input, context);

            // TODO: Reflector ResizeToPowerOfTwo(TextureContent tex)
            // Resize the first face and let mips get generated from the dll.
            /*if (ResizeToPowerOfTwo)
            {

            }*/

            var height = input.Faces[0][0].Height;
            var width = input.Faces[0][0].Width;
            var mipLevels = 1;

            var invalidBounds = height != width || !(isPowerOfTwo(height) && isPowerOfTwo(width));

            // Only PVR compress square, power of two textures.
            if (invalidBounds || compressionMode == MGCompressionMode.NoCompression)
            {
                if (compressionMode != MGCompressionMode.NoCompression)
                {
                    context.Logger.LogImportantMessage("WARNING: PVR Texture {0} must be a square, power of two texture. Skipping Compression.",
                                                        Path.GetFileName(context.OutputFilename));
                }

                // Skip compressing this texture and process it normally.
                this.TextureFormat = TextureProcessorOutputFormat.Color;

                return base.Process(input, context);
            }

            // Calculate how many mip levels will be created, and pass that to our DLL.
            if (GenerateMipmaps)
            {
                while (height != 1 || width != 1)
                {
                    height = Math.Max(height / 2, 1);
                    width = Math.Max(width / 2, 1);
                    mipLevels++;
                }
            }

            ConvertToPVRTC(input, mipLevels, PremultiplyAlpha, compressionMode);

            return input;
        }
Ejemplo n.º 16
0
        public DXTDataHandler(TextureContent content, Format format)
        {
            _content = content;

            _currentMipLevel = 0;
            _levelWidth      = content.Faces[0][0].Width;
            _levelHeight     = content.Faces[0][0].Height;
            _format          = format;

            WriteData  = new OutputOptions.WriteDataDelegate(writeData);
            BeginImage = new OutputOptions.ImageDelegate(beginImage);
        }
Ejemplo n.º 17
0
        public DxtDataHandler(TextureContent content, Format format)
        {
            _content = content;

            _currentMipLevel = 0;
            _levelWidth = content.Faces[0][0].Width;
            _levelHeight = content.Faces[0][0].Height;
            _format = format;

            WriteData = new OutputOptions.WriteDataDelegate(writeData);
            BeginImage = new OutputOptions.ImageDelegate(beginImage);
        }
Ejemplo n.º 18
0
        static public void CompressAti(TextureContent content, bool generateMipMaps)
        {
            var face       = content.Faces[0][0];
            var alphaRange = CalculateAlphaRange(face);

            if (alphaRange == AlphaRange.Full)
            {
                Compress(typeof(AtcExplicitBitmapContent), content, generateMipMaps);
            }
            else
            {
                Compress(typeof(AtcInterpolatedBitmapContent), content, generateMipMaps);
            }
        }
Ejemplo n.º 19
0
        private static void CompressDxt(GraphicsProfile profile, TextureContent content, bool generateMipmaps)
        {
            var texData = content.Faces[0][0];

            if (profile == GraphicsProfile.Reach)
            {
                if (!IsPowerOfTwo(texData.Width) || !IsPowerOfTwo(texData.Height))
                {
                    throw new PipelineException("DXT Compressed textures width and height must be powers of two in GraphicsProfile.Reach.");
                }
            }

            var _dxtCompressor = new Compressor();
            var inputOptions   = new InputOptions();

            inputOptions.SetAlphaMode(AlphaMode.Transparency);
            inputOptions.SetTextureLayout(TextureType.Texture2D, texData.Width, texData.Height, 1);

            var pixelData = texData.GetPixelData();

            // Small hack here. NVTT wants 8bit data in BGRA. Flip the B and R channels
            // again here.
            GraphicsUtil.BGRAtoRGBA(pixelData);
            var dataHandle = GCHandle.Alloc(pixelData, GCHandleType.Pinned);
            var dataPtr    = dataHandle.AddrOfPinnedObject();

            inputOptions.SetMipmapData(dataPtr, texData.Width, texData.Height, 1, 0, 0);
            inputOptions.SetMipmapGeneration(generateMipmaps);

            var containsFracAlpha = ContainsFractionalAlpha(pixelData);
            var outputOptions     = new OutputOptions();

            outputOptions.SetOutputHeader(false);

            var outputFormat = containsFracAlpha ? Format.DXT5 : Format.DXT1;

            var handler = new DxtDataHandler(content, outputFormat);

            outputOptions.SetOutputHandler(handler.BeginImage, handler.WriteData);

            var compressionOptions = new CompressionOptions();

            compressionOptions.SetFormat(outputFormat);
            compressionOptions.SetQuality(Quality.Fastest);

            _dxtCompressor.Compress(inputOptions, compressionOptions, outputOptions);

            dataHandle.Free();
        }
Ejemplo n.º 20
0
        public override TInput Process(TInput input, ContentProcessorContext context)
        {
            PixelBitmapContent <Color> texture = ((PixelBitmapContent <Color>)input.Faces[0][0]);

            PixelBitmapContent <Color> normalMap = CreateNormalMap(texture);

            Texture2DContent result = new Texture2DContent();

            result.Faces[0] = normalMap;

            // Call the base with the new texture to gen mipmaps and new format
            base.Process(result, context);

            return(result);
        }
Ejemplo n.º 21
0
        internal static void Resize(this TextureContent content, int newWidth, int newHeight)
        {
            var source = content.Faces[0][0].ToSystemBitmap();

            var destination = new Bitmap(newWidth, newHeight);

            using (var graphics = System.Drawing.Graphics.FromImage(destination))
            {
                graphics.DrawImage(source, 0, 0, newWidth, newHeight);
                source.Dispose();
            }

            content.Faces.Clear();
            content.Faces.Add(new MipmapChain(destination.ToXnaBitmap()));
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Performs conversion of the texture content to the correct format.
        /// </summary>
        /// <param name="context">The processor context.</param>
        /// <param name="content">The content to be compressed.</param>
        /// <param name="format">The user requested format for compression.</param>
        /// <param name="generateMipmaps">If mipmap generation is required.</param>
        /// <param name="isSpriteFont">If the texture has represents a sprite font, i.e. is greyscale and has sharp black/white contrast.</param>
        public void ConvertTexture(ContentProcessorContext context, TextureContent content, TextureProcessorOutputFormat format, bool generateMipmaps, bool isSpriteFont)
        {
            // We do nothing in this case.
            if (format == TextureProcessorOutputFormat.NoChange)
            {
                return;
            }

            // If this is color just make sure the format is right and return it.
            if (format == TextureProcessorOutputFormat.Color)
            {
                content.ConvertBitmapType(typeof(PixelBitmapContent <Color>));
                if (generateMipmaps)
                {
                    content.GenerateMipmaps(false);
                }
                return;
            }

            // Handle this common compression format.
            if (format == TextureProcessorOutputFormat.Color16Bit)
            {
                GraphicsUtil.CompressColor16Bit(content, generateMipmaps);
                return;
            }

            try
            {
                // All other formats require platform specific choices.
                PlatformCompressTexture(context, content, format, generateMipmaps, isSpriteFont);
            }
            catch (EntryPointNotFoundException ex)
            {
                context.Logger.LogImportantMessage("Could not find the entry point to compress the texture. " + ex.ToString());
                throw ex;
            }
            catch (DllNotFoundException ex)
            {
                context.Logger.LogImportantMessage("Could not compress texture. Required shared lib is missing. " + ex.ToString());
                throw ex;
            }
            catch (Exception ex)
            {
                context.Logger.LogImportantMessage("Could not convert texture. " + ex.ToString());
                throw ex;
            }
        }
Ejemplo n.º 23
0
 private static bool HasFractionalAlpha(TextureContent texture)
 {
     foreach (MipmapChain chain in texture.Faces)
     {
         foreach (PixelBitmapContent<Color> content in chain)
         {
             for (int i = 0; i < content.Height; i++)
             {
                 if (content.GetRow(i).Select(color => color.A).Any(a => (a != 0xff) && (a != 0)))
                 {
                     return true;
                 }
             }
         }
     }
     return false;
 }
Ejemplo n.º 24
0
        public static void CompressDxt(ContentProcessorContext context, TextureContent content, bool isSpriteFont)
        {
            var face = content.Faces[0][0];

            if (context.TargetProfile == GraphicsProfile.Reach)
            {
                if (!IsPowerOfTwo(face.Width) || !IsPowerOfTwo(face.Height))
                {
                    throw new PipelineException("DXT compression requires width and height must be powers of two in Reach graphics profile.");
                }
            }

            // Test the alpha channel to figure out if we have alpha.
            var alphaRange = CalculateAlphaRange(face);

            // TODO: This isn't quite right.
            //
            // We should be generating DXT1 textures for cutout alpha
            // as DXT1 supports 1bit alpha and it uses less memory.
            //
            // XNA never generated DXT3 for textures... it always picked
            // between DXT1 for cutouts and DXT5 for fractional alpha.
            //
            // DXT3 however can produce better results for high frequency
            // alpha like a chain link fence where is DXT5 is better for
            // low frequency alpha like clouds.  I don't know how we can
            // pick the right thing in this case without a hint.
            //
            if (isSpriteFont)
            {
                CompressFontDXT3(content);
            }
            else if (alphaRange == AlphaRange.Opaque)
            {
                content.ConvertBitmapType(typeof(Dxt1BitmapContent));
            }
            else if (alphaRange == AlphaRange.Cutout)
            {
                content.ConvertBitmapType(typeof(Dxt3BitmapContent));
            }
            else
            {
                content.ConvertBitmapType(typeof(Dxt5BitmapContent));
            }
        }
Ejemplo n.º 25
0
        static public void CompressColor16Bit(ContentProcessorContext context, TextureContent content)
        {
            var face       = content.Faces[0][0];
            var alphaRange = CalculateAlphaRange(face);

            if (alphaRange == AlphaRange.Opaque)
            {
                content.ConvertBitmapType(typeof(PixelBitmapContent <Bgr565>));
            }
            else if (alphaRange == AlphaRange.Cutout)
            {
                content.ConvertBitmapType(typeof(PixelBitmapContent <Bgra5551>));
            }
            else
            {
                content.ConvertBitmapType(typeof(PixelBitmapContent <Bgra4444>));
            }
        }
Ejemplo n.º 26
0
        static public void CompressColor16Bit(TextureContent content, bool generateMipMaps)
        {
            var face       = content.Faces[0][0];
            var alphaRange = CalculateAlphaRange(face);

            if (alphaRange == AlphaRange.Opaque)
            {
                Compress(typeof(PixelBitmapContent <Bgr565>), content, generateMipMaps);
            }
            else if (alphaRange == AlphaRange.Cutout)
            {
                Compress(typeof(PixelBitmapContent <Bgra5551>), content, generateMipMaps);
            }
            else
            {
                Compress(typeof(PixelBitmapContent <Bgra4444>), content, generateMipMaps);
            }
        }
Ejemplo n.º 27
0
        public static void PremultiplyAlpha(TextureContent content)
        {
            var colorTex = content.Faces[0][0] as PixelBitmapContent <Color>;

            if (colorTex != null)
            {
                for (int x = 0; x < colorTex.Height; x++)
                {
                    var row = colorTex.GetRow(x);
                    for (int y = 0; y < row.Length; y++)
                    {
                        if (row[y].A < 0xff)
                        {
                            row[y] = Color.FromNonPremultiplied(row[y].R, row[y].G, row[y].B, row[y].A);
                        }
                    }
                }
            }
            else
            {
                var vec4Tex = content.Faces[0][0] as PixelBitmapContent <Vector4>;
                if (vec4Tex == null)
                {
                    throw new NotSupportedException();
                }

                for (int x = 0; x < vec4Tex.Height; x++)
                {
                    var row = vec4Tex.GetRow(x);
                    for (int y = 0; y < row.Length; y++)
                    {
                        if (row[y].W < 1.0f)
                        {
                            row[y].X *= row[y].W;
                            row[y].Y *= row[y].W;
                            row[y].Z *= row[y].W;
                        }
                    }
                }
            }
        }
Ejemplo n.º 28
0
        internal static void Resize(this TextureContent content, int newWidth, int newHeight)
        {
            var resizedBmp = new Bitmap(newWidth, newHeight);

            using (var graphics = System.Drawing.Graphics.FromImage(resizedBmp))
            {
                graphics.DrawImage(content._bitmap, 0, 0, newWidth, newHeight);

                content._bitmap.Dispose();
                content._bitmap = resizedBmp;
            }

            var imageData = content._bitmap.GetData();

            var bitmapContent = new PixelBitmapContent <Color>(content._bitmap.Width, content._bitmap.Height);

            bitmapContent.SetPixelData(imageData);

            content.Faces.Clear();
            content.Faces.Add(new MipmapChain(bitmapContent));
        }
Ejemplo n.º 29
0
        internal static void Resize(this TextureContent content, int newWidth, int newHeight)
        {
            // TODO: This should be refactored to use FreeImage
            // with a higher quality filter.

            var destination = new Bitmap(newWidth, newHeight);

            using (var source = content.Faces[0][0].ToSystemBitmap())
                using (var graphics = System.Drawing.Graphics.FromImage(destination))
                {
                    var imageAttr = new ImageAttributes();
                    imageAttr.SetWrapMode(WrapMode.TileFlipXY);

                    var destRect = new System.Drawing.Rectangle(0, 0, newWidth, newHeight);

                    graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
                    graphics.DrawImage(source, destRect, 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, imageAttr);
                }

            content.Faces[0][0] = destination.ToXnaBitmap(false); //we dont want to flip colors twice
        }
Ejemplo n.º 30
0
        static public void CompressAti(ContentProcessorContext context, TextureContent content, bool isSpriteFont)
        {
            // If sharp alpha is required (for a font texture page), use 16-bit color instead of PVR
            if (isSpriteFont)
            {
                CompressColor16Bit(context, content);
                return;
            }

            var face       = content.Faces[0][0];
            var alphaRange = CalculateAlphaRange(face);

            if (alphaRange == AlphaRange.Full)
            {
                content.ConvertBitmapType(typeof(AtcExplicitBitmapContent));
            }
            else
            {
                content.ConvertBitmapType(typeof(AtcInterpolatedBitmapContent));
            }
        }
Ejemplo n.º 31
0
        static public void CompressEtc1(TextureContent content, bool generateMipMaps)
        {
            var face       = content.Faces[0][0];
            var alphaRange = CalculateAlphaRange(face);

            // Use BGRA4444 for textures with non-opaque alpha values
            if (alphaRange != AlphaRange.Opaque)
            {
                Compress(typeof(PixelBitmapContent <Bgra4444>), content, generateMipMaps);
            }
            else
            {
                // PVR SGX does not handle non-POT ETC1 textures.
                // https://code.google.com/p/libgdx/issues/detail?id=1310
                // Since we already enforce POT for PVR and DXT in Reach, we will also enforce POT for ETC1
                if (!IsPowerOfTwo(face.Width) || !IsPowerOfTwo(face.Height))
                {
                    throw new PipelineException("ETC1 compression require width and height must be powers of two due to hardware restrictions on some devices.");
                }
                Compress(typeof(Etc1BitmapContent), content, generateMipMaps);
            }
        }
        public override TextureContent Process(TextureContent input, ContentProcessorContext context)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            //check if its a normal map
            Console.WriteLine("Light pre-pass texture processor: " + context.OutputFilename);

            if (context.OutputFilename.Contains("normal"))
            {
                TextureFormat = TextureProcessorOutputFormat.Color;
            }
            else
            {
                TextureFormat = TextureProcessorOutputFormat.DxtCompressed;
            }
            GenerateMipmaps = true;
            //try to parse meta data
            FileInfo fileInfo = new FileInfo(Path.GetDirectoryName(input.Identity.SourceFilename) + "\\" + Path.GetFileNameWithoutExtension(input.Identity.SourceFilename) + ".metadata");
            if (fileInfo.Exists)
            {
                using (FileStream fileStream = fileInfo.OpenRead())
                {
                    StreamReader streamReader = new StreamReader(fileStream);
                    while (!streamReader.EndOfStream)
                    {
                        string line = streamReader.ReadLine();
                        ParseMetaData(line);
                    }
                }
            }
            if (_isCubemap)
            {
                return GenerateCubemap(input, context);
            }
            return base.Process(input, context);
        }
Ejemplo n.º 33
0
 public static void ColorKey(TextureContent texture, Color colorKey)
 {
     foreach (MipmapChain chain in texture.Faces)
     {
         foreach (BitmapContent content in chain)
         {
             var content3 = content as PixelBitmapContent<Color>;
             if (content3 == null)
             {
                 var content2 = content as PixelBitmapContent<Vector4>;
                 if (content2 == null)
                 {
                     throw new NotSupportedException();
                 }
                 content2.ReplaceColor(colorKey.ToVector4(), Vector4.Zero);
             }
             else
             {
                 content3.ReplaceColor(colorKey, Color.Transparent);
             }
         }
     }
 }
Ejemplo n.º 34
0
        public override TextureContent Process(TextureContent input, ContentProcessorContext context)
        {
            input.ConvertBitmapType(typeof(PixelBitmapContent<Color>));
            foreach (var mipmapChain in input.Faces)
            {
                for (int i = 0; i < mipmapChain.Count; i++)
                {
                    var bitmap = mipmapChain[i] as PixelBitmapContent<Color>;

                    int newWidth = (int) ((float) bitmap.Width * Scale);
                    int newHeight = (int) ((float) bitmap.Height * Scale);

                    var newBitmap = new PixelBitmapContent<Color>(newWidth, newHeight);

                    for (int y = 0; y < bitmap.Height; y++)
                    {
                        for (int x = 0; x < bitmap.Width; x++)
                        {
                            for (int scaleY = 0; scaleY < Scale; scaleY++)
                            {
                                for (int scaleX = 0; scaleX < Scale; scaleX++)
                                {
                                    newBitmap.SetPixel(
                                        (int) (x * Scale) + scaleX,
                                        (int) (y * Scale) + scaleY,
                                        bitmap.GetPixel(x, y));
                                }
                            }
                        }
                    }

                    mipmapChain[i] = newBitmap;
                }
            }

            return base.Process(input, context);
        }
Ejemplo n.º 35
0
        private static void CompressPVRTC(TextureContent content, bool premultipliedAlpha)
        {
            // Note: MipGeneration will be done by NVTT, rather than PVRTC's tool.
            // This way we have the same implementation across platforms.

            IntPtr dataSizesPtr = IntPtr.Zero;
            var    texDataPtr   = compressPVRTC(content.Faces[0][0].GetPixelData(),
                                                content.Faces[0][0].Height,
                                                content.Faces[0][0].Width,
                                                1,
                                                premultipliedAlpha,
                                                true,
                                                ref dataSizesPtr);

            // Store the size of each mipLevel
            var dataSizesArray = new int[1];

            Marshal.Copy(dataSizesPtr, dataSizesArray, 0, dataSizesArray.Length);

            var levelSize = 0;

            byte[] levelData;
            var    sourceWidth  = content.Faces[0][0].Width;
            var    sourceHeight = content.Faces[0][0].Height;

            content.Faces[0].Clear();

            levelSize = dataSizesArray[0];
            levelData = new byte[levelSize];

            Marshal.Copy(texDataPtr, levelData, 0, levelSize);

            var bmpContent = new PVRTCBitmapContent(4, sourceWidth, sourceHeight);

            bmpContent.SetPixelData(levelData);
            content.Faces[0].Add(bmpContent);
        }
Ejemplo n.º 36
0
        public static void CompressPvrtc(TextureContent content, bool generateMipMaps, bool isSpriteFont)
        {
            // If sharp alpha is required (for a font texture page), use 16-bit color instead of PVR
            if (isSpriteFont)
            {
                CompressColor16Bit(content, generateMipMaps);
                return;
            }

            // Calculate number of mip levels
            var width  = content.Faces[0][0].Height;
            var height = content.Faces[0][0].Width;

            if (!IsPowerOfTwo(width) || !IsPowerOfTwo(height))
            {
                throw new PipelineException("PVR compression requires width and height must be powers of two.");
            }

            if (width != height)
            {
                throw new PipelineException("PVR compression requires square textures.");
            }

            var face = content.Faces[0][0];

            var alphaRange = CalculateAlphaRange(face);

            if (alphaRange == AlphaRange.Opaque)
            {
                Compress(typeof(PvrtcRgb4BitmapContent), content, generateMipMaps);
            }
            else
            {
                Compress(typeof(PvrtcRgba4BitmapContent), content, generateMipMaps);
            }
        }
Ejemplo n.º 37
0
        private static void CompressDxt(TextureContent content, bool generateMipmaps)
        {
            var texData = content.Faces[0][0];

            if (!IsPowerOfTwo(texData.Width) || !IsPowerOfTwo(texData.Height))
                throw new PipelineException("DXT Compressed textures width and height must be powers of two.");

            var _dxtCompressor = new Compressor();
            var inputOptions = new InputOptions();
            inputOptions.SetAlphaMode(AlphaMode.Transparency);
            inputOptions.SetTextureLayout(TextureType.Texture2D, texData.Width, texData.Height, 1);

            var pixelData = texData.GetPixelData();
            
            // Small hack here. NVTT wants 8bit data in BGRA. Flip the B and R channels
            // again here.
            GraphicsUtil.BGRAtoRGBA(pixelData);
            var dataHandle = GCHandle.Alloc(pixelData, GCHandleType.Pinned);
            var dataPtr = dataHandle.AddrOfPinnedObject();

            inputOptions.SetMipmapData(dataPtr, texData.Width, texData.Height, 1, 0, 0);
            inputOptions.SetMipmapGeneration(generateMipmaps);

            var containsFracAlpha = ContainsFractionalAlpha(pixelData);
            var outputOptions = new OutputOptions();
            outputOptions.SetOutputHeader(false);

            var outputFormat = containsFracAlpha ? Format.DXT5 : Format.DXT1;

            var handler = new DxtDataHandler(content, outputFormat);
            outputOptions.SetOutputHandler(handler.BeginImage, handler.WriteData);

            var compressionOptions = new CompressionOptions();
            compressionOptions.SetFormat(outputFormat);
            compressionOptions.SetQuality(Quality.Fastest);

            _dxtCompressor.Compress(inputOptions, compressionOptions, outputOptions);

            dataHandle.Free();
        }
Ejemplo n.º 38
0
        static void CompressAti(TextureContent content, bool generateMipMaps)
        {
			var face = content.Faces[0][0];
			var alphaRange = CalculateAlphaRange(face);

            if (alphaRange == AlphaRange.Full)
                Compress(typeof(AtcExplicitBitmapContent), content, generateMipMaps);
            else
                Compress(typeof(AtcInterpolatedBitmapContent), content, generateMipMaps);
        }
        protected override void PlatformCompressTexture(ContentProcessorContext context, TextureContent content, TextureProcessorOutputFormat format, bool isSpriteFont)
        {
            format = GetTextureFormatForPlatform(format, context.TargetPlatform);

            // Make sure we're in a floating point format
            content.ConvertBitmapType(typeof(PixelBitmapContent <Vector4>));

            switch (format)
            {
            case TextureProcessorOutputFormat.AtcCompressed:
                GraphicsUtil.CompressAti(context, content, isSpriteFont);
                break;

            case TextureProcessorOutputFormat.Color16Bit:
                GraphicsUtil.CompressColor16Bit(context, content);
                break;

            case TextureProcessorOutputFormat.DxtCompressed:
                GraphicsUtil.CompressDxt(context, content, isSpriteFont);
                break;

            case TextureProcessorOutputFormat.Etc1Compressed:
                GraphicsUtil.CompressEtc1(context, content, isSpriteFont);
                break;

            case TextureProcessorOutputFormat.PvrCompressed:
                GraphicsUtil.CompressPvrtc(context, content, isSpriteFont);
                break;
            }
        }
        public static void ConvertToPVRTC(TextureContent sourceContent, int mipLevels, bool premultipliedAlpha, MGCompressionMode bpp)
        {
            IntPtr dataSizesPtr = IntPtr.Zero;

            var texDataPtr = CompressTexture(sourceContent.Faces[0][0].GetPixelData(), 
                                            sourceContent.Faces[0][0].Height, 
                                            sourceContent.Faces[0][0].Width, 
                                            mipLevels, 
                                            premultipliedAlpha,
                                            bpp == MGCompressionMode.PVRTCFourBitsPerPixel,
                                            ref dataSizesPtr);

            // Store the size of each mipLevel
            var dataSizesArray = new int[mipLevels];
            Marshal.Copy(dataSizesPtr, dataSizesArray, 0, dataSizesArray.Length);

            var levelSize = 0;
            byte[] levelData;
            var sourceWidth = sourceContent.Faces[0][0].Width;
            var sourceHeight = sourceContent.Faces[0][0].Height;

            // Set the pixel data for each mip level.
            sourceContent.Faces[0].Clear();

            for (int x = 0; x < mipLevels; x++)
            {
                levelSize = dataSizesArray[x];
                levelData = new byte[levelSize];

                Marshal.Copy(texDataPtr, levelData, 0, levelSize);

                var levelWidth = Math.Max(sourceWidth  >> x, 1);
                var levelHeight = Math.Max(sourceHeight >> x, 1);

                sourceContent.Faces[0].Add(new MGBitmapContent(levelData, levelWidth, levelHeight, bpp));

                texDataPtr = IntPtr.Add(texDataPtr, levelSize);
            }
        }
Ejemplo n.º 41
0
 public static void PremultiplyAlpha(TextureContent texture)
 {
     foreach (MipmapChain chain in texture.Faces)
     {
         foreach (BitmapContent content3 in chain)
         {
             var content2 = content3 as PixelBitmapContent<Color>;
             if (content2 != null)
             {
                 for (int i = 0; i < content2.Height; i++)
                 {
                     Color[] row = content2.GetRow(i);
                     for (int j = 0; j < row.Length; j++)
                     {
                         Color color = row[j];
                         if (color.A < 0xff)
                         {
                             row[j] = Color.FromNonPremultiplied(color.R, color.G, color.B, color.A);
                         }
                     }
                 }
             }
             else
             {
                 var content = content3 as PixelBitmapContent<Vector4>;
                 if (content == null)
                 {
                     throw new NotSupportedException();
                 }
                 for (int k = 0; k < content.Height; k++)
                 {
                     Vector4[] vectorArray = content.GetRow(k);
                     for (int m = 0; m < vectorArray.Length; m++)
                     {
                         Vector4 vector = vectorArray[m];
                         if (vector.W < 1f)
                         {
                             vector.X *= vector.W;
                             vector.Y *= vector.W;
                             vector.Z *= vector.W;
                             vectorArray[m] = vector;
                         }
                     }
                 }
             }
         }
     }
 }
Ejemplo n.º 42
0
 public static void ResizeToPowerOfTwo(TextureContent texture)
 {
     foreach (MipmapChain chain in texture.Faces)
     {
         for (int i = 0; i < chain.Count; i++)
         {
             BitmapContent source = chain[i];
             int width = RoundUpToPowerOfTwo(source.Width);
             int height = RoundUpToPowerOfTwo(source.Height);
             if ((width != source.Width) || (height != source.Height))
             {
                 chain[i] = ConvertBitmap(source, source.GetType(), width, height);
             }
         }
     }
 }
Ejemplo n.º 43
0
 protected abstract void PlatformCompressTexture(ContentProcessorContext context, TextureContent content, TextureProcessorOutputFormat format, bool generateMipmaps, bool isSpriteFont);
Ejemplo n.º 44
0
        private static void CompressPvrtc(TextureContent content, bool generateMipMaps)
        {
            // Calculate number of mip levels
            var width = content.Faces[0][0].Height;
            var height = content.Faces[0][0].Width;

			if (!IsPowerOfTwo(width) || !IsPowerOfTwo(height))
				throw new PipelineException("PVR compression requires width and height must be powers of two.");

			if (width != height)
				throw new PipelineException("PVR compression requires square textures.");

            var face = content.Faces[0][0];

            var alphaRange = CalculateAlphaRange(face);

            if (alphaRange == AlphaRange.Opaque)
                Compress(typeof(PvrtcRgb4BitmapContent), content, generateMipMaps);
            else
                Compress(typeof(PvrtcRgba4BitmapContent), content, generateMipMaps);
        }
Ejemplo n.º 45
0
        static void Compress(Type targetType, TextureContent content, bool generateMipMaps)
        {
            var wh = new object[2];
            if (generateMipMaps)
            {
                for (int i = 0; i < content.Faces.Count; ++i)
                {
                    // Only generate mipmaps if there are none already
                    if (content.Faces[i].Count == 1)
                    {
                        var src = content.Faces[i][0];
                        var w = src.Width;
                        var h = src.Height;

                        content.Faces[i].Clear();
                        wh[0] = w;
                        wh[1] = h;
                        var dest = (BitmapContent)Activator.CreateInstance(targetType, wh);
                        BitmapContent.Copy(src, dest);
                        content.Faces[i].Add(dest);
                        while (w > 1 && h > 1)
                        {
                            if (w > 1)
                                w = w >> 1;
                            if (h > 1)
                                h = h >> 1;
                            wh[0] = w;
                            wh[1] = h;
                            dest = (BitmapContent)Activator.CreateInstance(targetType, wh);
                            BitmapContent.Copy(src, dest);
                            content.Faces[i].Add(dest);
                        }
                    }
                    else
                    {
                        // Convert the existing mipmaps
                        var chain = content.Faces[i];
                        for (int j = 0; j < chain.Count; ++j)
                        {
                            var src = chain[j];
                            wh[0] = src.Width;
                            wh[1] = src.Height;
                            var dest = (BitmapContent)Activator.CreateInstance(targetType, wh);
                            BitmapContent.Copy(src, dest);
                            chain[j] = dest;
                        }
                    }
                }
            }
            else
            {
                // Converts all existing faces and mipmaps
                content.ConvertBitmapType(targetType);
            }
        }
Ejemplo n.º 46
0
        /// <summary>
        /// Compresses TextureContent in a format appropriate to the platform
        /// </summary>
        public static void CompressTexture(GraphicsProfile profile, TextureContent content, TextureProcessorOutputFormat format, ContentProcessorContext context, bool generateMipmaps, bool sharpAlpha)
        {
            format = GetTextureFormatForPlatform(format, context.TargetPlatform);

            // Make sure we're in a floating point format
            content.ConvertBitmapType(typeof(PixelBitmapContent<Vector4>));

            switch (format)
            {
                case TextureProcessorOutputFormat.AtcCompressed:
                    CompressAti(content, generateMipmaps);
                    break;

                case TextureProcessorOutputFormat.Color16Bit:
                    CompressColor16Bit(content, generateMipmaps);
                    break;

                case TextureProcessorOutputFormat.DxtCompressed:
                    CompressDxt(profile, content, generateMipmaps, sharpAlpha);
                    break;

                case TextureProcessorOutputFormat.Etc1Compressed:
                    CompressEtc1(content, generateMipmaps);
                    break;

                case TextureProcessorOutputFormat.PvrCompressed:
                    CompressPvrtc(content, generateMipmaps);
                    break;
            }
        }
Ejemplo n.º 47
0
 /// <summary>
 /// Checks that the face of the texture contains 7 mipmaps and that their sizes decline from 64x64 to 1x1
 /// </summary>
 /// <param name="content">Texture to check</param>
 /// <param name="faceIndex">Index of the face from the texture</param>
 private static void CheckDdsFace(TextureContent content, int faceIndex)
 {
     Assert.AreEqual(content.Faces[faceIndex].Count, 7);
     Assert.AreEqual(content.Faces[faceIndex][0].Width, 64);
     Assert.AreEqual(content.Faces[faceIndex][0].Height, 64);
     Assert.AreEqual(content.Faces[faceIndex][1].Width, 32);
     Assert.AreEqual(content.Faces[faceIndex][1].Height, 32);
     Assert.AreEqual(content.Faces[faceIndex][2].Width, 16);
     Assert.AreEqual(content.Faces[faceIndex][2].Height, 16);
     Assert.AreEqual(content.Faces[faceIndex][3].Width, 8);
     Assert.AreEqual(content.Faces[faceIndex][3].Height, 8);
     Assert.AreEqual(content.Faces[faceIndex][4].Width, 4);
     Assert.AreEqual(content.Faces[faceIndex][4].Height, 4);
     Assert.AreEqual(content.Faces[faceIndex][5].Width, 2);
     Assert.AreEqual(content.Faces[faceIndex][5].Height, 2);
     Assert.AreEqual(content.Faces[faceIndex][6].Width, 1);
     Assert.AreEqual(content.Faces[faceIndex][6].Height, 1);
 }
Ejemplo n.º 48
0
        static void CompressEtc1(TextureContent content, bool generateMipMaps)
        {
            var face = content.Faces[0][0];
            var alphaRange = CalculateAlphaRange(face);

            // Use BGRA4444 for textures with non-opaque alpha values
            if (alphaRange != AlphaRange.Opaque)
                Compress(typeof(PixelBitmapContent<Bgra4444>), content, generateMipMaps);
            else
            {
                // PVR SGX does not handle non-POT ETC1 textures.
                // https://code.google.com/p/libgdx/issues/detail?id=1310
                // Since we already enforce POT for PVR and DXT in Reach, we will also enforce POT for ETC1
                if (!IsPowerOfTwo(face.Width) || !IsPowerOfTwo(face.Height))
                    throw new PipelineException("ETC1 compression require width and height must be powers of two due to hardware restrictions on some devices.");
                Compress(typeof(Etc1BitmapContent), content, generateMipMaps);
            }
        }
        public override TextureContent Process(TextureContent input, ContentProcessorContext context)
        {
            // Fallback if we aren't buiding for iOS.
            var platform = ContentHelper.GetMonoGamePlatform();
            if (platform != MonoGamePlatform.iOS)
                return base.Process(input, context);

            // Only go this path if we are compressing the texture
            if (TextureFormat != TextureProcessorOutputFormat.DxtCompressed)
                return base.Process(input, context);

            // TODO: Reflector ResizeToPowerOfTwo(TextureContent tex)
            // Resize the first face and let mips get generated from the dll.
            /*if (ResizeToPowerOfTwo)
            {

            }*/

            var height = input.Faces[0][0].Height;
            var width = input.Faces[0][0].Width;
            var mipLevels = 1;

            var invalidBounds = height != width || !(isPowerOfTwo(height) && isPowerOfTwo(width));

            // Only PVR compress square, power of two textures.
            if (invalidBounds || compressionMode == MGCompressionMode.NoCompression)
            {
                if (compressionMode != MGCompressionMode.NoCompression)
                {
                    context.Logger.LogImportantMessage("WARNING: PVR Texture {0} must be a square, power of two texture. Skipping Compression.",
                                                        Path.GetFileName(context.OutputFilename));
                }

                // Skip compressing this texture and process it normally.
                this.TextureFormat = TextureProcessorOutputFormat.Color;

                return base.Process(input, context);
            }

            // Calculate how many mip levels will be created, and pass that to our DLL.
            if (GenerateMipmaps)
            {
                while (height != 1 || width != 1)
                {
                    height = Math.Max(height / 2, 1);
                    width = Math.Max(width / 2, 1);
                    mipLevels++;
                }
            }

            if (PremultiplyAlpha)
            {
                var colorTex = input.Faces[0][0] as PixelBitmapContent<Color>;
                if (colorTex != null)
                {
                    for (int x = 0; x < colorTex.Height; x++)
                    {
                        var row = colorTex.GetRow(x);
                        for (int y = 0; y < row.Length; y++)
                        {
                            if (row[y].A < 0xff)
                                row[y] = Color.FromNonPremultiplied(row[y].R, row[y].G, row[y].B, row[y].A);
                        }
                    }
                }
                else
                {
                    var vec4Tex = input.Faces[0][0] as PixelBitmapContent<Vector4>;
                    if (vec4Tex == null)
                        throw new NotSupportedException();

                    for (int x = 0; x < vec4Tex.Height; x++)
                    {
                        var row = vec4Tex.GetRow(x);
                        for (int y = 0; y < row.Length; y++)
                        {
                            if (row[y].W < 1.0f)
                            {
                                row[y].X *= row[y].W;
                                row[y].Y *= row[y].W;
                                row[y].Z *= row[y].W;
                            }
                        }
                    }
                }
            }

            ConvertToPVRTC(input, mipLevels, PremultiplyAlpha, compressionMode);

            return input;
        }
Ejemplo n.º 50
0
        // Compress the greyscale font texture page using a specially-formulated DXT3 mode
        static public unsafe void CompressFontDXT3(TextureContent content)
        {
            if (content.Faces.Count > 1)
            {
                throw new PipelineException("Font textures should only have one face");
            }

            var block = new Vector4[16];

            for (int i = 0; i < content.Faces[0].Count; ++i)
            {
                var face     = content.Faces[0][i];
                var xBlocks  = (face.Width + 3) / 4;
                var yBlocks  = (face.Height + 3) / 4;
                var dxt3Size = xBlocks * yBlocks * 16;
                var buffer   = new byte[dxt3Size];

                var bytes = face.GetPixelData();
                fixed(byte *b = bytes)
                {
                    Vector4 *colors = (Vector4 *)b;

                    int w = 0;
                    int h = 0;
                    int x = 0;
                    int y = 0;

                    while (h < (face.Height & ~3))
                    {
                        w = 0;
                        x = 0;

                        var h0 = h * face.Width;
                        var h1 = h0 + face.Width;
                        var h2 = h1 + face.Width;
                        var h3 = h2 + face.Width;

                        while (w < (face.Width & ~3))
                        {
                            block[0]  = colors[w + h0];
                            block[1]  = colors[w + h0 + 1];
                            block[2]  = colors[w + h0 + 2];
                            block[3]  = colors[w + h0 + 3];
                            block[4]  = colors[w + h1];
                            block[5]  = colors[w + h1 + 1];
                            block[6]  = colors[w + h1 + 2];
                            block[7]  = colors[w + h1 + 3];
                            block[8]  = colors[w + h2];
                            block[9]  = colors[w + h2 + 1];
                            block[10] = colors[w + h2 + 2];
                            block[11] = colors[w + h2 + 3];
                            block[12] = colors[w + h3];
                            block[13] = colors[w + h3 + 1];
                            block[14] = colors[w + h3 + 2];
                            block[15] = colors[w + h3 + 3];

                            int offset = (x + y * xBlocks) * 16;
                            CompressFontDXT3Block(block, buffer, offset);

                            w += 4;
                            ++x;
                        }

                        // Do partial block at end of row
                        if (w < face.Width)
                        {
                            var cols = face.Width - w;
                            Array.Clear(block, 0, 16);
                            for (int r = 0; r < 4; ++r)
                            {
                                h0 = (h + r) * face.Width;
                                for (int c = 0; c < cols; ++c)
                                {
                                    block[(r * 4) + c] = colors[w + h0 + c];
                                }
                            }

                            int offset = (x + y * xBlocks) * 16;
                            CompressFontDXT3Block(block, buffer, offset);
                        }

                        h += 4;
                        ++y;
                    }

                    // Do last partial row
                    if (h < face.Height)
                    {
                        var rows = face.Height - h;
                        w = 0;
                        x = 0;
                        while (w < (face.Width & ~3))
                        {
                            Array.Clear(block, 0, 16);
                            for (int r = 0; r < rows; ++r)
                            {
                                var h0 = (h + r) * face.Width;
                                block[(r * 4) + 0] = colors[w + h0 + 0];
                                block[(r * 4) + 1] = colors[w + h0 + 1];
                                block[(r * 4) + 2] = colors[w + h0 + 2];
                                block[(r * 4) + 3] = colors[w + h0 + 3];
                            }

                            int offset = (x + y * xBlocks) * 16;
                            CompressFontDXT3Block(block, buffer, offset);

                            w += 4;
                            ++x;
                        }

                        // Do last partial block
                        if (w < face.Width)
                        {
                            var cols = face.Width - w;
                            Array.Clear(block, 0, 16);
                            for (int r = 0; r < rows; ++r)
                            {
                                var h0 = (h + r) * face.Width;
                                for (int c = 0; c < cols; ++c)
                                {
                                    block[(r * 4) + c] = colors[w + h0 + c];
                                }
                            }

                            int offset = (x + y * xBlocks) * 16;
                            CompressFontDXT3Block(block, buffer, offset);
                        }
                    }
                }

                var dxt3 = new Dxt3BitmapContent(face.Width, face.Height);
                dxt3.SetPixelData(buffer);
                content.Faces[0][i] = dxt3;
            }
        }
Ejemplo n.º 51
0
        private static void CompressDxt(GraphicsProfile profile, TextureContent content, bool generateMipmaps, bool premultipliedAlpha, bool sharpAlpha)
        {
            var texData = content.Faces[0][0];

            if (profile == GraphicsProfile.Reach)
            {
                if (!IsPowerOfTwo(texData.Width) || !IsPowerOfTwo(texData.Height))
                    throw new PipelineException("DXT Compressed textures width and height must be powers of two in GraphicsProfile.Reach.");                
            }

            var pixelData = texData.GetPixelData();

            // Test the alpha channel to figure out if we have alpha.
            var containsAlpha = false;
            var containsFracAlpha = false;
            for (var x = 3; x < pixelData.Length; x += 4)
            {
                if (pixelData[x] != 0xFF)
                {
                    containsAlpha = true;

                    if (pixelData[x] != 0x0)
                        containsFracAlpha = true;
                }
            }

            var _dxtCompressor = new Compressor();
            var inputOptions = new InputOptions();
            if (containsAlpha)           
                inputOptions.SetAlphaMode(premultipliedAlpha ? AlphaMode.Premultiplied : AlphaMode.Transparency);
            else
                inputOptions.SetAlphaMode(AlphaMode.None);
            inputOptions.SetTextureLayout(TextureType.Texture2D, texData.Width, texData.Height, 1);

           
            // Small hack here. NVTT wants 8bit data in BGRA. Flip the B and R channels
            // again here.
            GraphicsUtil.BGRAtoRGBA(pixelData);
            var dataHandle = GCHandle.Alloc(pixelData, GCHandleType.Pinned);
            var dataPtr = dataHandle.AddrOfPinnedObject();

            inputOptions.SetMipmapData(dataPtr, texData.Width, texData.Height, 1, 0, 0);
            inputOptions.SetMipmapGeneration(generateMipmaps);
            inputOptions.SetGamma(1.0f, 1.0f);

            var outputOptions = new OutputOptions();
            outputOptions.SetOutputHeader(false);

            var outputFormat = Format.DXT1;
            if (containsFracAlpha)
            {
                if (sharpAlpha)
                    outputFormat = Format.DXT3;
                else
                    outputFormat = Format.DXT5;
            }

            var handler = new DxtDataHandler(content, outputFormat);
            outputOptions.SetOutputHandler(handler.BeginImage, handler.WriteData);

            var compressionOptions = new CompressionOptions();
            compressionOptions.SetFormat(outputFormat);
            compressionOptions.SetQuality(Quality.Normal);

            _dxtCompressor.Compress(inputOptions, compressionOptions, outputOptions);

            dataHandle.Free();
        }       
Ejemplo n.º 52
0
        private static void CompressDxt(GraphicsProfile profile, TextureContent content, bool generateMipmaps, bool premultipliedAlpha, bool sharpAlpha)
        {
            var texData = content.Faces[0][0];

            if (profile == GraphicsProfile.Reach)
            {
                if (!IsPowerOfTwo(texData.Width) || !IsPowerOfTwo(texData.Height))
                {
                    throw new PipelineException("DXT Compressed textures width and height must be powers of two in GraphicsProfile.Reach.");
                }
            }

            var pixelData = texData.GetPixelData();

            // Test the alpha channel to figure out if we have alpha.
            var containsAlpha     = false;
            var containsFracAlpha = false;

            for (var x = 3; x < pixelData.Length; x += 4)
            {
                if (pixelData[x] != 0xFF)
                {
                    containsAlpha = true;

                    if (pixelData[x] != 0x0)
                    {
                        containsFracAlpha = true;
                    }
                }
            }

            var _dxtCompressor = new Compressor();
            var inputOptions   = new InputOptions();

            if (containsAlpha)
            {
                inputOptions.SetAlphaMode(premultipliedAlpha ? AlphaMode.Premultiplied : AlphaMode.Transparency);
            }
            else
            {
                inputOptions.SetAlphaMode(AlphaMode.None);
            }
            inputOptions.SetTextureLayout(TextureType.Texture2D, texData.Width, texData.Height, 1);


            // Small hack here. NVTT wants 8bit data in BGRA. Flip the B and R channels
            // again here.
            GraphicsUtil.BGRAtoRGBA(pixelData);
            var dataHandle = GCHandle.Alloc(pixelData, GCHandleType.Pinned);
            var dataPtr    = dataHandle.AddrOfPinnedObject();

            inputOptions.SetMipmapData(dataPtr, texData.Width, texData.Height, 1, 0, 0);
            inputOptions.SetMipmapGeneration(generateMipmaps);
            inputOptions.SetGamma(1.0f, 1.0f);

            var outputOptions = new OutputOptions();

            outputOptions.SetOutputHeader(false);

            var outputFormat = Format.DXT1;

            if (containsFracAlpha)
            {
                if (sharpAlpha)
                {
                    outputFormat = Format.DXT3;
                }
                else
                {
                    outputFormat = Format.DXT5;
                }
            }

            var handler = new DxtDataHandler(content, outputFormat);

            outputOptions.SetOutputHandler(handler.BeginImage, handler.WriteData);

            var compressionOptions = new CompressionOptions();

            compressionOptions.SetFormat(outputFormat);
            compressionOptions.SetQuality(Quality.Normal);

            _dxtCompressor.Compress(inputOptions, compressionOptions, outputOptions);

            dataHandle.Free();
        }
Ejemplo n.º 53
0
 public void AddFrame(TimeSpan delayTime, TextureContent content)
 {
     _frames.Add(new Frame {DelayTime = delayTime, Content = content});
 }
Ejemplo n.º 54
0
        /// <summary>
        /// Compresses TextureContent in a format appropriate to the platform
        /// </summary>
        public static void CompressTexture(TextureContent content, ContentProcessorContext context, bool generateMipmaps, bool premultipliedAlpha)
        {
            // TODO: At the moment, only DXT compression from windows machine is supported
            // Add more here as they become available.
            switch (context.TargetPlatform)
            {
                case TargetPlatform.Windows:
                case TargetPlatform.WindowsPhone:
                case TargetPlatform.WindowsPhone8:
                case TargetPlatform.WindowsStoreApp:
                case TargetPlatform.Ouya:
                case TargetPlatform.Android:
                case TargetPlatform.Linux: 
                case TargetPlatform.MacOSX:
                case TargetPlatform.NativeClient:
                case TargetPlatform.Xbox360:
					context.Logger.LogMessage ("Detected {0} using DXT Compression", context.TargetPlatform);
				    CompressDxt(content, generateMipmaps);
				    break;
                case TargetPlatform.iOS:
					context.Logger.LogMessage ("Detected {0} using PVRTC Compression", context.TargetPlatform);
                    CompressPvrtc(content, generateMipmaps, premultipliedAlpha);
                    break;

                default:
                    throw new NotImplementedException(string.Format("Texture Compression it not implemented for {0}", context.TargetPlatform));
            }

        }
Ejemplo n.º 55
0
        private static void CompressDxt(GraphicsProfile profile, TextureContent content, bool generateMipMaps, bool sharpAlpha)
        {
            var face = content.Faces[0][0];

            if (profile == GraphicsProfile.Reach)
            {
                if (!IsPowerOfTwo(face.Width) || !IsPowerOfTwo(face.Height))
                    throw new PipelineException("DXT compression requires width and height must be powers of two in Reach graphics profile.");                
            }

            // Test the alpha channel to figure out if we have alpha.
            var alphaRange = CalculateAlphaRange(face);

            if (alphaRange == AlphaRange.Opaque)
                Compress(typeof(Dxt1BitmapContent), content, generateMipMaps);
            else if (alphaRange == AlphaRange.Cutout || sharpAlpha)
                Compress(typeof(Dxt3BitmapContent), content, generateMipMaps);
            else
                Compress(typeof(Dxt5BitmapContent), content, generateMipMaps);
        }
Ejemplo n.º 56
0
        private static void CompressPvrtc(TextureContent content, bool generateMipmaps, bool premultipliedAlpha)
        {
            // TODO: Once uncompressed mipmap generation is supported, first use NVTT to generate mipmaps,
            // then compress them withthe PVRTC tool, so we have the same implementation of mipmap generation
            // across platforms.

            // Calculate number of mip levels
            var width = content.Faces[0][0].Height;
            var height = content.Faces[0][0].Width;

			if (!IsPowerOfTwo(width) || !IsPowerOfTwo(height))
				throw new PipelineException("PVRTC Compressed textures width and height must be powers of two.");

			if (width != height)
				throw new PipelineException("PVRTC Compressed textures must be square. i.e width == height.");

            var numberOfMipLevels = 1;
            if (generateMipmaps)
            {
                while (height != 1 || width != 1)
                {
                    height = Math.Max(height / 2, 1);
                    width = Math.Max(width / 2, 1);
                    numberOfMipLevels++;
                }
            }

            IntPtr dataSizesPtr = IntPtr.Zero;
            var texDataPtr = ManagedPVRTC.ManagedPVRTC.CompressTexture(content.Faces[0][0].GetPixelData(),
                                            content.Faces[0][0].Height,
                                            content.Faces[0][0].Width,
                                            numberOfMipLevels,
                                            premultipliedAlpha,
                                            true,
                                            ref dataSizesPtr);

            // Store the size of each mip level
            var dataSizesArray = new int[numberOfMipLevels];
            Marshal.Copy(dataSizesPtr, dataSizesArray, 0, dataSizesArray.Length);

            var levelSize = 0;
            byte[] levelData;
            var sourceWidth = content.Faces[0][0].Width;
            var sourceHeight = content.Faces[0][0].Height;

            content.Faces[0].Clear();

            for (int x = 0; x < numberOfMipLevels; x++)
            {
                levelSize = dataSizesArray[x];
                levelData = new byte[levelSize];

                Marshal.Copy(texDataPtr, levelData, 0, levelSize);

                var levelWidth = Math.Max(sourceWidth >> x, 1);
                var levelHeight = Math.Max(sourceHeight >> x, 1);

                var bmpContent = new PvrtcBitmapContent(4, sourceWidth, sourceHeight);
                bmpContent.SetPixelData(levelData);
                content.Faces[0].Add(bmpContent);

                texDataPtr = IntPtr.Add(texDataPtr, levelSize);
            }
        }
Ejemplo n.º 57
0
        static void CompressColor16Bit(TextureContent content, bool generateMipMaps)
        {
            var face = content.Faces[0][0];
            var alphaRange = CalculateAlphaRange(face);

            if (alphaRange == AlphaRange.Opaque)
                Compress(typeof(PixelBitmapContent<Bgr565>), content, generateMipMaps);
            else if (alphaRange == AlphaRange.Cutout)
                Compress(typeof(PixelBitmapContent<Bgra5551>), content, generateMipMaps);
            else
                Compress(typeof(PixelBitmapContent<Bgra4444>), content, generateMipMaps);
        }
 /// <summary>
 /// Constructs a new skinning data object.
 /// </summary>
 public InstancedSkinningDataContent(IDictionary<string, InstancedAnimationClip> animationClips, TextureContent animationTexture)
 {
     this.animations = animationClips;
     this.texture = animationTexture;
 }
        //--------------------------------------------------------------
        /// <summary>
        /// Converts an XNA <see cref="TextureContent"/> to a DigitalRune <see cref="Texture"/>.
        /// </summary>
        /// <param name="textureContent">The <see cref="TextureContent"/>.</param>
        /// <returns>The <see cref="Texture"/>.</returns>
        public static Texture ToTexture(TextureContent textureContent)
        {
            SurfaceFormat surfaceFormat;
              var bitmapContent0 = textureContent.Faces[0][0];
              if (!bitmapContent0.TryGetFormat(out surfaceFormat))
            throw new InvalidContentException("Invalid surface format.", textureContent.Identity);

              var texture2DContent = textureContent as Texture2DContent;
              if (texture2DContent != null)
              {
            var description = new TextureDescription
            {
              Dimension = TextureDimension.Texture2D,
              Width = bitmapContent0.Width,
              Height = bitmapContent0.Height,
              Depth = 1,
              MipLevels = texture2DContent.Mipmaps.Count,
              ArraySize = 1,
              Format = surfaceFormat.ToDataFormat()
            };

            var texture = new Texture(description);
            for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++)
            {
              var bitmapContent = texture2DContent.Mipmaps[mipIndex];
              var image = texture.Images[texture.GetImageIndex(mipIndex, 0, 0)];
              Buffer.BlockCopy(bitmapContent.GetPixelData(), 0, image.Data, 0, image.Data.Length);
            }

            return texture;
              }

              var textureCubeContent = textureContent as TextureCubeContent;
              if (textureCubeContent != null)
              {
            var description = new TextureDescription
            {
              Dimension = TextureDimension.TextureCube,
              Width = bitmapContent0.Width,
              Height = bitmapContent0.Height,
              Depth = 1,
              MipLevels = textureCubeContent.Faces[0].Count,
              ArraySize = 6,
              Format = surfaceFormat.ToDataFormat()
            };

            var texture = new Texture(description);
            for (int faceIndex = 0; faceIndex < 6; faceIndex++)
            {
              for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++)
              {
            var bitmapContent = textureCubeContent.Faces[faceIndex][mipIndex];
            var image = texture.Images[texture.GetImageIndex(mipIndex, faceIndex, 0)];
            Buffer.BlockCopy(bitmapContent.GetPixelData(), 0, image.Data, 0, image.Data.Length);
              }
            }

            return texture;
              }

              var texture3DContent = textureContent as Texture3DContent;
              if (texture3DContent != null)
              {
            var description = new TextureDescription
            {
              Dimension = TextureDimension.Texture3D,
              Width = bitmapContent0.Width,
              Height = bitmapContent0.Height,
              Depth = texture3DContent.Faces.Count,
              MipLevels = texture3DContent.Faces[0].Count,
              ArraySize = 1,
              Format = surfaceFormat.ToDataFormat()
            };

            var texture = new Texture(description);
            for (int zIndex = 0; zIndex < description.Depth; zIndex++)
            {
              for (int mipIndex = 0; mipIndex < description.MipLevels; mipIndex++)
              {
            var bitmapContent = texture3DContent.Faces[zIndex][mipIndex];
            var image = texture.Images[texture.GetImageIndex(mipIndex, 0, zIndex)];
            Buffer.BlockCopy(bitmapContent.GetPixelData(), 0, image.Data, 0, image.Data.Length);
              }
            }

            return texture;
              }

              throw new InvalidOperationException("Invalid texture dimension.");
        }