簡體   English   中英

如何在 XNA 中逐像素繪制 2D?

[英]How to draw 2D pixel-by-pixel in XNA?

我正在嘗試使用 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() 時,出現以下錯誤:

“操作已中止。您不能修改已在設備上設置的資源,或在平鋪括號內使用后的資源。”

如果我嘗試在 Draw() 中創建一個新的 Texture2D,我很快就會遇到內存不足的錯誤。 這適用於 Windows Phone。 似乎我正在嘗試以錯誤的方式進行操作,我還需要哪些其他選項才能使其正常工作?

在調用SetData之前,請嘗試設置GraphicsDevice.Textures[0] = null 根據您之后可能有更高效的方法的效果,您還可以考慮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);
}

您基本上需要按照異常中的要求執行操作:

要確保未在圖形設備上設置紋理,請將其放在Draw的末尾:

GraphicsDevice.Textures[0] = null;

為確保您沒有在平鋪括號內Draw ,請不要在Draw中使用SetData 將調用SetData移動到Update


獎勵信息:您的內存不足錯誤是因為您沒有釋放Texture2D分配的非托管資源(垃圾收集器無法跟蹤它們,因此它不知道您的內存不足)。 您需要在紋理上調用Dispose 然而,無論如何在每個幀中創建一個新的紋理是一個壞主意(沒有辦法避免它導致的性能和內存碎片問題)。

永遠不要在Draw() ** 中創建或修改紋理。**

SpriteBatch.Draw() 調用期望 GraphicsDevice 緩沖區包含所有紋理數據(通過擴展到 GPU 緩沖區),此時仍在發生的任何更改(來自 Update 和 IsRunningSlowly == true)將導致渲染時撕裂。

GraphicsDevice.Textures[0] = null;的解決方法GraphicsDevice.Textures[0] = null; 阻塞 Draw 調用和游戲直到傳輸到 GPU 完成,從而減慢整個游戲循環。

重用在類級別聲明的 Texure2D 對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM