XNA noob здесь, учится каждый день. Я только что придумал, как объединить несколько текстур в одну с помощью RenderTarget2D. Однако, хотя я могу использовать RenderTarget2D в качестве Texture2D для большинства целей, есть важное отличие: эти визуализированные текстуры теряются при изменении размера заднего буфера (и, несомненно, при других обстоятельствах, например, при нехватке памяти графическому устройству).
На данный момент я просто копирую готовый RenderTarget2D в новый энергонезависимый Texture2D объект. Однако мой код для этого довольно шаткий. Есть ли более изящный способ сделать это? Возможно, я просто устал, но не могу найти ответ в Google или SO.
Слегка упрощен:
public static Texture2D MergeTextures(int width, int height, IEnumerable<Tuple<Texture2D, Color>> textures)
{
RenderTarget2D buffer = new RenderTarget2D(_device, width, height);
_device.SetRenderTarget(buffer);
_device.Clear(Color.Transparent);
SpriteBatch spriteBatch = new SpriteBatch(_device);
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied);
// Paint each texture over the one before, in the appropriate color
Rectangle rectangle = new Rectangle(0, 0, width, height);
foreach (Tuple<Texture2D, Color> texture in textures)
spriteBatch.Draw(texture.Item1, rectangle, texture.Item2);
spriteBatch.End();
_device.SetRenderTarget((RenderTarget2D)null);
// Write the merged texture to a Texture2D, so we don't lose it when resizing the back buffer
// This is POWERFUL ugly code, and probably terribly, terribly slow
Texture2D mergedTexture = new Texture2D(_device, width, height);
Color[] content = new Color[width * height];
buffer.GetData<Color>(content);
mergedTexture.SetData<Color>(content);
return mergedTexture;
}
Полагаю, мне следует проверить IsContentLost и при необходимости выполнить повторный рендеринг, но это происходит в середине моего основного цикла рисования, и, конечно же, вы не можете вкладывать SpriteBatches. Я мог бы вести список «TODO рендеринга», обрабатывать их после завершения основного SpriteBatch, и тогда они были бы доступны для следующего кадра. Это предпочтительная стратегия?
Этот код вызывается всего несколько раз, поэтому производительность не является проблемой, но я хотел бы узнать, как все делать правильно.