Drawing sprites to a permanent Texture2d using Monogame / XNA

I'm working with Monogame to do a 2d sprite engine. I've gotten it work pretty well where I can move lots of sprites around the screen with the effects and positions that I want.

Last night I tried to add a feature and I can't quite get it to work right.
I'm trying to create permanent trails that the moving sprites can leave behind. So I have a mostly transparent PNG with some white lines on it called "streak". The idea is that I set up a new Texture2d surface (called streakoverlay) and I draw the streaks on to it.

I switch back to the back buffer and draw: The background, the streakoverlay, and finally the sprite on top of it. The streaks should build up over time. It almost works, but the trouble I have is that streakOverlay seems to clear itself every time. How I'd like it to behave would be the same behaviour as having the graphics display without this line "GraphicsDevice.Clear(Color.White);" - everything would just pile up in it.

Instead it resets back to the Purple transparent color that is the default for that texture. Any suggestions? Here's the core piece of the rendering engine:

GraphicsDeviceManager graphics;
RenderTarget2D streakOverlay;
SpriteBatch spriteBatch;

private Texture2D bkg;
private Texture2D prototype;
private Texture2D streak;

//Initialize
graphics = new GraphicsDeviceManager(this);
GraphicsDevice.Clear(Color.Transparent);
streakOverlay = new RenderTarget2D(GraphicsDevice, 200,200);

prototype = Content.Load<Texture2D>("prototype"); //Prototype sprite that moves around
streak = Content.Load<Texture2D>("blueStreak"); //Trails being left by Prototype sprite

graphics.GraphicsDevice.SetRenderTarget(streakOverlay);
GraphicsDevice.Clear(Color.Transparent); //Attempt to make the streakoverlay is fully transparent.
graphics.GraphicsDevice.SetRenderTarget(null);

//Draw
Random r = new Random();
graphics.GraphicsDevice.SetRenderTarget(streakOverlay); //Switch to drawing to the streakoverlay

spriteBatch.Begin();
//Draw some streaks that should accumulate
spriteBatch.Draw(streak, new Vector2(r.Next(0, 200), r.Next(0, 200)), null, Color.White, 0f, new Vector2(25, 25), 1f, SpriteEffects.None, 1f);
spriteBatch.End();

//Switch back to drawing on the back buffer.
graphics.GraphicsDevice.SetRenderTarget(null);

spriteBatch.Begin();
spriteBatch.Draw(bkg, new Rectangle(0, 0, 2000, 2000), Color.White);    //Draw our background
spriteBatch.Draw(streakOverlay, new Vector2(0, 0), Color.White); //Put the overlay on top of it
spriteBatch.Draw(prototype, new Vector2(_spritePrototype.getX, _spritePrototype.getY), null, Color.White, DegreeToRadian(rotationSprite), new Vector2(25, 25), .5f, SpriteEffects.None, 0f); //Draw the sprite that's moving around.
spriteBatch.End();

base.Draw(gameTime);

• I'm not sure, but I suspect one of the calls to the sprite batch (Begin or End) have a parameter you can use to specify "don't clear everything." Nov 22, 2013 at 18:10
• Looks like there is: spriteBatch.Begin(SpriteSortMode.Texture, BlendState.Additive); This blends things better, but the texture is still getting wiped every turn. Nov 22, 2013 at 18:56

In XNA, setting a render target (including the backbuffer) onto a device will, by default, clear that render target to the "uninitialized surface" purple colour.

To avoid this, set the RenderTargetUsage of your render target to PreserveContents when constructing it.

DiscardContents is the default for performance reasons: On mobile systems and on the Xbox 360, retaining the contents of a render target is an expensive operation. This default is used on all platforms to aid portability.

I am not sure whether MonoGame's implementation matches this behaviour exactly.

An alternative approach would be to "bounce" the texture between two render targets, alternating which is rendered to on each frame. (This can also allow you to do effects like fading out the existing streaks.)

• This is exactly what I needed, thank you. I also like the idea of using a duplicate texture for fading. I'll implement that. Nov 26, 2013 at 15:11