diff --git a/OpenRa.Game/Chrome.cs b/OpenRa.Game/Chrome.cs new file mode 100644 index 0000000000..fc410d316b --- /dev/null +++ b/OpenRa.Game/Chrome.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using OpenRa.Game.Graphics; +using OpenRa.Game.Support; +using System.Drawing; + +namespace OpenRa.Game +{ + class Chrome + { + readonly Renderer renderer; + readonly Sheet specialBin; + readonly SpriteRenderer spriteRenderer; + readonly Sprite specialBinSprite; + readonly Sprite moneyBinSprite; + + public Chrome(Renderer r) + { + this.renderer = r; + specialBin = new Sheet(renderer, "specialbin.png"); + spriteRenderer = new SpriteRenderer(renderer, true, renderer.RgbaSpriteShader); + specialBinSprite = new Sprite(specialBin, new Rectangle(0, 0, 64, 256), TextureChannel.Alpha); + moneyBinSprite = new Sprite(specialBin, new Rectangle(128, 0, 384, 64), TextureChannel.Alpha); + } + + public void Draw() + { + renderer.Device.DisableScissor(); + renderer.DrawText(string.Format("RenderFrame {0} ({2:F1} ms)\nTick {1} ({3:F1} ms)\n$ {4}\nPower {5}", + Game.RenderFrame, + Game.orderManager.FrameNumber, + PerfHistory.items["render"].LastValue, + PerfHistory.items["tick_time"].LastValue, + Game.LocalPlayer.Cash, + Game.LocalPlayer.GetTotalPower() + ), new int2(140, 5), Color.White); + + PerfHistory.Render(renderer, Game.worldRenderer.lineRenderer); + + spriteRenderer.DrawSprite(specialBinSprite, float2.Zero, 0); + spriteRenderer.DrawSprite(moneyBinSprite, new float2( Game.viewport.Width - 384, 0 ), 0); + spriteRenderer.Flush(); + } + } +} diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index 4ddd12fec6..d707cb907c 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -24,6 +24,7 @@ namespace OpenRa.Game public static PathFinder PathFinder; public static WorldRenderer worldRenderer; public static Controller controller; + public static Chrome chrome; public static OrderManager orderManager; @@ -86,6 +87,8 @@ namespace OpenRa.Game skipMakeAnims = false; PerfHistory.items["render"].hasNormalTick = false; + + chrome = new Chrome(renderer); } static void LoadMapBuildings( IniFile mapfile ) @@ -174,7 +177,6 @@ namespace OpenRa.Game using (new PerfSample("render")) { - ++RenderFrame; viewport.cursor = controller.ChooseCursor(); viewport.DrawRegions(); diff --git a/OpenRa.Game/Graphics/Renderer.cs b/OpenRa.Game/Graphics/Renderer.cs index 9b36128a72..87145b4eb8 100644 --- a/OpenRa.Game/Graphics/Renderer.cs +++ b/OpenRa.Game/Graphics/Renderer.cs @@ -10,8 +10,9 @@ namespace OpenRa.Game.Graphics { readonly GraphicsDevice device; Texture[] palettes; - public Shader SpriteShader { get; private set; } /* note: shared shader params */ - public Shader LineShader { get; private set; } + public Shader SpriteShader { get; private set; } /* note: shared shader params */ + public Shader LineShader { get; private set; } + public Shader RgbaSpriteShader { get; private set; } readonly SpriteHelper sh; readonly FontHelper fhDebug; @@ -29,31 +30,34 @@ namespace OpenRa.Game.Graphics public Renderer(Control host, Size resolution, bool windowed) { host.ClientSize = resolution; - device = GraphicsDevice.Create(host, + device = GraphicsDevice.Create(host, resolution.Width, resolution.Height, windowed, false); SpriteShader = new Shader(device, FileSystem.Open("sprite.fx")); SpriteShader.Quality = ShaderQuality.Low; - LineShader = new Shader(device, FileSystem.Open("line.fx")); - LineShader.Quality = ShaderQuality.High; + LineShader = new Shader(device, FileSystem.Open("line.fx")); + LineShader.Quality = ShaderQuality.High; + RgbaSpriteShader = new Shader(device, FileSystem.Open("rgbasprite.fx")); + RgbaSpriteShader.Quality = ShaderQuality.High; - sh = new SpriteHelper(device ); - fhDebug = new FontHelper(device, "Tahoma", 10, false ); + sh = new SpriteHelper(device); + fhDebug = new FontHelper(device, "Tahoma", 10, false); } public GraphicsDevice Device { get { return device; } } public static float waterFrame = 0.0f; - public void BeginFrame( float2 r1, float2 r2, float2 scroll ) + public void BeginFrame(float2 r1, float2 r2, float2 scroll) { device.Begin(); + device.Clear(0, Surfaces.Color); - SpriteShader.SetValue("Palette", palettes[ (int)(waterFrame * palettes.Length) % palettes.Length ]); + SpriteShader.SetValue("Palette", palettes[(int)(waterFrame * palettes.Length) % palettes.Length]); SpriteShader.SetValue("Scroll", scroll); SpriteShader.SetValue("r1", r1); SpriteShader.SetValue("r2", r2); - SpriteShader.Commit(); + SpriteShader.Commit(); } public void EndFrame() @@ -63,7 +67,21 @@ namespace OpenRa.Game.Graphics } public void DrawBatch(FvfVertexBuffer vertices, IndexBuffer indices, - Range vertexRange, Range indexRange, Texture texture, PrimitiveType type) + Range vertexRange, Range indexRange, Texture texture, PrimitiveType type, Shader shader) + where T : struct + { + shader.SetValue("DiffuseTexture", texture); + shader.Commit(); + + vertices.Bind(0); + indices.Bind(); + + device.DrawIndexedPrimitives(type, + vertexRange, indexRange); + } + + public void DrawBatch(FvfVertexBuffer vertices, IndexBuffer indices, + int vertexPool, int numPrimitives, Texture texture, PrimitiveType type) where T : struct { SpriteShader.SetValue("DiffuseTexture", texture); @@ -73,23 +91,9 @@ namespace OpenRa.Game.Graphics indices.Bind(); device.DrawIndexedPrimitives(type, - vertexRange, indexRange); + vertexPool, numPrimitives); } - public void DrawBatch(FvfVertexBuffer vertices, IndexBuffer indices, - int vertexPool, int numPrimitives, Texture texture, PrimitiveType type) - where T : struct - { - SpriteShader.SetValue("DiffuseTexture", texture); - SpriteShader.Commit(); - - vertices.Bind(0); - indices.Bind(); - - device.DrawIndexedPrimitives(type, - vertexPool, numPrimitives); - } - public void DrawText(string text, int2 pos, Color c) { sh.Begin(); @@ -101,5 +105,19 @@ namespace OpenRa.Game.Graphics { return new int2(fhDebug.MeasureText(sh, text)); } + + public void DrawTexture(Texture t, int2 pos) + { + sh.Begin(); + sh.SetTransform(1,1, pos.X, pos.Y); + sh.Draw(t, 0, 0, 256,256, -1); + sh.End(); + } + + public Texture LoadTexture(string filename) + { + using (var stream = FileSystem.Open(filename)) + return Texture.Create(stream, device); + } } } diff --git a/OpenRa.Game/Graphics/Sheet.cs b/OpenRa.Game/Graphics/Sheet.cs index 57fcda9fea..cff0e3518c 100644 --- a/OpenRa.Game/Graphics/Sheet.cs +++ b/OpenRa.Game/Graphics/Sheet.cs @@ -1,6 +1,7 @@ using System.Drawing; using System.IO; using Ijw.DirectX; +using OpenRa.FileFormats; namespace OpenRa.Game.Graphics { @@ -18,6 +19,12 @@ namespace OpenRa.Game.Graphics this.bitmap = new Bitmap(size.Width, size.Height); } + public Sheet(Renderer renderer, string filename) + { + this.renderer = renderer; + this.bitmap = (Bitmap)Image.FromStream(FileSystem.Open(filename)); + } + void Resolve() { string filename = string.Format("../../../sheet-{0}.png", suffix++); diff --git a/OpenRa.Game/Graphics/SpriteRenderer.cs b/OpenRa.Game/Graphics/SpriteRenderer.cs index 0b9ae75e2d..f1fbcdf9c4 100644 --- a/OpenRa.Game/Graphics/SpriteRenderer.cs +++ b/OpenRa.Game/Graphics/SpriteRenderer.cs @@ -12,6 +12,7 @@ namespace OpenRa.Game.Graphics FvfVertexBuffer vertexBuffer; IndexBuffer indexBuffer; Renderer renderer; + Shader shader; const int spritesPerBatch = 1024; @@ -22,9 +23,10 @@ namespace OpenRa.Game.Graphics ShaderQuality quality; int nv = 0, ni = 0; - public SpriteRenderer(Renderer renderer, bool allowAlpha) + public SpriteRenderer(Renderer renderer, bool allowAlpha, Shader shader) { this.renderer = renderer; + this.shader = shader; vertexBuffer = new FvfVertexBuffer(renderer.Device, vertices.Length, Vertex.Format); indexBuffer = new IndexBuffer(renderer.Device, indices.Length); @@ -32,19 +34,23 @@ namespace OpenRa.Game.Graphics quality = allowAlpha ? ShaderQuality.High : ShaderQuality.Low; } + public SpriteRenderer(Renderer renderer, bool allowAlpha) + : this(renderer, allowAlpha, renderer.SpriteShader) { } + public void Flush() { if (sprites > 0) { - renderer.SpriteShader.Quality = quality; - renderer.SpriteShader.Render(() => + shader.Quality = quality; + shader.Render(() => { vertexBuffer.SetData(vertices); indexBuffer.SetData(indices); renderer.DrawBatch(vertexBuffer, indexBuffer, new Range(0, nv), new Range(0, ni), - currentSheet.Texture, PrimitiveType.TriangleList); + currentSheet.Texture, PrimitiveType.TriangleList, + shader); }); nv = 0; ni = 0; diff --git a/OpenRa.Game/Graphics/TerrainRenderer.cs b/OpenRa.Game/Graphics/TerrainRenderer.cs index 3fb2995a35..86533152f6 100644 --- a/OpenRa.Game/Graphics/TerrainRenderer.cs +++ b/OpenRa.Game/Graphics/TerrainRenderer.cs @@ -76,7 +76,7 @@ namespace OpenRa.Game.Graphics renderer.DrawBatch(vertexBuffer, indexBuffer, new Range(verticesPerRow * firstRow, verticesPerRow * lastRow), new Range(indicesPerRow * firstRow, indicesPerRow * lastRow), - terrainSheet.Texture, PrimitiveType.TriangleList)); + terrainSheet.Texture, PrimitiveType.TriangleList, renderer.SpriteShader)); overlayRenderer.Draw(); } diff --git a/OpenRa.Game/Graphics/Viewport.cs b/OpenRa.Game/Graphics/Viewport.cs index 26ea5204ac..c76b827225 100644 --- a/OpenRa.Game/Graphics/Viewport.cs +++ b/OpenRa.Game/Graphics/Viewport.cs @@ -24,18 +24,19 @@ namespace OpenRa.Game.Graphics public void Scroll(float2 delta) { - scrollPosition = ( scrollPosition + delta ).Constrain( scrollLowBounds, scrollHighBounds ); + scrollPosition = scrollPosition + delta;// (scrollPosition + delta).Constrain(scrollLowBounds, scrollHighBounds); } public Viewport(float2 screenSize, int2 mapStart, int2 mapEnd, Renderer renderer) { this.screenSize = screenSize; - this.scrollLowBounds = Game.CellSize * mapStart; - this.scrollHighBounds = float2.Max( scrollLowBounds, Game.CellSize * mapEnd - ( screenSize - new float2( 128, 0 ) ) ); +// this.scrollLowBounds = Game.CellSize * mapStart; +// this.scrollHighBounds = float2.Max( scrollLowBounds, Game.CellSize * mapEnd - ( screenSize /*- new float2( 128, 0 )*/ ) ); this.renderer = renderer; cursorRenderer = new SpriteRenderer(renderer, true); - this.scrollPosition = scrollLowBounds; + this.scrollPosition = Game.CellSize* mapStart; +// this.scrollPosition = scrollLowBounds; } List regions = new List(); @@ -52,6 +53,8 @@ namespace OpenRa.Game.Graphics foreach (Region region in regions) region.Draw(renderer); + Game.chrome.Draw(); + var c = (Game.worldRenderer.region.Contains(mousePos)) ? cursor : Cursor.Default; cursorRenderer.DrawSprite(c.GetSprite((int)cursorFrame), mousePos + Location - c.GetHotspot(), 0); cursorRenderer.Flush(); diff --git a/OpenRa.Game/Graphics/WorldRenderer.cs b/OpenRa.Game/Graphics/WorldRenderer.cs index d3c51dea07..5120afa049 100644 --- a/OpenRa.Game/Graphics/WorldRenderer.cs +++ b/OpenRa.Game/Graphics/WorldRenderer.cs @@ -4,7 +4,8 @@ using System.Windows.Forms; using IjwFramework.Types; using System.Collections.Generic; using OpenRa.Game.Traits; -using OpenRa.Game.Support; +using OpenRa.Game.Support; +using Ijw.DirectX; namespace OpenRa.Game.Graphics { @@ -15,7 +16,8 @@ namespace OpenRa.Game.Graphics public readonly LineRenderer lineRenderer; public readonly Region region; public readonly UiOverlay uiOverlay; - readonly Renderer renderer; + readonly Renderer renderer; + readonly Texture specialbin; public static bool ShowUnitPaths = false; @@ -25,7 +27,7 @@ namespace OpenRa.Game.Graphics // TODO: this is layout policy. it belongs at a higher level than this. region = Region.Create(Game.viewport, DockStyle.Left, - Game.viewport.Width - 128, Draw, + Game.viewport.Width - /*128*/ 0, Draw, Game.controller.HandleMouseInput); Game.viewport.AddRegion(region); @@ -33,7 +35,9 @@ namespace OpenRa.Game.Graphics this.renderer = renderer; spriteRenderer = new SpriteRenderer(renderer, true); lineRenderer = new LineRenderer(renderer); - uiOverlay = new UiOverlay(spriteRenderer); + uiOverlay = new UiOverlay(spriteRenderer); + + specialbin = renderer.LoadTexture("specialbin.png"); } void DrawSpriteList(RectangleF rect, @@ -67,7 +71,7 @@ namespace OpenRa.Game.Graphics foreach (var a in Game.world.Actors .Where(u => u.traits.Contains()) .Select(u => u.traits.Get())) - DrawSpriteList(rect, a.RenderRoof(a.self)); /* RUDE HACK */ + DrawSpriteList(rect, a.RenderRoof(a.self)); foreach (IEffect e in Game.world.Effects) DrawSpriteList(rect, e.Render()); @@ -98,17 +102,6 @@ namespace OpenRa.Game.Graphics DrawSelectionBox(a, Color.White, true); lineRenderer.Flush(); - - renderer.DrawText(string.Format("RenderFrame {0} ({2:F1} ms)\nTick {1} ({3:F1} ms)\n$ {4}\nPower {5}", - Game.RenderFrame, - Game.orderManager.FrameNumber, - PerfHistory.items["render"].LastValue, - PerfHistory.items["tick_time"].LastValue, - Game.LocalPlayer.Cash, - Game.LocalPlayer.GetTotalPower() - ), new int2(5, 5), Color.White); - - PerfHistory.Render(renderer, lineRenderer); } void DrawSelectionBox(Actor selectedUnit, Color c, bool drawHealthBar) diff --git a/OpenRa.Game/OpenRa.Game.csproj b/OpenRa.Game/OpenRa.Game.csproj index 5cd94575af..c3e3b54ad9 100644 --- a/OpenRa.Game/OpenRa.Game.csproj +++ b/OpenRa.Game/OpenRa.Game.csproj @@ -75,6 +75,7 @@ + diff --git a/OpenRa.Game/Sidebar.cs b/OpenRa.Game/Sidebar.cs index 2ff6fcc6c7..a7c3fc1a22 100644 --- a/OpenRa.Game/Sidebar.cs +++ b/OpenRa.Game/Sidebar.cs @@ -37,7 +37,7 @@ namespace OpenRa.Game { this.player = player; this.renderer = renderer; - region = GRegion.Create(Game.viewport, DockStyle.Right, 128, Paint, MouseHandler); + region = GRegion.Create(Game.viewport, DockStyle.Right, /*128*/0, Paint, MouseHandler); region.UseScissor = false; region.AlwaysWantMovement = true; Game.viewport.AddRegion( region ); diff --git a/bits.psd b/bits.psd new file mode 100644 index 0000000000..0dc50b63e4 Binary files /dev/null and b/bits.psd differ diff --git a/rgbasprite.fx b/rgbasprite.fx new file mode 100644 index 0000000000..e118112e07 --- /dev/null +++ b/rgbasprite.fx @@ -0,0 +1,74 @@ +// OpenRA ui shader for non-SHP sprites (mostly just chrome) +// Author: C. Forbes +//-------------------------------------------------------- + +shared texture DiffuseTexture; +shared float2 r1, r2; // matrix elements + +sampler s_DiffuseTexture = sampler_state { + Texture = ; + MinFilter = None; + MagFilter = None; + MipFilter = None; + + AddressU = Wrap; + AddressV = Wrap; + AddressW = Wrap; +}; + +struct VertexIn { + float4 Position: POSITION; + float2 Tex0: TEXCOORD0; + float2 Tex1: TEXCOORD1; +}; + +struct VertexOut { + float4 Position: POSITION; + float2 Tex0: TEXCOORD0; +}; + +struct FragmentIn { + float2 Tex0: TEXCOORD0; +}; + +VertexOut Simple_vp(VertexIn v) { + VertexOut o; + float2 p = v.Position.xy * r1 + r2; + o.Position = float4(p.x,p.y,0,1); + o.Tex0 = v.Tex0; + return o; +} + +float4 Simple_fp(FragmentIn f) : COLOR0 { + float4 r = tex2D(s_DiffuseTexture, f.Tex0.xy); + return r; +} + +/* +technique low_quality { + pass p0 { + AlphaBlendEnable = false; + ZWriteEnable = false; + ZEnable = false; + CullMode = None; + FillMode = Solid; + VertexShader = compile vs_2_0 Simple_vp(); + PixelShader = compile ps_2_0 Simple_fp(); + } +} +*/ + +technique high_quality { + pass p0 { + AlphaBlendEnable = true; + ZWriteEnable = false; + ZEnable = false; + CullMode = None; + FillMode = Solid; + VertexShader = compile vs_2_0 Simple_vp(); + PixelShader = compile ps_2_0 Simple_fp(); + + SrcBlend = SrcAlpha; + DestBlend = InvSrcAlpha; + } +} diff --git a/specialbin.png b/specialbin.png new file mode 100644 index 0000000000..673ca32853 Binary files /dev/null and b/specialbin.png differ