Currently working on a game using XNA with MonoGame but have run into a visual error while trying to render the background where it'll appear above sprites when it should always appear behind.
The background render target will occasionally flicker on top of the sprites when it should always appear behind.
I've narrowed it down to something breaking when I use the RenderTarget2D.Dispose() function because when I don't dispose my render targets, it works just fine.
/* <DRAW ENTITIES> */
spriteBatch.GraphicsDevice.SetRenderTarget(entityRt);
spriteBatch.GraphicsDevice.Clear(Color.Transparent);
spriteBatch.Begin(SpriteSortMode.BackToFront, samplerState: SamplerState.PointClamp);
for (int i = 0; i < entities.Count; i++)
entities[i].Draw();
spriteBatch.End();
spriteBatch.GraphicsDevice.SetRenderTarget(null);
/* </DRAW ENTITIES> */
/* <HANDLE BACKGROUND EFFECT> */
MouseState mouseState = Mouse.GetState();
Point mousePos = mouseState.Position;
RenderTarget2D newPrev = new RenderTarget2D(spriteBatch.GraphicsDevice, BackgroundBuffer1.Width, BackgroundBuffer1.Height);
spriteBatch.GraphicsDevice.SetRenderTarget(newPrev);
spriteBatch.GraphicsDevice.Clear(Color.Transparent);
spriteBatch.Begin();
spriteBatch.Draw(BackgroundBuffer1,
new Rectangle(0, 0, BackgroundBuffer1.Width, BackgroundBuffer1.Height),
Color.White);
spriteBatch.Draw(DrawUtils.createTexture(spriteBatch.GraphicsDevice),
new Vector2((int)(mousePos.X * PixelateMultiplier), (int)(mousePos.Y * PixelateMultiplier)),
Color.White);
spriteBatch.End();
spriteBatch.GraphicsDevice.SetRenderTarget(null);
(BackgroundBuffer1, newPrev) = (newPrev, BackgroundBuffer1);
newPrev.Dispose(); //<<==== PROBLEM LINE
/* </HANDLE BACKGROUND EFFECT> */
/* <DRAW TO SCREEN> */
spriteBatch.GraphicsDevice.SetRenderTarget(null);
spriteBatch.GraphicsDevice.Clear(Color.Transparent);
spriteBatch.Begin(samplerState: SamplerState.PointClamp, effect: CRTShader, sortMode: SpriteSortMode.Immediate);
spriteBatch.Draw(BackgroundBuffer1, //<<== Can be deleted and will still have a problem
new Rectangle(0, 0, Globals.Camera.Width, Globals.Camera.Height),
Color.White);
spriteBatch.Draw(entityRt,
new Rectangle(0, 0, Globals.Camera.Width, Globals.Camera.Height),
Color.White);
spriteBatch.End();
/* <DRAW TO SCREEN> */
In the code snippet the line newPrev.Dispose(); can be moved anywhere and the code will still have a problem. It's only when I omit it entirely that the code doesn't have the flickering problem.
It appears to be rendering things in newPrev on top of entityRt because even when not rendering the BackgroundBuffer1 to the screen, the visual flickering glitch still pops up. I tested this by removing the line spriteBatch.Draw(BackgroundBuffer1...
Usually, for such an effect, you would create one RenderTarget (or a pool of some RenderTargets) at start (e.g. in
Initialize()) of the program (or scene) and reuse it (them) every frame - thus avoiding creating (and disposing) a new RenderTarget every frame.You only recreate the RT when your resolution changes or when it becomes otherwise unusable and you'd dispose it only when the program stops or the effect is no longer needed.
Then, swapping of references is also not necessary: