目前正在使用 XNA 和 MonoGame 开发一款游戏,但在尝试渲染背景时遇到了视觉错误,背景应该始终出现在精灵后面。
背景渲染目标偶尔会在精灵顶部闪烁,而它应该始终出现在后面。
当我使用 RenderTarget2D.Dispose() 函数时,我已经将其范围缩小到了一些破坏的范围,因为当我不处理渲染目标时,它工作得很好。
/* <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> */
在代码片段中,行
newPrev.Dispose();
可以移动到任何地方,代码仍然会有问题。只有当我完全忽略它时,代码才不会出现闪烁问题。
它似乎在
newPrev
之上渲染entityRt
中的内容,因为即使不将BackgroundBuffer1渲染到屏幕上,视觉闪烁的故障仍然会弹出。我通过删除线spriteBatch.Draw(BackgroundBuffer1...
来测试这一点
通常,对于这样的效果,您会在程序(或场景)开始时(例如在
Initialize()
中)创建一个 RenderTarget(或一些 RenderTarget 的池)并在每一帧重用它(它们) - 从而避免创建(并处置)每帧一个新的 RenderTarget。
仅当您的分辨率发生变化或 RT 变得不可用时,您才重新创建 RT,并且仅当程序停止或不再需要效果时才将其丢弃。
那么,交换引用也是没有必要的:
(BackgroundBuffer1, newPrev) = (newPrev, BackgroundBuffer1);