I am writing an application in XNA that relies on render targets that are rendered to just once, and then used indefinitely afterwards. The problem I've encountered is that there are certain situations where the render targets' contents are lost or disposed, such when the computer goes to sleep or the application enters full-screen mode.
Re-rendering to each target when content is lost is an option, but likely not the best option, as it could be fairly costly when there are many targets.
I could probably save each result as a PNG image and then load that PNG back up as a texture, but that adds a lot of I/O overhead.
Suggestions?
Most likely option I've found so far is to use GetData()
and SetData()
to copy from the RenderTarget2D
to a new Texture2D.
Since I want a mip mapped texture, I found that I had to copy each mip level individually to the new texture, like so. If you don't do this, the object will turn black as you move away from it since there's no data in the mip maps. Note that the render target must also be mip mapped.
Texture2D copy = new Texture2D(graphicsDevice,
renderTarget.Width, renderTarget.Height, true,
renderTarget.Format);
// Set data for each mip map level
for (int i = 0; i < renderTarget.LevelCount; i++)
{
// calculate the dimensions of the mip level.
// Math.Max because dimensions always non-zero
int width = (int)Math.Max((renderTarget.Width / Math.Pow(2, i)), 1);
int height = (int)Math.Max((renderTarget.Height / Math.Pow(2, i)), 1);
Color[] data = new Color[width * height];
renderTarget.GetData<Color>(i, null, data, 0, data.Length);
copy.SetData<Color>(i, null, data, 0, data.Length);
}