Как нарисовать 2D попиксельно в XNA? - PullRequest
7 голосов
/ 29 января 2011

Я пытаюсь рисовать на экране попиксельно, используя XNA, но у меня проблемы с ресурсами.Я думал, что лучшим способом будет иметь 1 текстуру, которая обновляет каждый кадр, но у меня возникают проблемы при обновлении.Вот что у меня получилось, просто в качестве теста:

Texture2D canvas;
Rectangle tracedSize;
UInt32[] pixels;

protected override void Initialize()
    {
        tracedSize = GraphicsDevice.PresentationParameters.Bounds;
        canvas = new Texture2D(GraphicsDevice, tracedSize.Width, tracedSize.Height, false, SurfaceFormat.Color);
        pixels = new UInt32[tracedSize.Width * tracedSize.Height];               

        base.Initialize();
    }

protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        pixels[100] = 0xFF00FF00;
        canvas.SetData<UInt32>(pixels, 0, tracedSize.Width * tracedSize.Height);

        spriteBatch.Begin();
        spriteBatch.Draw(canvas, new Rectangle(0, 0, tracedSize.Width, tracedSize.Height), Color.White);
        spriteBatch.End();

        base.Draw(gameTime);
    }

При повторном вызове Draw () я получаю следующую ошибку:

"Операция была прервана. Вы не можете изменять ресурс, который был установлен на устройстве, или после того, как он был использован в квадратной скобке. "

Если я пытаюсь создать новую Texture2D в Draw (), я быстро получаюОшибка нехватки памяти.Это для Windows Phone.Похоже, я пытаюсь сделать это неправильно, какие еще есть варианты, чтобы заставить его работать?

Ответы [ 2 ]

6 голосов
/ 29 января 2011

Попробуйте установить GraphicsDevice.Textures[0] = null перед вызовом SetData. В зависимости от эффекта, который вам нужен, может быть более эффективный метод, вы также можете рассмотреть Silverlight WriteableBitmap.

Редактировать: это код, который я тестировал в эмуляторе:

Texture2D canvas;
Rectangle tracedSize;
UInt32[] pixels;

protected override void Initialize()
{
    tracedSize = GraphicsDevice.PresentationParameters.Bounds;
    canvas = new Texture2D(GraphicsDevice, tracedSize.Width, tracedSize.Height, false, SurfaceFormat.Color);
    pixels = new UInt32[tracedSize.Width * tracedSize.Height];

    base.Initialize();
}
Random rnd = new Random();
protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    GraphicsDevice.Textures[0] = null;
    pixels[rnd.Next(pixels.Length)] = 0xFF00FF00;
    canvas.SetData<UInt32>(pixels, 0, tracedSize.Width * tracedSize.Height);

    spriteBatch.Begin();
    spriteBatch.Draw(canvas, new Rectangle(0, 0, tracedSize.Width, tracedSize.Height), Color.White);
    spriteBatch.End();

    base.Draw(gameTime);
}
3 голосов
/ 30 января 2011

В основном вам нужно сделать так, как он просит в исключении:

Чтобы гарантировать, что текстура не установлена ​​на графическом устройстве, поставьте в конце Draw:

GraphicsDevice.Textures[0] = null;

Чтобы убедиться, что вы не рисуете внутри кронштейна, вообще не используйте SetData внутри Draw. Переместите вызов на SetData в Update.


Дополнительная информация: Ваша ошибка нехватки памяти связана с тем, что вы не высвобождаете неуправляемые ресурсы, которые выделяет Texture2D (сборщик мусора не может их отслеживать, поэтому он не знает, что у вас недостаточно памяти) ). Вам нужно позвонить Dispose на текстуру. Однако создавать новую текстуру для каждого кадра в любом случае - плохая идея (нет способа избежать проблем с производительностью и фрагментацией памяти, которые она вызывает).

...