Как эффективно клонировать выходные данные после записи в RenderTarget?

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, и тогда они были бы доступны для следующего кадра. Это предпочтительная стратегия?

Этот код вызывается всего несколько раз, поэтому производительность не является проблемой, но я хотел бы узнать, как все делать правильно.

9
задан ROMANIA_engineer 14 December 2017 в 21:13
поделиться