Ejemplo n.º 1
0
        void InitializeBloomFilter()
        {
            BloomEnabled = true;

            // A bloom filter makes graphics appear to be bright and glowing by adding blur around only
            // the brightest parts of the image. This approximates the look of HDR (high dynamic range)
            // rendering, in which the color of the brightest light sources spills over onto surrounding
            // pixels.
            //
            // Many different visual styles can be achieved by adjusting these settings:
            //
            //  Intensity = how much bloom is added
            //      0 = none
            //
            //  Threshold = how bright does a pixel have to be in order for it to bloom
            //      0 = the entire image blooms equally
            //
            //  Blur = how much the glow spreads sideways around bright areas

            BloomIntensity = 200;
            BloomThreshold = 80;
            BloomBlur      = 48;

            // Before drawing, properties of these effects will be adjusted to match the
            // current settings (see ApplyBloomFilter), and an input image connected to
            // extractBrightAreas.Source and bloomResult.Background (see DemandCreateBloomRenderTarget).

            // Step 1: use a transfer effect to extract only pixels brighter than the threshold.
            extractBrightAreas = new LinearTransferEffect
            {
                ClampOutput = true,
            };

            // Step 2: blur these bright pixels.
            blurBrightAreas = new GaussianBlurEffect
            {
                Source = extractBrightAreas,
            };

            // Step 3: adjust how much bloom is wanted.
            adjustBloomIntensity = new LinearTransferEffect
            {
                Source = blurBrightAreas,
            };

            // Step 4: blend the bloom over the top of the original image.
            bloomResult = new BlendEffect
            {
                Foreground = adjustBloomIntensity,
                Mode       = BlendEffectMode.Screen,
            };
        }
Ejemplo n.º 2
0
 public BloomRendering()
 {
     extractBrightAreas = new LinearTransferEffect
     {
         ClampOutput = true,
     };
     blurBrightAreas = new GaussianBlurEffect
     {
         Source = extractBrightAreas,
     };
     adjustBloomIntensity = new LinearTransferEffect
     {
         Source = blurBrightAreas,
     };
     result = new BlendEffect
     {
         Foreground = adjustBloomIntensity,
         Mode       = BlendEffectMode.Screen,
     };
 }
        void InitializeBloomFilter()
        {
            BloomEnabled = true;

            // A bloom filter makes graphics appear to be bright and glowing by adding blur around only
            // the brightest parts of the image. This approximates the look of HDR (high dynamic range)
            // rendering, in which the color of the brightest light sources spills over onto surrounding
            // pixels.
            //
            // Many different visual styles can be achieved by adjusting these settings:
            //
            //  Intensity = how much bloom is added
            //      0 = none
            //
            //  Threshold = how bright does a pixel have to be in order for it to bloom
            //      0 = the entire image blooms equally
            //
            //  Blur = how much the glow spreads sideways around bright areas

            BloomIntensity = 200;
            BloomThreshold = 80;
            BloomBlur = 48;

            // Before drawing, properties of these effects will be adjusted to match the
            // current settings (see ApplyBloomFilter), and an input image connected to
            // extractBrightAreas.Source and bloomResult.Background (see DemandCreateBloomRenderTarget).

            // Step 1: use a transfer effect to extract only pixels brighter than the threshold.
            extractBrightAreas = new LinearTransferEffect
            {
                ClampOutput = true,
            };

            // Step 2: blur these bright pixels.
            blurBrightAreas = new GaussianBlurEffect
            {
                Source = extractBrightAreas,
            };

            // Step 3: adjust how much bloom is wanted.
            adjustBloomIntensity = new LinearTransferEffect
            {
                Source = blurBrightAreas,
            };

            // Step 4: blend the bloom over the top of the original image.
            bloomResult = new BlendEffect
            {
                Foreground = adjustBloomIntensity,
                Mode = BlendEffectMode.Screen,
            };
        }
Ejemplo n.º 4
0
        private ICanvasImage CreateLuminanceToAlpha()
        {
            var contrastAdjustedTiger = new LinearTransferEffect
            {
                Source = bitmapTiger,

                RedOffset = -3,
                GreenOffset = -3,
                BlueOffset = -3,
            };

            var tigerAlpha = new LuminanceToAlphaEffect
            {
                Source = contrastAdjustedTiger
            };

            var tigerAlphaWithWhiteRgb = new LinearTransferEffect
            {
                Source = tigerAlpha,
                RedOffset = 1,
                GreenOffset = 1,
                BlueOffset = 1,
                RedSlope = 0,
                GreenSlope = 0,
                BlueSlope = 0,
            };

            var recombinedRgbAndAlpha = new ArithmeticCompositeEffect
            {
                Source1 = tigerAlphaWithWhiteRgb,
                Source2 = bitmapTiger,
            };

            var movedTiger = new Transform2DEffect
            {
                Source = recombinedRgbAndAlpha
            };

            const float turbulenceSize = 128;

            var backgroundImage = new CropEffect
            {
                Source = new TileEffect
                {
                    Source = new TurbulenceEffect
                    {
                        Octaves = 8,
                        Size = new Vector2(turbulenceSize),
                        Tileable = true
                    },
                    SourceRectangle= new Rect(0, 0, turbulenceSize, turbulenceSize)
                },
                SourceRectangle = new Rect((bitmapTiger.Size.ToVector2() * -0.5f).ToPoint(),
                                           (bitmapTiger.Size.ToVector2() * 1.5f).ToPoint())
            };

            var tigerOnBackground = new BlendEffect
            {
                Foreground = movedTiger,
                Background = backgroundImage
            };

            // Animation moves the alpha bitmap around, and alters color transfer settings to change how solid it is.
            animationFunction = elapsedTime =>
            {
                contrastAdjustedTiger.RedSlope =
                contrastAdjustedTiger.GreenSlope =
                contrastAdjustedTiger.BlueSlope = ((float)Math.Sin(elapsedTime * 0.9) + 2) * 3;

                var dx = (float)Math.Cos(elapsedTime) * 50;
                var dy = (float)Math.Sin(elapsedTime) * 50;

                movedTiger.TransformMatrix = Matrix3x2.CreateTranslation(dx, dy);
            };

            return tigerOnBackground;
        }
Ejemplo n.º 5
0
        void CreateEffects()
        {
            // The Game of Life is a cellular automaton with very simple rules.
            // Each cell (pixel) can be either alive (white) or dead (black).
            // The state is updated by:
            //
            //  - for each cell, count how many of its 8 neighbors are alive
            //  - if less than two, the cell dies from loneliness
            //  - if exactly two, the cell keeps its current state
            //  - if exactly three, the cell become alive
            //  - if more than three, the cell dies from overcrowding

            // Step 1: use a convolve matrix to count how many neighbors are alive. This filter
            // also includes the state of the current cell, but with a lower weighting. The result
            // is an arithmetic encoding where (value / 2) indicates how many neighbors are alive,
            // and (value % 2) is the state of the cell itself. This is divided by 18 to make it
            // fit within 0-1 color range.

            countNeighborsEffect = new ConvolveMatrixEffect
            {
                KernelMatrix = new float[]
                {
                    2, 2, 2,
                    2, 1, 2,
                    2, 2, 2
                },

                Divisor    = 18,
                BorderMode = EffectBorderMode.Hard,
            };

            // Step 2: use a color transfer table to map the different states produced by the
            // convolve matrix to whether the cell should live or die. Each pair of entries in
            // this table corresponds to a certain number of live neighbors. The first of the
            // pair is the result if the current cell is dead, or the second if it is alive.

            float[] transferTable =
            {
                0, 0,   // 0 live neighbors -> dead cell
                0, 0,   // 1 live neighbors -> dead cell
                0, 1,   // 2 live neighbors -> cell keeps its current state
                1, 1,   // 3 live neighbors -> live cell
                0, 0,   // 4 live neighbors -> dead cell
                0, 0,   // 5 live neighbors -> dead cell
                0, 0,   // 6 live neighbors -> dead cell
                0, 0,   // 7 live neighbors -> dead cell
                0, 0,   // 8 live neighbors -> dead cell
            };

            liveOrDieEffect = new DiscreteTransferEffect
            {
                Source = countNeighborsEffect,

                RedTable   = transferTable,
                GreenTable = transferTable,
                BlueTable  = transferTable,
            };

            // Step 3: the algorithm is implemented in terms of white = live,
            // black = dead, but we invert these colors before displaying the
            // result, just 'cause I think it looks better that way.

            invertEffect = new LinearTransferEffect
            {
                RedSlope    = -1,
                RedOffset   = 1,
                GreenSlope  = -1,
                GreenOffset = 1,
                BlueSlope   = -1,
                BlueOffset  = 1,
            };

            // Step 4: insert our own DPI compensation effect to stop the system trying to
            // automatically convert DPI for us. The Game of Life simulation always works
            // in pixels (96 DPI) regardless of display DPI. Normally, the system would
            // handle this mismatch automatically and scale the image up as needed to fit
            // higher DPI displays. We don't want that behavior here, because it would use
            // a linear filter while we want nearest neighbor. So we insert a no-op DPI
            // converter of our own. This overrides the default adjustment by telling the
            // system the source image is already the same DPI as the destination canvas
            // (even though it really isn't). We'll handle any necessary scaling later
            // ourselves, using Transform2DEffect to control the interpolation mode.

            var dpiCompensationEffect = new DpiCompensationEffect
            {
                Source    = invertEffect,
                SourceDpi = new Vector2(canvas.Dpi),
            };

            // Step 5: a transform matrix scales up the simulation rendertarget and moves
            // it to the right part of the screen. This uses nearest neighbor filtering
            // to avoid unwanted blurring of the cell shapes.

            transformEffect = new Transform2DEffect
            {
                Source            = dpiCompensationEffect,
                InterpolationMode = CanvasImageInterpolation.NearestNeighbor,
            };
        }
Ejemplo n.º 6
0
        private ICanvasImage CreateLuminanceToAlpha()
        {
            var contrastAdjustedTiger = new LinearTransferEffect
            {
                Source = bitmapTiger,

                RedOffset   = -3,
                GreenOffset = -3,
                BlueOffset  = -3,
            };

            var tigerAlpha = new LuminanceToAlphaEffect
            {
                Source = contrastAdjustedTiger
            };

            var tigerAlphaWithWhiteRgb = new LinearTransferEffect
            {
                Source      = tigerAlpha,
                RedOffset   = 1,
                GreenOffset = 1,
                BlueOffset  = 1,
                RedSlope    = 0,
                GreenSlope  = 0,
                BlueSlope   = 0,
            };

            var recombinedRgbAndAlpha = new ArithmeticCompositeEffect
            {
                Source1 = tigerAlphaWithWhiteRgb,
                Source2 = bitmapTiger,
            };

            var movedTiger = new Transform2DEffect
            {
                Source = recombinedRgbAndAlpha
            };

            const float turbulenceSize = 128;

            var backgroundImage = new CropEffect
            {
                Source = new TileEffect
                {
                    Source = new TurbulenceEffect
                    {
                        Octaves  = 8,
                        Size     = new Vector2(turbulenceSize),
                        Tileable = true
                    },
                    SourceRectangle = new Rect(0, 0, turbulenceSize, turbulenceSize)
                },
                SourceRectangle = new Rect((bitmapTiger.Size.ToVector2() * -0.5f).ToPoint(),
                                           (bitmapTiger.Size.ToVector2() * 1.5f).ToPoint())
            };

            var tigerOnBackground = new BlendEffect
            {
                Foreground = movedTiger,
                Background = backgroundImage
            };

            // Animation moves the alpha bitmap around, and alters color transfer settings to change how solid it is.
            animationFunction = elapsedTime =>
            {
                contrastAdjustedTiger.RedSlope          =
                    contrastAdjustedTiger.GreenSlope    =
                        contrastAdjustedTiger.BlueSlope = ((float)Math.Sin(elapsedTime * 0.9) + 2) * 3;

                var dx = (float)Math.Cos(elapsedTime) * 50;
                var dy = (float)Math.Sin(elapsedTime) * 50;

                movedTiger.TransformMatrix = Matrix3x2.CreateTranslation(dx, dy);
            };

            return(tigerOnBackground);
        }
