5

I'm attempting to change RenderTargets at runtime, so I can draw some elements at runtime, manipulate them and then finally draw the texture to the screen. Problem is, the screen turns purple if I change the RenderTarget at runtime. Here's the code I've got in Draw:

        RenderTarget2D tempTarget = new RenderTarget2D(GraphicsDevice, 128, 128, 1,
            GraphicsDevice.DisplayMode.Format, GraphicsDevice.PresentationParameters.MultiSampleType,
            GraphicsDevice.PresentationParameters.MultiSampleQuality, RenderTargetUsage.PreserveContents);

        GraphicsDevice.SetRenderTarget(0, tempTarget);
        GraphicsDevice.Clear(ClearOptions.Target, Color.SpringGreen, 0, 0);
        GraphicsDevice.SetRenderTarget(0, null);

It doesn't seem to matter how I create the RenderTarget, if I do it at runtime (and I do need to create in-memory textures at runtime and draw on them with SpriteBatch) it results in an entirely purple screen. What can I do to fix this?

jasonh
  • 29,297
  • 11
  • 59
  • 61

3 Answers3

3

It looks like the best option is to create the RenderTarget somewhere other than Draw, draw to it during Update, save the resulting texture (and manipulate as necessary) then draw that texture during Draw.

jasonh
  • 29,297
  • 11
  • 59
  • 61
  • 1
    This was my problem. Do you know the reason it can't be done in the draw method, or why the color is purple though? – Jason Goemaat Dec 30 '10 at 17:27
  • 1
    Thanks to our google overlords for auto-completing "xna rendertarget" with "purple." I separated my `Draw` scene graph call into `PreDraw->Clear->Draw` and draw into the render target during `PreDraw`. [Shawn Hargreaves responded](http://xboxforums.create.msdn.com/forums/t/6264.aspx) that this is to make [render target behavior consistent between windows and XBOX](http://blogs.msdn.com/b/shawnhar/archive/2007/11/21/rendertarget-changes-in-xna-game-studio-2-0.aspx). From that last link, it looks like it _might_ also be possible to use `RenderTargetUsage.PreserveContents` at cost of performance. – cod3monk3y Aug 27 '13 at 00:06
2

I know this is late, but the solution is to write to the RenderTarget BEFORE you clear the screen and beginning drawing your other items.

protected override void Draw(GameTime gameTime)
{
     GraphicsDevice.SetRenderTarget(_renderTarget);

     //...
     //Perform Rendering to the specified target
     //...

     GraphicsDevice.SetRenderTarget(null);

     GraphicsDevice.Clear(Color.CornflowerBlue);

     //...
     //Code that draws to the users screen goes here
     //...
}

This should prevent you from rendering in the Update method as suggested by others, which is counter-intuitive in many aspects.

Michael Aquilina
  • 5,352
  • 4
  • 33
  • 38
  • 2
    I think this answer deserves more attention, and I'd really love to find out why this happens. It seems like tribal knowledge. – Fibericon Sep 07 '13 at 12:05
  • Yeah, I stumbled on to this myself. I don't like it. I want to render to my target inline. :-/ – BrainSlugs83 Apr 27 '14 at 08:19
1

When spritebatch.End() is called objects are written to the backbuffer or in your case to tempTarget. To make the texture,

  • change the target
  • call begin
  • call all of the draws
  • end the spritebatch
  • set target back to null

then use the render2d

TankorSmash
  • 12,186
  • 6
  • 68
  • 106
  • I'm not even using SpriteBatch -- I'm just calling `GraphicsDevice.SetRenderTarget(buffer);` followed by `GraphicsDevice.SetRenderTarget(null);` -- if I do it before anything else in Draw, it works, but if I do it at the end, it all turns purple~ish. I think it has something to do with page flipping being automatic in XNA 4.0. :-/ – BrainSlugs83 Apr 27 '14 at 08:18