コード例 #1
0
ファイル: TextureFilter.cs プロジェクト: ARLM-Attic/xna-xen
        internal SinglePassTextureFilter(DrawTargetTexture2D source, DrawTargetTexture2D target)
        {
            if (source == null || target == null)
            {
                throw new ArgumentNullException();
            }
            if (source.SurfaceFormat != target.SurfaceFormat)
            {
                throw new ArgumentException("source.SurfaceFormat != target.SurfaceFormat");
            }
#if XBOX360
            if (source == target && source.Width * source.Height * DrawTarget.FormatSize(source.SurfaceFormat) >
                1000 * 1000 * 10)            //approx 10mb
            {
                throw new ArgumentException("source == target is invalid for larget render targets on Xbox360");
            }
#else
            if (source == target)
            {
                throw new ArgumentException("source == target is invalid on windows");
            }
#endif
            if (source.Width > target.Width ||
                source.Height > target.Height)
            {
                throw new ArgumentException("source is larger than target");
            }

            this.source      = source;
            this.targetClone = target.Clone(false, false, false);

            this.targetClone.ClearBuffer.Enabled = false;

            this.element = new ShaderElement(null, source.Width, source.Height, new Vector2(1, 1), true);
            this.targetClone.Add(element);

            if (target.Width != source.Width ||
                target.Height != source.Height)
            {
                this.targetClone.AddModifier(new Xen.Graphics.Modifier.ScissorModifier(0, 0, Math.Min(1, (source.Width) / target.Width), Math.Min(1, (source.Height) / target.Height)));
                this.element.TextureCrop = new Rectangle(0, 0, Math.Min(this.source.Width, this.targetClone.Width), Math.Min(this.source.Height, this.targetClone.Height));
            }
        }
コード例 #2
0
ファイル: TextureFilter.cs プロジェクト: ARLM-Attic/xna-xen
        /// <summary>
        /// Construct the texture downsampler
        /// </summary>
        /// <param name="source">Source texture to read</param>
        /// <param name="target">Target texture to write to</param>
        /// <param name="intermediate">Intermediate texture (if null, will be created as required)</param>
        /// <param name="intermediate2">Second intermediate texture (if null, will be created as required)</param>
        /// <param name="targetWidth">target width to downsample to</param>
        /// <param name="targetHeight">target height to downsample to</param>
        public TextureDownsample(DrawTargetTexture2D source, DrawTargetTexture2D target, ref DrawTargetTexture2D intermediate, ref DrawTargetTexture2D intermediate2, int targetWidth, int targetHeight)
        {
            if (source == null ||
                target == null)
            {
                throw new ArgumentNullException();
            }

            if (targetWidth <= 0 ||
                targetHeight <= 0)
            {
                throw new ArgumentException("Invalid target size");
            }

            if (DrawTarget.FormatChannels(source.SurfaceFormat) != DrawTarget.FormatChannels(target.SurfaceFormat))
            {
                throw new ArgumentException("source.SurfaceFormat has a different number of channels than target.SurfaceFormat");
            }

            if (targetWidth > target.Width ||
                targetHeight > target.Height)
            {
                throw new ArgumentException("Size is larger than target");
            }

            if (targetWidth > source.Width ||
                targetHeight > source.Height)
            {
                throw new ArgumentException("Size is larger than source");
            }

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

            int w = source.Width;
            int h = source.Height;

            int targetMultipleWidth  = targetWidth;
            int targetMultipleHeight = targetHeight;

            while (targetMultipleWidth * 2 <= w)
            {
                targetMultipleWidth *= 2;
            }
            while (targetMultipleHeight * 2 <= h)
            {
                targetMultipleHeight *= 2;
            }

            DrawTargetTexture2D current = null;
            Rectangle           sRegion = new Rectangle(0, 0, 0, 0);

            //first pass may require that the source is sized down to a multiple of the target size

            if ((double)targetWidth / (double)w <= 0.5 &&
                (double)targetHeight / (double)h <= 0.5 &&
                (targetMultipleWidth != w || targetMultipleHeight != h))
            {
                DrawTargetTexture2D go = this.PickRT(ref intermediate, ref intermediate2, source, targetMultipleWidth, targetMultipleHeight, target.SurfaceFormat);

                Vector2 size = new Vector2((float)targetMultipleWidth, (float)targetMultipleHeight);

                TexturedElement te = new TexturedElement(source, size, false);
                te.TextureCrop = new Rectangle(0, 0, w, h);

                go.Add(te);
                passes.Add(go);
                current = go;
                w       = targetMultipleWidth;
                h       = targetMultipleHeight;
            }

            //downsample on the larger axis, either 2x, 4x or 8x downsampling, until reached the target size

            while (target.Equals(current) == false)
            {
                DrawTargetTexture2D localSource = current ?? source;

                double difW = (double)targetWidth / (double)w;
                double difH = (double)targetHeight / (double)h;

                sRegion.Width  = w;
                sRegion.Height = h;
                sRegion.Y      = localSource.Height - h;

                //both width/height difference are less than 50% smaller, so a linear interpolation will do fine
                if (difW > 0.5 &&
                    difH > 0.5)
                {
                    //write directly to the target
                    DrawTargetTexture2D go      = target.Clone(false, false, false);
                    Vector2             te_size = new Vector2((float)targetWidth, (float)targetHeight);
                    TexturedElement     te      = new TexturedElement(localSource, te_size, false);

                    go.AddModifier(new ScissorModifier(0, go.Height - targetHeight, targetWidth, go.Height, go));
                    te.TextureCrop = sRegion;

                    go.Add(te);
                    passes.Add(go);
                    current = go;

                    continue;
                }

                bool   horizontal = difW < difH;
                double dif        = Math.Min(difW, difH);
                int    size       = horizontal ? w : h;

                Vector2 dir = new Vector2(0, 0);
                if (horizontal)
                {
                    dir.X = 1.0f / localSource.Width;
                }
                else
                {
                    dir.Y = 1.0f / localSource.Height;
                }

                if (dif > 0.25)                 // cutoff for using 2 samples
                {
                    DrawTargetTexture2D go;
                    int new_width  = w;
                    int new_height = h;
                    if (horizontal)
                    {
                        new_width /= 2;
                    }
                    else
                    {
                        new_height /= 2;
                    }

                    if (new_width == targetWidth && new_height == targetHeight)
                    {
                        go = target.Clone(false, false, false);
                    }
                    else
                    {
                        go = PickRT(ref intermediate, ref intermediate2, localSource, new_width, new_height, target.SurfaceFormat);
                    }

                    Vector2       se_size = new Vector2((float)new_width, (float)new_height);
                    ShaderElement se      = new ShaderElement(new Downsample2(), se_size, false);

                    go.AddModifier(new ScissorModifier(0, go.Height - new_height, new_width, go.Height, go));

                    se.TextureCrop = sRegion;

                    go.Add(new Drawer(dir, se, localSource));
                    passes.Add(go);

                    w = new_width;
                    h = new_height;

                    current = go;
                    continue;
                }

                if (dif > 0.125)                 // cutoff for using 4 samples
                {
                    DrawTargetTexture2D go;
                    int new_width  = w;
                    int new_height = h;
                    if (horizontal)
                    {
                        new_width /= 4;
                    }
                    else
                    {
                        new_height /= 4;
                    }

                    if (new_width == targetWidth && new_height == targetHeight)
                    {
                        go = target.Clone(false, false, false);
                    }
                    else
                    {
                        go = PickRT(ref intermediate, ref intermediate2, localSource, new_width, new_height, target.SurfaceFormat);
                    }

                    Vector2       se_size = new Vector2((float)new_width, (float)new_height);
                    ShaderElement se      = new ShaderElement(new Downsample4(), se_size, false);

                    go.AddModifier(new ScissorModifier(0, go.Height - new_height, new_width, go.Height, go));

                    se.TextureCrop = sRegion;

                    go.Add(new Drawer(dir, se, localSource));
                    passes.Add(go);

                    w = new_width;
                    h = new_height;

                    current = go;
                    continue;
                }

                // cutoff for using 8 samples
                {
                    DrawTargetTexture2D go;
                    int new_width  = w;
                    int new_height = h;
                    if (horizontal)
                    {
                        new_width /= 8;
                    }
                    else
                    {
                        new_height /= 8;
                    }

                    if (new_width == targetWidth && new_height == targetHeight)
                    {
                        go = target.Clone(false, false, false);
                    }
                    else
                    {
                        go = PickRT(ref intermediate, ref intermediate2, localSource, new_width, new_height, target.SurfaceFormat);
                    }

                    Vector2       se_size = new Vector2((float)new_width, (float)new_height);
                    ShaderElement se      = new ShaderElement(new Downsample8(), se_size, false);

                    go.AddModifier(new ScissorModifier(0, go.Height - new_height, new_width, go.Height, go));

                    se.TextureCrop = sRegion;

                    go.Add(new Drawer(dir, se, localSource));
                    passes.Add(go);

                    w = new_width;
                    h = new_height;

                    current = go;
                    continue;
                }
            }
        }