Ejemplo n.º 7
0
        void CreateEffects()
        {
            // The Game of Life is a cellular automaton with very simple rules.
            // Each cell (pixel) can be either alive (white) or dead (black).
            // The state is updated by:
            //
            //  - for each cell, count how many of its 8 neighbors are alive
            //  - if less than two, the cell dies from loneliness
            //  - if exactly two, the cell keeps its current state
            //  - if exactly three, the cell become alive
            //  - if more than three, the cell dies from overcrowding

            // Step 1: use a convolve matrix to count how many neighbors are alive. This filter
            // also includes the state of the current cell, but with a lower weighting. The result
            // is an arithmetic encoding where (value / 2) indicates how many neighbors are alive,
            // and (value % 2) is the state of the cell itself. This is divided by 18 to make it
            // fit within 0-1 color range.

            countNeighborsEffect = new ConvolveMatrixEffect
            {
                KernelMatrix = new float[]
                {
                    2, 2, 2,
                    2, 1, 2,
                    2, 2, 2
                },

                Divisor = 18,
                BorderMode = EffectBorderMode.Hard,
            };

            // Step 2: use a color transfer table to map the different states produced by the
            // convolve matrix to whether the cell should live or die. Each pair of entries in
            // this table corresponds to a certain number of live neighbors. The first of the
            // pair is the result if the current cell is dead, or the second if it is alive.

            float[] transferTable =
            {
                0, 0,   // 0 live neighbors -> dead cell
                0, 0,   // 1 live neighbors -> dead cell
                0, 1,   // 2 live neighbors -> cell keeps its current state
                1, 1,   // 3 live neighbors -> live cell
                0, 0,   // 4 live neighbors -> dead cell
                0, 0,   // 5 live neighbors -> dead cell
                0, 0,   // 6 live neighbors -> dead cell
                0, 0,   // 7 live neighbors -> dead cell
                0, 0,   // 8 live neighbors -> dead cell
            };

            liveOrDieEffect = new DiscreteTransferEffect
            {
                Source = countNeighborsEffect,

                RedTable = transferTable,
                GreenTable = transferTable,
                BlueTable = transferTable,
            };

            // Step 3: the algorithm is implemented in terms of white = live,
            // black = dead, but we invert these colors before displaying the
            // result, just 'cause I think it looks better that way.

            invertEffect = new LinearTransferEffect
            {
                RedSlope = -1,
                RedOffset = 1,
                GreenSlope = -1,
                GreenOffset = 1,
                BlueSlope = -1,
                BlueOffset = 1,
            };

            // Step 4: insert our own DPI compensation effect to stop the system trying to
            // automatically convert DPI for us. The Game of Life simulation always works
            // in pixels (96 DPI) regardless of display DPI. Normally, the system would
            // handle this mismatch automatically and scale the image up as needed to fit
            // higher DPI displays. We don't want that behavior here, because it would use
            // a linear filter while we want nearest neighbor. So we insert a no-op DPI
            // converter of our own. This overrides the default adjustment by telling the
            // system the source image is already the same DPI as the destination canvas
            // (even though it really isn't). We'll handle any necessary scaling later
            // ourselves, using Transform2DEffect to control the interpolation mode.

            var dpiCompensationEffect = new DpiCompensationEffect
            {
                Source = invertEffect,
                SourceDpi = new Vector2(canvas.Dpi),
            };

            // Step 5: a transform matrix scales up the simulation rendertarget and moves
            // it to the right part of the screen. This uses nearest neighbor filtering
            // to avoid unwanted blurring of the cell shapes.

            transformEffect = new Transform2DEffect
            {
                Source = dpiCompensationEffect,
                InterpolationMode = CanvasImageInterpolation.NearestNeighbor,
            };
        }