Exemplo n.º 1
0
        /// <summary>
        /// <para>Set the filter format of the blur filter.</para>
        /// <para>Note: Some filter formats require the graphics device support texture filtering for the given format</para>
        /// </summary>
        /// <param name="filterFormat"></param>
        /// <param name="bellCurveExponent">
        /// <para>A scale value to infulence the bell curve used to generate the filter kernel.</para>
        /// <para>A value of 1.0 generates a standard blur filter kernels. Larger values will produce a tighter curve, and less blur.</para>
        /// <para>Smaller values will produce a wider curve, and a larger blur - but may produce a visible edge as the curve more rapidly ends.</para>
        /// </param>
        public void SetFilterFormat(BlurFilterFormat filterFormat, float bellCurveExponent)
        {
            //IsFilterFormat
            bool filteringSupported = DrawTargetTexture2D.SupportsFormatFiltering(source.SurfaceFormat);

            if (filteringSupported == false && filterFormat == BlurFilterFormat.ThirtyOneSampleBlur_FilteredTextureFormat)
            {
                throw new ArgumentException("BlurFilterFormat.ThirtyOneSampleBlurFiltered is not supported, Hardware does not support texture filter for " + source.SurfaceFormat.ToString());
            }

            FilterGenerator.SetFilter(filterFormat, true, this.filterH, filteringSupported, bellCurveExponent);
            FilterGenerator.SetFilter(filterFormat, false, this.filterV, filteringSupported, bellCurveExponent);
        }
Exemplo n.º 2
0
        public static void SetFilter(BlurFilterFormat format, bool xAxis, SinglePassTextureFilter target, bool supportsFiltering, float bellExponent)
        {
            lock (weights)
            {
                int kernel = GenerateFilter(format, supportsFiltering, bellExponent);

                Vector2 axis = new Vector2(xAxis ? 1 : 0, xAxis ? 0 : 1);

                for (int i = 0; i < 16; i++)
                {
                    offsetsV[i] = axis * offset[i];
                }

                target.SetFilter(offsetsV, weights, kernel);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Blur the source horizontally to the <paramref name="intermediate"/> target, then blur vertically to <paramref name="target"/>.
        /// </summary>
        /// <param name="source"></param>
        /// <param name="filterFormat">format of the blur filter</param>
        /// <param name="intermediate">draw target to use as a temporary, intermediate target for blurring</param>
        /// <param name="target"></param>
        /// <param name="bellCurveExponent">
        /// <para>A scale value to infulence the bell curve used to generate the filter kernel.</para>
        /// <para>A value of 1.0 generates a standard blur filter kernels. Larger values will produce a tighter curve, and less blur.</para>
        /// <para>Smaller values will produce a wider curve, and a larger blur - but may produce a visible edge as the curve more rapidly ends.</para>
        /// </param>
        public BlurFilter(BlurFilterFormat filterFormat, float bellCurveExponent, DrawTargetTexture2D source, DrawTargetTexture2D intermediate, DrawTargetTexture2D target)
        {
            if (target == null || source == null)
            {
                throw new ArgumentNullException();
            }

            if (intermediate != null && source.SurfaceFormat != intermediate.SurfaceFormat)
            {
                throw new ArgumentException("source.SurfaceFormat != intermediate.SurfaceFormat");
            }
            if (intermediate != null && target.SurfaceFormat != intermediate.SurfaceFormat)
            {
                throw new ArgumentException("target.SurfaceFormat != intermediate.SurfaceFormat");
            }

            this.source = source;

#if XBOX360
            //if the surface will fit into EDRAM then the intermediate can be skipped
            if (source.Width * source.Height * DrawTarget.FormatSize(source.SurfaceFormat) < 1000 * 1000 * 10)  //approx
            {
                this.filterV = new SinglePassTextureFilter(source, target);
                this.filterH = new SinglePassTextureFilter(target, target);
            }
            else
            {
                this.filterV = new SinglePassTextureFilter(source, intermediate);
                this.filterH = new SinglePassTextureFilter(intermediate, source);
            }
#else
            this.filterV = new SinglePassTextureFilter(source, intermediate);
            this.filterH = new SinglePassTextureFilter(intermediate, target);
#endif

            SetFilterFormat(filterFormat, bellCurveExponent);
        }
Exemplo n.º 4
0
 /// <summary>
 /// Blur the source horizontally to the <paramref name="intermediate"/> target, then blur vertically back to <paramref name="source"/>. (Xbox360 may specify null for <paramref name="intermediate"/> if the render target will fit in 10mib)
 /// </summary>
 /// <param name="source"></param>
 /// <param name="filterFormat">format of the blur filter</param>
 /// <param name="intermediate">draw target to use as a temporary, intermediate target for blurring</param>
 /// <param name="bellCurveExponent">
 /// <para>A scale value to infulence the bell curve used to generate the filter kernel.</para>
 /// <para>A value of 1.0 generates a standard blur filter kernels. Larger values will produce a tighter curve, and less blur.</para>
 /// <para>Smaller values will produce a wider curve, and a larger blur - but may produce a visible edge as the curve more rapidly ends.</para>
 /// </param>
 public BlurFilter(BlurFilterFormat filterFormat, float bellCurveExponent, DrawTargetTexture2D source, DrawTargetTexture2D intermediate) :
     this(filterFormat, bellCurveExponent, source, intermediate, source)
 {
 }
Exemplo n.º 5
0
        //generates weight and offset value for bell curve filters
        private static int GenerateFilter(BlurFilterFormat format, bool filtered, float bellExponent)
        {
            int samples = 0;

            switch (format)
            {
            case BlurFilterFormat.ThreeSampleBlur:
                samples = 3;
                break;

            case BlurFilterFormat.FiveSampleBlur:
                samples = 5;
                break;

            case BlurFilterFormat.SevenSampleBlur:
                samples = 7;
                break;

            case BlurFilterFormat.FifteenSampleBlur:
                samples = 15;
                break;

            case BlurFilterFormat.ThirtyOneSampleBlur_FilteredTextureFormat:
                if (!filtered)
                {
                    throw new ArgumentException();
                }
                samples = 31;
                break;
            }

            int actualSamples = samples;

            if (filtered)
            {
                actualSamples = samples / 2 + 1;
            }

            if (!filtered)
            {
                //centre sample samples the 0 offset pixel
                int centre = actualSamples / 2;
                weights[centre] = 1;
                offset[centre]  = 0;

                double total = 1;

                for (int i = 1; i <= centre; i++)
                {
                    //bell curve
                    //~ exp(- x^2 )
                    double x = (i / (double)(centre + 1));

                    double bell = Math.Exp(-(x * x) * 3 * bellExponent);
                    total += bell * 2;

                    offset[centre - i]  = -i;
                    offset[centre + i]  = i;
                    weights[centre - i] = (float)bell;
                    weights[centre + i] = (float)bell;
                }

                float inv = 1.0f / (float)total;
                for (int i = 0; i < actualSamples; i++)
                {
                    weights[i] *= inv;
                }
            }
            else
            {
                bool isOdd = (actualSamples & 1) == 1;

                //if it's odd, there is a centre sample

                int count = actualSamples / 2;

                double total = 0;

                if (isOdd)
                {
                    weights[count] = 2;
                    offset[count]  = 0;
                    total          = 2;
                }


                for (int i = 0; i < count; i++)
                {
                    //bell curve
                    //~ exp(- x^2 )
                    //each is made up of two combined samples (filter)
                    double x1, x2;

                    if (isOdd)
                    {
                        x1 = ((i * 2 + 1) / (double)(actualSamples));
                        x2 = ((i * 2 + 2) / (double)(actualSamples));
                    }
                    else
                    {
                        x1 = ((i * 2) / (double)(actualSamples));
                        x2 = ((i * 2 + 1) / (double)(actualSamples));
                    }

                    double bell1 = Math.Exp(-(x1 * x1) * 3 * bellExponent);
                    double bell2 = Math.Exp(-(x2 * x2) * 3 * bellExponent);

                    if (!isOdd && i == 0)
                    {
                        bell1 *= 0.5;                         //two samples on the centre
                    }
                    double bias;
                    if (isOdd)
                    {
                        bias = ((i * 2 + 1) * bell1 + (i * 2 + 2) * bell2) / (bell1 + bell2);
                    }
                    else
                    {
                        bias = (i * 2 * bell1 + (i * 2 + 1) * bell2) / (bell1 + bell2);
                    }
                    double weight = bell1 + bell2;

                    total += weight * 2;

                    int p = isOdd ? 1 : 0;

                    offset[count - i - 1]  = -(float)bias;
                    offset[count + i + p]  = (float)bias;
                    weights[count - i - 1] = (float)weight;
                    weights[count + i + p] = (float)weight;
                }

                float inv = 1.0f / (float)total;
                for (int i = 0; i < actualSamples; i++)
                {
                    weights[i] *= inv;
                }
            }
            return(actualSamples);
        }
		//generates weight and offset value for bell curve filters
		private static int GenerateFilter(BlurFilterFormat format, bool filtered, float bellExponent)
		{
			int samples = 0;
			switch (format)
			{
				case BlurFilterFormat.ThreeSampleBlur:
					samples = 3;
					break;
				case BlurFilterFormat.FiveSampleBlur:
					samples = 5;
					break;
				case BlurFilterFormat.SevenSampleBlur:
					samples = 7;
					break;
				case BlurFilterFormat.FifteenSampleBlur:
					samples = 15;
					break;
				case BlurFilterFormat.ThirtyOneSampleBlur_FilteredTextureFormat:
					if (!filtered)
						throw new ArgumentException();
					samples = 31;
					break;
			}

			int actualSamples = samples;
			if (filtered)
				actualSamples = samples / 2 + 1;

			if (!filtered)
			{
				//centre sample samples the 0 offset pixel
				int centre = actualSamples / 2;
				weights[centre] = 1;
				offset[centre] = 0;

				double total = 1;

				for (int i = 1; i <= centre; i++)
				{
					//bell curve
					//~ exp(- x^2 )
					double x = (i / (double)(centre + 1));

					double bell = Math.Exp(-(x * x) * 3 * bellExponent);
					total += bell * 2;

					offset[centre - i] = -i;
					offset[centre + i] = i;
					weights[centre - i] = (float)bell;
					weights[centre + i] = (float)bell;
				}

				float inv = 1.0f / (float)total;
				for (int i = 0; i < actualSamples; i++)
					weights[i] *= inv;
			}
			else
			{
				bool isOdd = (actualSamples & 1) == 1;

				//if it's odd, there is a centre sample

				int count = actualSamples/2;

				double total = 0;

				if (isOdd)
				{
					weights[count] = 2;
					offset[count] = 0;
					total = 2;
				}


				for (int i = 0; i < count; i++)
				{
					//bell curve
					//~ exp(- x^2 )
					//each is made up of two combined samples (filter)
					double x1,x2;

					if (isOdd)
					{
						x1 = ((i * 2 + 1) / (double)(actualSamples));
						x2 = ((i * 2 + 2) / (double)(actualSamples));
					}
					else
					{
						x1 = ((i * 2) / (double)(actualSamples));
						x2 = ((i * 2 + 1) / (double)(actualSamples));
					}

					double bell1 = Math.Exp(-(x1 * x1) * 3 * bellExponent);
					double bell2 = Math.Exp(-(x2 * x2) * 3 * bellExponent);

					if (!isOdd && i == 0)
						bell1 *= 0.5; //two samples on the centre

					double bias;
					if (isOdd)
						bias = ((i*2 + 1) * bell1 + (i*2 + 2) * bell2) / (bell1 + bell2);
					else
						bias = (i*2 * bell1 + (i*2 + 1) * bell2) / (bell1 + bell2);
					double weight = bell1 + bell2;

					total += weight * 2;

					int p = isOdd ? 1 : 0;

					offset[count - i - 1] = -(float)bias;
					offset[count + i + p] = (float)bias;
					weights[count - i - 1] = (float)weight;
					weights[count + i + p] = (float)weight;

				}

				float inv = 1.0f / (float)total;
				for (int i = 0; i < actualSamples; i++)
					weights[i] *= inv;
			}
			return actualSamples;
		}
		/// <summary>
		/// <para>Set the filter format of the blur filter.</para>
		/// <para>Note: Some filter formats require the graphics device support texture filtering for the given format</para>
		/// </summary>
		/// <param name="filterFormat"></param>
		/// <param name="bellCurveExponent">
		/// <para>A scale value to infulence the bell curve used to generate the filter kernel.</para>
		/// <para>A value of 1.0 generates a standard blur filter kernels. Larger values will produce a tighter curve, and less blur.</para>
		/// <para>Smaller values will produce a wider curve, and a larger blur - but may produce a visible edge as the curve more rapidly ends.</para>
		/// </param>
		public void SetFilterFormat(BlurFilterFormat filterFormat, float bellCurveExponent)
		{
			//IsFilterFormat
			bool filteringSupported = 
				
				DrawTargetTexture2D.SupportsFormatFiltering(source.SurfaceFormat);

			if (filteringSupported == false && filterFormat == BlurFilterFormat.ThirtyOneSampleBlur_FilteredTextureFormat)
				throw new ArgumentException("BlurFilterFormat.ThirtyOneSampleBlurFiltered is not supported, Hardware does not support texture filter for " + source.SurfaceFormat.ToString());

			FilterGenerator.SetFilter(filterFormat, true, this.filterH, filteringSupported, bellCurveExponent);
			FilterGenerator.SetFilter(filterFormat, false, this.filterV, filteringSupported, bellCurveExponent);
		}
		/// <summary>
		/// Blur the source horizontally to the <paramref name="intermediate"/> target, then blur vertically to <paramref name="target"/>.
		/// </summary>
		/// <param name="source"></param>
		/// <param name="filterFormat">format of the blur filter</param>
		/// <param name="intermediate">draw target to use as a temporary, intermediate target for blurring</param>
		/// <param name="target"></param>
		/// <param name="bellCurveExponent">
		/// <para>A scale value to infulence the bell curve used to generate the filter kernel.</para>
		/// <para>A value of 1.0 generates a standard blur filter kernels. Larger values will produce a tighter curve, and less blur.</para>
		/// <para>Smaller values will produce a wider curve, and a larger blur - but may produce a visible edge as the curve more rapidly ends.</para>
		/// </param>
		public BlurFilter(BlurFilterFormat filterFormat, float bellCurveExponent, DrawTargetTexture2D source, DrawTargetTexture2D intermediate, DrawTargetTexture2D target)
		{
			if (target == null || source == null)
				throw new ArgumentNullException();

			if (intermediate != null && source.SurfaceFormat != intermediate.SurfaceFormat)
				throw new ArgumentException("source.SurfaceFormat != intermediate.SurfaceFormat");
			if (intermediate != null && target.SurfaceFormat != intermediate.SurfaceFormat)
				throw new ArgumentException("target.SurfaceFormat != intermediate.SurfaceFormat");

			this.source = source;

			this.filterV = new SinglePassTextureFilter(source, intermediate);
			this.filterH = new SinglePassTextureFilter(intermediate, target);

			SetFilterFormat(filterFormat, bellCurveExponent);
		}
		/// <summary>
		/// Blur the source horizontally to the <paramref name="intermediate"/> target, then blur vertically back to <paramref name="source"/>.
		/// </summary>
		/// <param name="source"></param>
		/// <param name="filterFormat">format of the blur filter</param>
		/// <param name="intermediate">draw target to use as a temporary, intermediate target for blurring</param>
		/// <param name="bellCurveExponent">
		/// <para>A scale value to infulence the bell curve used to generate the filter kernel.</para>
		/// <para>A value of 1.0 generates a standard blur filter kernels. Larger values will produce a tighter curve, and less blur.</para>
		/// <para>Smaller values will produce a wider curve, and a larger blur - but may produce a visible edge as the curve more rapidly ends.</para>
		/// </param>
		public BlurFilter(BlurFilterFormat filterFormat, float bellCurveExponent, DrawTargetTexture2D source, DrawTargetTexture2D intermediate) :
			this(filterFormat, bellCurveExponent, source, intermediate, source)
		{
		}
		public static void SetFilter(BlurFilterFormat format, bool xAxis, SinglePassTextureFilter target, bool supportsFiltering, float bellExponent)
		{
			lock (weights)
			{
				int kernel = GenerateFilter(format, supportsFiltering, bellExponent);

				Vector2 axis = new Vector2(xAxis ? 1 : 0, xAxis ? 0 : 1);

				for (int i = 0; i < 16; i++)
					offsetsV[i] = axis * offset[i];

				target.SetFilter(offsetsV, weights, kernel);
			}
		}