xna-4.0

Creating RenderTarget2D on runtime makes my screen flash in purple


i am developing my own XNA tile-based game and i have an issue with RenderTarget2D. I try to draw a background image on the screen and also draw my player on the screen, and it works fine! but when i try to add block textures to the game at runtime using RenderTarget2D, my screen starts to flash in purple. This happens whenever i create a new Chunk of blocks with RenderTarget2D.

Here is some code:

protected override void Draw(GameTime gameTime)
    {
        this.DrawPlayer(gameTime);
        this.DrawWorld(gameTime);

        base.Draw(gameTime);
    }

    private void DrawPlayer(GameTime gameTime)
    {
        GraphicsDevice.SetRenderTarget(Main.PlayerRenderTarget);
        GraphicsDevice.Clear(Color.Transparent);

        this.SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, null, this.Camera.Transform);

        SpriteBatch.Draw(this.Background, new Vector2(this.Screen.X, this.Screen.Y), Color.White);
        this.Player.Draw(SpriteBatch);

        SpriteBatch.End();

        GraphicsDevice.SetRenderTarget(null);
        GraphicsDevice.Clear(Color.Transparent);

        SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
        SpriteBatch.Draw(Main.PlayerRenderTarget, Vector2.Zero, Color.White);
        SpriteBatch.End();
    }

    private void DrawWorld(GameTime gameTime)
    {
        Main.World.Draw(SpriteBatch, this.Screen);
    }

World Draw:

public void Draw(SpriteBatch SpriteBatch, System.Drawing.RectangleF Screen)
    {
        foreach (Chunk CurrentChunk in this.WorldChunks.Where(SomeChunk => SomeChunk.Bounds.IntersectsWith(Screen)))
        {
            CurrentChunk.Draw(SpriteBatch);
        }
    }

Chunk Draw:

public void Draw(SpriteBatch spriteBatch)
{
        if (this.ChunkTexture == null)
        {
            this.CreateChunk(spriteBatch);
        }
        else
        {
            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
            spriteBatch.Draw(this.ChunkTexture, this.ChunkPosition, Color.White);
            spriteBatch.End();
        }
}

    public void CreateChunk(SpriteBatch spriteBatch)
    {
        RenderTarget2D CurrentRenderTarget = new RenderTarget2D(Chunk.GraphicsDevice, (int)this.Bounds.Width, (int)this.Bounds.Height);

        Chunk.GraphicsDevice.SetRenderTarget(CurrentRenderTarget);
        Chunk.GraphicsDevice.Clear(Color.Transparent);

        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);

        foreach(Block in Chunk)
        {
              spriteBatch.Draw(BlockTexture, BlockPosition, Color.White);
        }

        spriteBatch.End();
        Chunk.GraphicsDevice.SetRenderTarget(null);
        Chunk.GraphicsDevice.Clear(Color.Transparent);

        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
        spriteBatch.Draw(CurrentRenderTarget, ChunkPositon, Color.White);
        spriteBatch.End();

        CurrentRenderTarget.GetData<Color>(Chunk.Colors);
        this.Texture = new Texture2D(Chunk.GraphicsDevice, (int)this.Bounds.Width, (int)this.Bounds.Height);
        this.Texture.SetData<Color>(Chunk.Colors);
        this.IsLoaded = true;

        CurrentRenderTarget.Dispose();
    }

Whenever "CreateChunk" is called, the screen flashes for about 0.1 second with purple or black and it draws everything fine after that.
The screen flashes in black when i use Chunk.GraphicsDevice.Clear(Color.Transparent), but when i remove that line, the screen starts flashing in purple.
So i want to make that "flashing" dissapear because it is very disturbing.
Please help me to figure out why that happens.
Thanks, Vlad.

EDIT:
The "flashing" appears to work only on the Background image and the player image, but not the blocks i have drawn.


Solution

  • XNA thinks you are trying to create another backbuffer. It automatically flips backbuffers so that you can draw without disturbing the current display texture, then alternates seamlessly in the background. This eliminates tearing, but causes a lot of confusion for people new to XNA (I struggled with this myself for a while).

    Whenever CreateChunk is being called, you are creating a new RenderTarget2D which is going out of scope at the end of the function. While RenderTarget2D.Dispose() supposedly disposes all resources allocated to the texture, from my experience it does not decrement the internal count of RenderTargets in GraphicsDevice. Before your CreateChunk ends, insert a breakpoint and Call GraphicsDevice.GetRenderTarget(1); and check if this is null.

    Tip: When you hit that breakpoint, check the non-public members of GraphicsDevice. You will see how many RenderTargets the device is using and tons of useful debugging information.

    Hopefully this helps you target your investigation.