简体   繁体   中英

Smooth fadeout/transition between 2 textures in XNA WP7

I have 2 textures 800x480 (foreground/backgound) which are .png files in XNA Windows Phone 7 application. I want to fadeout/transision foreground to reveal background. I have huge problem with performance. My idea is only to maipulate Alpha channel in one Texture2D so i created such a code:

GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;

private Texture2D _background, _foreground;
private BlendState _blendState;
private uint[] _pixelsForeground;
private uint[] _pixelsBackground;

public Game1()
{
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";

    TargetElapsedTime = TimeSpan.FromTicks(333333);

    graphics.IsFullScreen = true;
    graphics.SupportedOrientations = DisplayOrientation.Portrait;
    graphics.PreferredBackBufferHeight = 840;
    graphics.PreferredBackBufferWidth = 480;
}

protected override void LoadContent()
{
    spriteBatch = new SpriteBatch(GraphicsDevice);

    _background = this.Content.Load<Texture2D>(@"background");
    _foreground = this.Content.Load<Texture2D>(@"foreground");

    _pixelsForeground = new uint[_foreground.Width * _foreground.Height];
    _pixelsBackground = new uint[_foreground.Width * _foreground.Height];

    _background.GetData(_pixelsBackground);
    _foreground.GetData(_pixelsForeground);

    _blendState = new BlendState
    {
        AlphaBlendFunction = BlendFunction.Add,
        ColorBlendFunction = BlendFunction.Add,
        AlphaSourceBlend = Blend.SourceAlpha,
        ColorSourceBlend = Blend.SourceAlpha,
        AlphaDestinationBlend = Blend.InverseSourceAlpha,
        ColorDestinationBlend = Blend.InverseSourceAlpha
    };
}

protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
        this.Exit();

    this.GraphicsDevice.Textures[0] = null;

    for (int x = 0; x < _foreground.Width; x++)
    {
        for (int y = 0; y < _foreground.Height; y++)
        {
            uint pixelCanvas = _pixelsForeground[y * _foreground.Width + x];
            uint newPixelCanvas = pixelCanvas - 0x05000000;
            _pixelsForeground[y*_foreground.Width + x] = newPixelCanvas;
            _pixelsForeground[y * _foreground.Width + x] = (newPixelCanvas & 0xFF000000) > (pixelCanvas & 0xFF000000)
                                                                                ? pixelCanvas & 0x00FFFFFF
                                                                                : newPixelCanvas;
        }
    }

    Rectangle rect = new Rectangle(0, 0, _foreground.Width, _foreground.Height);
    _foreground.SetData<uint>(0, rect, _pixelsForeground, 0, _foreground.Height * _foreground.Width);

    base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    spriteBatch.Begin(SpriteSortMode.FrontToBack, _blendState);
    spriteBatch.Draw(_foreground, Vector2.One, null, Color.White);
    spriteBatch.Draw(_background, Vector2.One, null, Color.White);
    spriteBatch.End();

    base.Draw(gameTime);
}

Problem is that it generates poor performance because of:

_foreground.SetData<uint>(...)

What technique I can use to manage this better?
I'd rather need that manipulation of Alpha channel for other purposes. Keep in mind that foreground pixels can have different alpha channel already on start something like transparent spots.

This is definitely the wrong way to approach this. What you want to do is pass a Color to the sprite batch's Draw method that has the appropriate alpha channel.

int alpha = 150;
spriteBatch.Draw(tex, pos, new Color(255,255,255,alpha));

That way, the GPU handles the alpha blending on your behalf, and your performance issues dissapear :-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM