diff --git a/OpenRA.FileFormats/Graphics/IGraphicsDevice.cs b/OpenRA.FileFormats/Graphics/IGraphicsDevice.cs index a59f8042bd..564a143825 100755 --- a/OpenRA.FileFormats/Graphics/IGraphicsDevice.cs +++ b/OpenRA.FileFormats/Graphics/IGraphicsDevice.cs @@ -32,6 +32,8 @@ namespace OpenRA.FileFormats.Graphics IGraphicsDevice Create( Size size, WindowMode windowMode ); } + public enum BlendMode { None, Alpha, Additive } + public interface IGraphicsDevice { IVertexBuffer CreateVertexBuffer( int length ); @@ -55,8 +57,7 @@ namespace OpenRA.FileFormats.Graphics void EnableDepthBuffer(); void DisableDepthBuffer(); - void EnableAlphaBlending(); - void DisableAlphaBlending(); + void SetBlendMode(BlendMode mode); } public interface IVertexBuffer diff --git a/OpenRA.Game/Graphics/LineRenderer.cs b/OpenRA.Game/Graphics/LineRenderer.cs index d2d07e39a0..d5533e2e3b 100644 --- a/OpenRA.Game/Graphics/LineRenderer.cs +++ b/OpenRA.Game/Graphics/LineRenderer.cs @@ -34,7 +34,7 @@ namespace OpenRA.Graphics { if (nv > 0) { - renderer.Device.EnableAlphaBlending(); + renderer.Device.SetBlendMode(BlendMode.Alpha); shader.Render(() => { var vb = renderer.GetTempVertexBuffer(); @@ -42,7 +42,7 @@ namespace OpenRA.Graphics renderer.SetLineWidth(LineWidth * Game.viewport.Zoom); renderer.DrawBatch(vb, 0, nv, PrimitiveType.LineList); }); - renderer.Device.DisableAlphaBlending(); + renderer.Device.SetBlendMode(BlendMode.None); nv = 0; } } diff --git a/OpenRA.Game/Graphics/QuadRenderer.cs b/OpenRA.Game/Graphics/QuadRenderer.cs index bce702c982..970c66a1ce 100644 --- a/OpenRA.Game/Graphics/QuadRenderer.cs +++ b/OpenRA.Game/Graphics/QuadRenderer.cs @@ -31,14 +31,14 @@ namespace OpenRA.Graphics { if (nv > 0) { - renderer.Device.EnableAlphaBlending(); + renderer.Device.SetBlendMode(BlendMode.Alpha); shader.Render(() => { var vb = renderer.GetTempVertexBuffer(); vb.SetData(vertices, nv); renderer.DrawBatch(vb, 0, nv, PrimitiveType.QuadList); }); - renderer.Device.DisableAlphaBlending(); + renderer.Device.SetBlendMode(BlendMode.None); nv = 0; } diff --git a/OpenRA.Game/Graphics/Sequence.cs b/OpenRA.Game/Graphics/Sequence.cs index 56176750a7..005c63f2dc 100644 --- a/OpenRA.Game/Graphics/Sequence.cs +++ b/OpenRA.Game/Graphics/Sequence.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; using OpenRA.FileFormats; +using OpenRA.FileFormats.Graphics; namespace OpenRA.Graphics { @@ -36,16 +37,20 @@ namespace OpenRA.Graphics Name = name; var d = info.NodesDict; var offset = float2.Zero; + var blendMode = BlendMode.Alpha; Start = int.Parse(d["Start"].Value); if (d.ContainsKey("Offset")) offset = FieldLoader.GetValue("Offset", d["Offset"].Value); + if (d.ContainsKey("BlendMode")) + blendMode = FieldLoader.GetValue("BlendMode", d["BlendMode"].Value); + // Apply offset to each sprite in the sequence // Different sequences may apply different offsets to the same frame sprites = Game.modData.SpriteLoader.LoadAllSprites(srcOverride ?? unit).Select( - s => new Sprite(s.sheet, s.bounds, s.offset + offset, s.channel)).ToArray(); + s => new Sprite(s.sheet, s.bounds, s.offset + offset, s.channel, blendMode)).ToArray(); if (!d.ContainsKey("Length")) Length = 1; diff --git a/OpenRA.Game/Graphics/SheetBuilder.cs b/OpenRA.Game/Graphics/SheetBuilder.cs index 915660a7eb..75183a8e9a 100644 --- a/OpenRA.Game/Graphics/SheetBuilder.cs +++ b/OpenRA.Game/Graphics/SheetBuilder.cs @@ -10,6 +10,7 @@ using System; using System.Drawing; +using OpenRA.FileFormats.Graphics; namespace OpenRA.Graphics { @@ -105,7 +106,7 @@ namespace OpenRA.Graphics p = new Point(0,0); } - var rect = new Sprite(current, new Rectangle(p, imageSize), spriteOffset, channel); + var rect = new Sprite(current, new Rectangle(p, imageSize), spriteOffset, channel, BlendMode.Alpha); p.X += imageSize.Width; return rect; diff --git a/OpenRA.Game/Graphics/Sprite.cs b/OpenRA.Game/Graphics/Sprite.cs index 7296bbb25c..290524ec29 100644 --- a/OpenRA.Game/Graphics/Sprite.cs +++ b/OpenRA.Game/Graphics/Sprite.cs @@ -9,6 +9,7 @@ #endregion using System.Drawing; +using OpenRA.FileFormats.Graphics; namespace OpenRA.Graphics { @@ -16,21 +17,26 @@ namespace OpenRA.Graphics { public readonly Rectangle bounds; public readonly Sheet sheet; + public readonly BlendMode blendMode; public readonly TextureChannel channel; public readonly float2 size; public readonly float2 offset; readonly float2[] textureCoords; public Sprite(Sheet sheet, Rectangle bounds, TextureChannel channel) - : this(sheet, bounds, float2.Zero, channel) {} + : this(sheet, bounds, float2.Zero, channel, BlendMode.Alpha) {} - public Sprite(Sheet sheet, Rectangle bounds, float2 offset, TextureChannel channel) + public Sprite(Sheet sheet, Rectangle bounds, TextureChannel channel, BlendMode blendMode) + : this(sheet, bounds, float2.Zero, channel, blendMode) {} + + public Sprite(Sheet sheet, Rectangle bounds, float2 offset, TextureChannel channel, BlendMode blendMode) { this.sheet = sheet; this.bounds = bounds; this.offset = offset; this.channel = channel; this.size = new float2(bounds.Size); + this.blendMode = blendMode; var left = (float)(bounds.Left) / sheet.Size.Width; var top = (float)(bounds.Top) / sheet.Size.Height; diff --git a/OpenRA.Game/Graphics/SpriteRenderer.cs b/OpenRA.Game/Graphics/SpriteRenderer.cs index b8d144bc1a..62d8c6a82a 100644 --- a/OpenRA.Game/Graphics/SpriteRenderer.cs +++ b/OpenRA.Game/Graphics/SpriteRenderer.cs @@ -20,6 +20,7 @@ namespace OpenRA.Graphics Vertex[] vertices = new Vertex[Renderer.TempBufferSize]; Sheet currentSheet = null; + BlendMode currentBlend = BlendMode.Alpha; int nv = 0; public SpriteRenderer(Renderer renderer, IShader shader) @@ -33,14 +34,15 @@ namespace OpenRA.Graphics if (nv > 0) { shader.SetTexture("DiffuseTexture", currentSheet.Texture); - renderer.Device.EnableAlphaBlending(); + + renderer.Device.SetBlendMode(currentBlend); shader.Render(() => { var vb = renderer.GetTempVertexBuffer(); vb.SetData(vertices, nv); renderer.DrawBatch(vb, 0, nv, PrimitiveType.QuadList); }); - renderer.Device.DisableAlphaBlending(); + renderer.Device.SetBlendMode(BlendMode.None); nv = 0; currentSheet = null; @@ -64,9 +66,13 @@ namespace OpenRA.Graphics if (s.sheet != currentSheet) Flush(); + if (s.blendMode != currentBlend) + Flush(); + if (nv + 4 > Renderer.TempBufferSize) Flush(); + currentBlend = s.blendMode; currentSheet = s.sheet; Util.FastCreateQuad(vertices, location + s.offset, s, paletteIndex, nv, size); nv += 4; @@ -90,10 +96,14 @@ namespace OpenRA.Graphics if (s.sheet != currentSheet) Flush(); + if (s.blendMode != currentBlend) + Flush(); + if (nv + 4 > Renderer.TempBufferSize) Flush(); currentSheet = s.sheet; + currentBlend = s.blendMode; Util.FastCreateQuad(vertices, a, b, c, d, s, 0, nv); nv += 4; } @@ -101,9 +111,9 @@ namespace OpenRA.Graphics public void DrawVertexBuffer(IVertexBuffer buffer, int start, int length, PrimitiveType type, Sheet sheet) { shader.SetTexture("DiffuseTexture", sheet.Texture); - renderer.Device.EnableAlphaBlending(); + renderer.Device.SetBlendMode(BlendMode.Alpha); shader.Render(() => renderer.DrawBatch(buffer, start, length, type)); - renderer.Device.DisableAlphaBlending(); + renderer.Device.SetBlendMode(BlendMode.None); } public void SetPalette(ITexture palette) diff --git a/OpenRA.Renderer.Null/NullGraphicsDevice.cs b/OpenRA.Renderer.Null/NullGraphicsDevice.cs index e136c77734..e58e5c10f1 100644 --- a/OpenRA.Renderer.Null/NullGraphicsDevice.cs +++ b/OpenRA.Renderer.Null/NullGraphicsDevice.cs @@ -41,8 +41,7 @@ namespace OpenRA.Renderer.Null public void EnableDepthBuffer() { } public void DisableDepthBuffer() { } - public void EnableAlphaBlending() { } - public void DisableAlphaBlending() { } + public void SetBlendMode(BlendMode mode) { } public void Clear() { } public void Present() { } diff --git a/OpenRA.Renderer.SdlCommon/SdlGraphics.cs b/OpenRA.Renderer.SdlCommon/SdlGraphics.cs index cb39a890d6..4a48be0f5f 100644 --- a/OpenRA.Renderer.SdlCommon/SdlGraphics.cs +++ b/OpenRA.Renderer.SdlCommon/SdlGraphics.cs @@ -147,17 +147,24 @@ namespace OpenRA.Renderer.SdlCommon ErrorHandler.CheckGlError(); } - public void EnableAlphaBlending() + public void SetBlendMode(BlendMode mode) { - Gl.glEnable(Gl.GL_BLEND); - ErrorHandler.CheckGlError(); - Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA); - ErrorHandler.CheckGlError(); - } - - public void DisableAlphaBlending() - { - Gl.glDisable(Gl.GL_BLEND); + switch (mode) + { + case BlendMode.None: + Gl.glDisable(Gl.GL_BLEND); + break; + case BlendMode.Alpha: + Gl.glEnable(Gl.GL_BLEND); + ErrorHandler.CheckGlError(); + Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA); + break; + case BlendMode.Additive: + Gl.glEnable(Gl.GL_BLEND); + ErrorHandler.CheckGlError(); + Gl.glBlendFunc(Gl.GL_ONE, Gl.GL_ONE); + break; + } ErrorHandler.CheckGlError(); }