diff --git a/OpenRA.Game/Graphics/WorldRenderer.cs b/OpenRA.Game/Graphics/WorldRenderer.cs index 85b95ee9d554..08cdcb408dc2 100644 --- a/OpenRA.Game/Graphics/WorldRenderer.cs +++ b/OpenRA.Game/Graphics/WorldRenderer.cs @@ -46,7 +46,6 @@ public sealed class WorldRenderer : IDisposable readonly List renderablesBuffer = new(); readonly IRenderer[] renderers; readonly IRenderPostProcessPass[] postProcessPasses; - readonly ITexture postProcessTexture; internal WorldRenderer(ModData modData, World world) { @@ -75,8 +74,6 @@ internal WorldRenderer(ModData modData, World world) debugVis = Exts.Lazy(() => world.WorldActor.TraitOrDefault()); postProcessPasses = world.WorldActor.TraitsImplementing().ToArray(); - if (postProcessPasses.Length > 0) - postProcessTexture = Game.Renderer.Context.CreateTexture(); } public void BeginFrame() @@ -323,18 +320,13 @@ public void Draw() void ApplyPostProcessing(PostProcessPassType type) { - var size = Game.Renderer.WorldFrameBufferSize; - var rect = new Rectangle(0, 0, size.Width, size.Height); foreach (var pass in postProcessPasses) { if (pass.Type != type || !pass.Enabled) continue; - // Make a copy of the world texture to avoid reading and writing on the same buffer Game.Renderer.Flush(); - postProcessTexture.SetDataFromReadBuffer(rect); - Game.Renderer.Flush(); - pass.Draw(this, postProcessTexture); + pass.Draw(this); } } diff --git a/OpenRA.Game/Renderer.cs b/OpenRA.Game/Renderer.cs index b737cd93416a..dbb85c53e9f3 100644 --- a/OpenRA.Game/Renderer.cs +++ b/OpenRA.Game/Renderer.cs @@ -47,6 +47,7 @@ enum RenderType { None, World, UI } readonly IVertexBuffer tempVertexBuffer; readonly IIndexBuffer quadIndexBuffer; readonly Stack scissorState = new(); + readonly ITexture worldBufferSnapshot; IFrameBuffer screenBuffer; Sprite screenSprite; @@ -60,6 +61,15 @@ enum RenderType { None, World, UI } public Size WorldFrameBufferSize => worldSheet.Size; public int WorldDownscaleFactor { get; private set; } = 1; + /// + /// Copies and returns the currently rendered world state as a temporary texture. + /// + public ITexture WorldBufferSnapshot() + { + worldBufferSnapshot.SetDataFromReadBuffer(new Rectangle(int2.Zero, worldSheet.Size)); + return worldBufferSnapshot; + } + SheetBuilder fontSheetBuilder; readonly IPlatform platform; @@ -98,6 +108,7 @@ public Renderer(IPlatform platform, GraphicSettings graphicSettings) tempVertexBuffer = Context.CreateVertexBuffer(TempVertexBufferSize); quadIndexBuffer = Context.CreateIndexBuffer(Util.CreateQuadIndices(TempIndexBufferSize / 6)); + worldBufferSnapshot = Context.CreateTexture(); } static Size GetResolution(GraphicSettings graphicsSettings) @@ -525,6 +536,7 @@ public void Dispose() { worldBuffer.Dispose(); screenBuffer.Dispose(); + worldBufferSnapshot.Dispose(); tempVertexBuffer.Dispose(); quadIndexBuffer.Dispose(); fontSheetBuilder?.Dispose(); diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 25509261b1f5..42dfe37fc508 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -467,7 +467,7 @@ public interface IRenderPostProcessPass { PostProcessPassType Type { get; } bool Enabled { get; } - void Draw(WorldRenderer wr, ITexture worldTexture); + void Draw(WorldRenderer wr); } [Flags] diff --git a/OpenRA.Mods.Cnc/Traits/World/ChronoVortexRenderer.cs b/OpenRA.Mods.Cnc/Traits/World/ChronoVortexRenderer.cs index b62f711456f8..e0ed8b4b6535 100644 --- a/OpenRA.Mods.Cnc/Traits/World/ChronoVortexRenderer.cs +++ b/OpenRA.Mods.Cnc/Traits/World/ChronoVortexRenderer.cs @@ -84,7 +84,7 @@ public void DrawVortex(float3 pos, int frame) PostProcessPassType IRenderPostProcessPass.Type => PostProcessPassType.AfterWorld; bool IRenderPostProcessPass.Enabled => vortices.Count > 0; - void IRenderPostProcessPass.Draw(WorldRenderer wr, ITexture worldTexture) + void IRenderPostProcessPass.Draw(WorldRenderer wr) { var scroll = wr.Viewport.TopLeft; var size = renderer.WorldFrameBufferSize; @@ -94,7 +94,7 @@ void IRenderPostProcessPass.Draw(WorldRenderer wr, ITexture worldTexture) shader.SetVec("Scroll", scroll.X, scroll.Y); shader.SetVec("p1", width, height); shader.SetVec("p2", -1, -1); - shader.SetTexture("WorldTexture", worldTexture); + shader.SetTexture("WorldTexture", Game.Renderer.WorldBufferSnapshot()); shader.SetTexture("VortexTexture", vortexSheet.GetTexture()); shader.PrepareRender(); foreach (var (pos, frame) in vortices) diff --git a/OpenRA.Mods.Common/Traits/World/RenderPostProcessPassBase.cs b/OpenRA.Mods.Common/Traits/World/RenderPostProcessPassBase.cs index 2658694e44d2..558a6db3e0c1 100644 --- a/OpenRA.Mods.Common/Traits/World/RenderPostProcessPassBase.cs +++ b/OpenRA.Mods.Common/Traits/World/RenderPostProcessPassBase.cs @@ -42,9 +42,9 @@ protected RenderPostProcessPassBase(string name, PostProcessPassType type) PostProcessPassType IRenderPostProcessPass.Type => type; bool IRenderPostProcessPass.Enabled => Enabled; - void IRenderPostProcessPass.Draw(WorldRenderer wr, ITexture worldTexture) + void IRenderPostProcessPass.Draw(WorldRenderer wr) { - shader.SetTexture("WorldTexture", worldTexture); + shader.SetTexture("WorldTexture", Game.Renderer.WorldBufferSnapshot()); PrepareRender(wr, shader); shader.PrepareRender(); renderer.DrawBatch(buffer, shader, 0, 6, PrimitiveType.TriangleList);