public TerrainSpriteLayer(World world, WorldRenderer wr, Sheet sheet, BlendMode blendMode, PaletteReference palette, bool restrictToBounds) { worldRenderer = wr; this.restrictToBounds = restrictToBounds; Sheet = sheet; BlendMode = blendMode; paletteIndex = palette.TextureIndex; map = world.Map; rowStride = 4 * map.MapSize.X; vertices = new Vertex[rowStride * map.MapSize.Y]; vertexBuffer = Game.Renderer.Device.CreateVertexBuffer(vertices.Length); emptySprite = new Sprite(sheet, Rectangle.Empty, TextureChannel.Alpha); wr.PaletteInvalidated += () => { paletteIndex = palette.TextureIndex; // Everything in the layer uses the same palette, // so we can fix the indices in one pass for (var i = 0; i < vertices.Length; i++) { var v = vertices[i]; vertices[i] = new Vertex(v.X, v.Y, v.Z, v.U, v.V, paletteIndex, v.C); } for (var row = 0; row < map.MapSize.Y; row++) dirtyRows.Add(row); }; }
public static void FastCreateQuad(Vertex[] vertices, float2 o, Sprite r, int palette, int nv, float2 size) { var b = new float2(o.X + size.X, o.Y); var c = new float2(o.X + size.X, o.Y + size.Y); var d = new float2(o.X, o.Y + size.Y); FastCreateQuad(vertices, o, b, c, d, r, palette, nv); }
public void DrawLine(float2 start, float2 end, float width, Color startColor, Color endColor) { renderer.CurrentBatchRenderer = this; if (nv + 6 > renderer.TempBufferSize) Flush(); var delta = (end - start) / (end - start).Length; var corner = width / 2 * new float2(-delta.Y, delta.X); startColor = Util.PremultiplyAlpha(startColor); var sr = startColor.R / 255.0f; var sg = startColor.G / 255.0f; var sb = startColor.B / 255.0f; var sa = startColor.A / 255.0f; endColor = Util.PremultiplyAlpha(endColor); var er = endColor.R / 255.0f; var eg = endColor.G / 255.0f; var eb = endColor.B / 255.0f; var ea = endColor.A / 255.0f; vertices[nv++] = new Vertex(start - corner + Offset, sr, sg, sb, sa); vertices[nv++] = new Vertex(start + corner + Offset, sr, sg, sb, sa); vertices[nv++] = new Vertex(end + corner + Offset, er, eg, eb, ea); vertices[nv++] = new Vertex(end + corner + Offset, er, eg, eb, ea); vertices[nv++] = new Vertex(end - corner + Offset, er, eg, eb, ea); vertices[nv++] = new Vertex(start - corner + Offset, sr, sg, sb, sa); }
public static void FastCreateQuad(Vertex[] vertices, float2 a, float2 b, float2 c, float2 d, Sprite r, int palette, int nv) { var attrib = new float2(palette / (float)HardwarePalette.MaxPalettes, channelSelect[(int)r.channel]); vertices[nv] = new Vertex(a, r.FastMapTextureCoords(0), attrib); vertices[nv + 1] = new Vertex(b, r.FastMapTextureCoords(1), attrib); vertices[nv + 2] = new Vertex(c, r.FastMapTextureCoords(3), attrib); vertices[nv + 3] = new Vertex(d, r.FastMapTextureCoords(2), attrib); }
public static void FastCreateQuad(Vertex[] vertices, float2 a, float2 b, float2 c, float2 d, Sprite r, int palette, int nv) { var attribP = palette / (float)HardwarePalette.MaxPalettes; var attribC = channelSelect[(int)r.channel]; vertices[nv] = new Vertex(a, r.left, r.top, attribP, attribC); vertices[nv + 1] = new Vertex(b, r.right, r.top, attribP, attribC); vertices[nv + 2] = new Vertex(c, r.right, r.bottom, attribP, attribC); vertices[nv + 3] = new Vertex(d, r.left, r.bottom, attribP, attribC); }
public static void FastCreateQuad(Vertex[] vertices, float2 a, float2 b, float2 c, float2 d, Sprite r, float paletteTextureIndex, int nv) { var attribC = ChannelSelect[(int)r.Channel]; if (r.Sheet.Type == SheetType.DualIndexed) attribC *= -1; vertices[nv] = new Vertex(a, r.Left, r.Top, paletteTextureIndex, attribC); vertices[nv + 1] = new Vertex(b, r.Right, r.Top, paletteTextureIndex, attribC); vertices[nv + 2] = new Vertex(c, r.Right, r.Bottom, paletteTextureIndex, attribC); vertices[nv + 3] = new Vertex(d, r.Left, r.Bottom, paletteTextureIndex, attribC); }
void UpdatePaletteIndices() { // Everything in the layer uses the same palette, // so we can fix the indices in one pass for (var i = 0; i < vertices.Length; i++) { var v = vertices[i]; vertices[i] = new Vertex(v.X, v.Y, v.Z, v.U, v.V, palette.TextureIndex, v.C); } for (var row = 0; row < map.MapSize.Y; row++) dirtyRows.Add(row); }
public void FillRect(RectangleF r, Color color) { Renderer.CurrentBatchRenderer = this; if (nv + 4 > Renderer.TempBufferSize) Flush(); vertices[nv] = new Vertex(new float2(r.Left, r.Top), new float2(color.R / 255.0f, color.G / 255.0f), new float2(color.B / 255.0f, color.A / 255.0f)); vertices[nv + 1] = new Vertex(new float2(r.Right, r.Top), new float2(color.R / 255.0f, color.G / 255.0f), new float2(color.B / 255.0f, color.A / 255.0f)); vertices[nv + 2] = new Vertex(new float2(r.Right, r.Bottom), new float2(color.R / 255.0f, color.G / 255.0f), new float2(color.B / 255.0f, color.A / 255.0f)); vertices[nv + 3] = new Vertex(new float2(r.Left, r.Bottom), new float2(color.R / 255.0f, color.G / 255.0f), new float2(color.B / 255.0f, color.A / 255.0f)); nv += 4; }
public void DrawLine(float2 start, float2 end, Color color) { renderer.CurrentBatchRenderer = this; if (nv + 2 > renderer.TempBufferSize) Flush(); color = Util.PremultiplyAlpha(color); var r = color.R / 255.0f; var g = color.G / 255.0f; var b = color.B / 255.0f; var a = color.A / 255.0f; vertices[nv++] = new Vertex(start + Offset, r, g, b, a); vertices[nv++] = new Vertex(end + Offset, r, g, b, a); }
public void DrawLine(float2 start, float2 end, Color startColor, Color endColor) { Renderer.CurrentBatchRenderer = this; if (nv + 2 > Renderer.TempBufferSize) Flush(); vertices[nv++] = new Vertex(start + offset, new float2(startColor.R / 255.0f, startColor.G / 255.0f), new float2(startColor.B / 255.0f, startColor.A / 255.0f)); vertices[nv++] = new Vertex(end + offset, new float2(endColor.R / 255.0f, endColor.G / 255.0f), new float2(endColor.B / 255.0f, endColor.A / 255.0f)); }
public void FillRect(RectangleF rect, Color color) { Renderer.CurrentBatchRenderer = this; if (nv + 4 > Renderer.TempBufferSize) Flush(); var r = color.R / 255.0f; var g = color.G / 255.0f; var b = color.B / 255.0f; var a = color.A / 255.0f; vertices[nv] = new Vertex(new float2(rect.Left, rect.Top), r, g, b, a); vertices[nv + 1] = new Vertex(new float2(rect.Right, rect.Top), r, g, b, a); vertices[nv + 2] = new Vertex(new float2(rect.Right, rect.Bottom), r, g, b, a); vertices[nv + 3] = new Vertex(new float2(rect.Left, rect.Bottom), r, g, b, a); nv += 4; }
public TerrainRenderer(World world, WorldRenderer wr) { this.world = world; this.map = world.Map; var terrainPalette = wr.Palette("terrain").Index; var vertices = new Vertex[4 * map.Bounds.Height * map.Bounds.Width]; var nv = 0; foreach (var cell in map.Cells) { var tile = wr.Theater.TileSprite(map.MapTiles.Value[cell]); var pos = wr.ScreenPosition(map.CenterOfCell(cell)) - 0.5f * tile.size; Util.FastCreateQuad(vertices, pos, tile, terrainPalette, nv, tile.size); nv += 4; } vertexBuffer = Game.Renderer.Device.CreateVertexBuffer(vertices.Length); vertexBuffer.SetData(vertices, nv); }
public TerrainRenderer(World world, WorldRenderer wr) { this.world = world; this.map = world.Map; var terrainPalette = wr.Palette("terrain").Index; var vertices = new Vertex[4 * map.Bounds.Height * map.Bounds.Width]; int nv = 0; for (var j = map.Bounds.Top; j < map.Bounds.Bottom; j++) { for (var i = map.Bounds.Left; i < map.Bounds.Right; i++) { var tile = wr.Theater.TileSprite(map.MapTiles.Value[i, j]); var pos = wr.ScreenPosition(new CPos(i, j).CenterPosition) - 0.5f * tile.size; Util.FastCreateQuad(vertices, pos, tile, terrainPalette, nv, tile.size); nv += 4; } } vertexBuffer = Game.Renderer.Device.CreateVertexBuffer(vertices.Length); vertexBuffer.SetData(vertices, nv); }
public void FillRect(float2 a, float2 b, float2 c, float2 d, Color color) { renderer.CurrentBatchRenderer = this; if (nv + 6 > renderer.TempBufferSize) Flush(); color = Util.PremultiplyAlpha(color); var cr = color.R / 255.0f; var cg = color.G / 255.0f; var cb = color.B / 255.0f; var ca = color.A / 255.0f; vertices[nv++] = new Vertex(a + Offset, cr, cg, cb, ca); vertices[nv++] = new Vertex(b + Offset, cr, cg, cb, ca); vertices[nv++] = new Vertex(c + Offset, cr, cg, cb, ca); vertices[nv++] = new Vertex(c + Offset, cr, cg, cb, ca); vertices[nv++] = new Vertex(d + Offset, cr, cg, cb, ca); vertices[nv++] = new Vertex(a + Offset, cr, cg, cb, ca); }
public void DrawLineStrip(IEnumerable<float2> points, Color color) { renderer.CurrentBatchRenderer = this; color = Util.PremultiplyAlpha(color); var r = color.R / 255.0f; var g = color.G / 255.0f; var b = color.B / 255.0f; var a = color.A / 255.0f; var first = true; var prev = new Vertex(); foreach (var point in points) { if (first) { first = false; prev = new Vertex(point + Offset, r, g, b, a); continue; } if (nv + 2 > renderer.TempBufferSize) Flush(); vertices[nv++] = prev; prev = new Vertex(point + Offset, r, g, b, a); vertices[nv++] = prev; } }
public void DrawLine(float2 start, float2 end, float width, Color color) { renderer.CurrentBatchRenderer = this; if (nv + 6 > renderer.TempBufferSize) Flush(); var delta = (end - start) / (end - start).Length; var corner = width / 2 * new float2(-delta.Y, delta.X); color = Util.PremultiplyAlpha(color); var r = color.R / 255.0f; var g = color.G / 255.0f; var b = color.B / 255.0f; var a = color.A / 255.0f; vertices[nv++] = new Vertex(start - corner + Offset, r, g, b, a); vertices[nv++] = new Vertex(start + corner + Offset, r, g, b, a); vertices[nv++] = new Vertex(end + corner + Offset, r, g, b, a); vertices[nv++] = new Vertex(end + corner + Offset, r, g, b, a); vertices[nv++] = new Vertex(end - corner + Offset, r, g, b, a); vertices[nv++] = new Vertex(start - corner + Offset, r, g, b, a); }
Sprite CacheTile(MPos uv, int offset, Edges edges, TileInfo tileInfo, Sprite[] sprites, Vertex[] vertices, PaletteReference palette, CellLayer<Sprite> spriteLayer) { var sprite = GetSprite(sprites, edges, tileInfo.Variant); if (sprite != null) { var size = sprite.Size; var location = tileInfo.ScreenPosition - 0.5f * size; OpenRA.Graphics.Util.FastCreateQuad( vertices, location + sprite.FractionalOffset * size, sprite, palette.TextureIndex, offset, size); } spriteLayer[uv] = sprite; return sprite; }
void RenderCachedTile(Sprite sprite, Vertex[] vertices, int offset) { if (sprite != null) Game.Renderer.WorldSpriteRenderer.DrawSprite(sprite, vertices, offset); }
void GenerateTileVertices(Vertex[] vertices, int offset, CPos cell) { var tile = theater.TileSprite(mapTiles[cell]); var pos = worldRenderer.ScreenPosition(map.CenterOfCell(cell)) + tile.Offset - 0.5f * tile.Size; Util.FastCreateQuad(vertices, pos, tile, terrainPaletteIndex, offset, tile.Size); }
void UpdateMap() { var nv = 0; var vertices = new Vertex[rowStride * map.Bounds.Height]; foreach (var cell in map.Cells) { GenerateTileVertices(vertices, nv, cell); nv += 4; } vertexBuffer.SetData(vertices, nv); }
void DrawConnectedLine(float2[] points, float width, Color color, bool closed) { // Not a line if (points.Length < 2) return; // Single segment if (points.Length == 2) { DrawLine(points[0], points[1], width, color); return; } renderer.CurrentBatchRenderer = this; color = Util.PremultiplyAlpha(color); var r = color.R / 255.0f; var g = color.G / 255.0f; var b = color.B / 255.0f; var a = color.A / 255.0f; var start = points[0]; var end = points[1]; var dir = (end - start) / (end - start).Length; var corner = width / 2 * new float2(-dir.Y, dir.X); // Corners for start of line segment var ca = start - corner; var cb = start + corner; // Segment is part of closed loop if (closed) { var prev = points[points.Length - 1]; var prevDir = (start - prev) / (start - prev).Length; var prevCorner = width / 2 * new float2(-prevDir.Y, prevDir.X); ca = IntersectionOf(start - prevCorner, prevDir, start - corner, dir); cb = IntersectionOf(start + prevCorner, prevDir, start + corner, dir); } var limit = closed ? points.Length : points.Length - 1; for (var i = 0; i < limit; i++) { var next = points[(i + 2) % points.Length]; var nextDir = (next - end) / (next - end).Length; var nextCorner = width / 2 * new float2(-nextDir.Y, nextDir.X); // Vertices for the corners joining start-end to end-next var cc = closed || i < limit ? IntersectionOf(end + corner, dir, end + nextCorner, nextDir) : end + corner; var cd = closed || i < limit ? IntersectionOf(end - corner, dir, end - nextCorner, nextDir) : end - corner; // Fill segment if (nv + 6 > renderer.TempBufferSize) Flush(); vertices[nv++] = new Vertex(ca + Offset, r, g, b, a); vertices[nv++] = new Vertex(cb + Offset, r, g, b, a); vertices[nv++] = new Vertex(cc + Offset, r, g, b, a); vertices[nv++] = new Vertex(cc + Offset, r, g, b, a); vertices[nv++] = new Vertex(cd + Offset, r, g, b, a); vertices[nv++] = new Vertex(ca + Offset, r, g, b, a); // Advance line segment end = next; dir = nextDir; corner = nextCorner; ca = cd; cb = cc; } }
public void DrawSprite(Sprite s, Vertex[] sourceVertices, int offset) { SetRenderStateForSprite(s); Array.Copy(sourceVertices, offset, vertices, nv, 6); nv += 6; }
void RenderDirtyTile(MPos uv, int offset, Func<MPos, bool> isVisible, Sprite[] sprites, Vertex[] vertices, PaletteReference palette, CellLayer<Sprite> spriteLayer) { var tile = tileInfos[uv]; var edges = GetEdges(uv, isVisible); var sprite = CacheTile(uv, offset, edges, tile, sprites, vertices, palette, spriteLayer); RenderCachedTile(sprite, vertices, offset); }
public ShroudRenderer(World world, ShroudRendererInfo info) { if (info.ShroudVariants.Length != info.FogVariants.Length) throw new ArgumentException("ShroudRenderer must define the same number of shroud and fog variants!", "info"); if ((info.OverrideFullFog == null) ^ (info.OverrideFullShroud == null)) throw new ArgumentException("ShroudRenderer cannot define overrides for only one of shroud or fog!", "info"); if (info.ShroudVariants.Length > byte.MaxValue) throw new ArgumentException("ShroudRenderer cannot define this many shroud and fog variants.", "info"); if (info.Index.Length >= byte.MaxValue) throw new ArgumentException("ShroudRenderer cannot define this many indexes for shroud directions.", "info"); this.info = info; map = world.Map; tileInfos = new CellLayer<TileInfo>(map); shroudDirty = new CellLayer<bool>(map); cellsDirty = new HashSet<CPos>(); cellsAndNeighborsDirty = new HashSet<CPos>(); var verticesLength = map.MapSize.X * map.MapSize.Y * 4; fogVertices = new Vertex[verticesLength]; shroudVertices = new Vertex[verticesLength]; fogSpriteLayer = new CellLayer<Sprite>(map); shroudSpriteLayer = new CellLayer<Sprite>(map); // Load sprite variants var variantCount = info.ShroudVariants.Length; variantStride = (byte)(info.Index.Length + (info.OverrideFullShroud != null ? 1 : 0)); shroudSprites = new Sprite[variantCount * variantStride]; fogSprites = new Sprite[variantCount * variantStride]; for (var j = 0; j < variantCount; j++) { var shroud = map.SequenceProvider.GetSequence(info.Sequence, info.ShroudVariants[j]); var fog = map.SequenceProvider.GetSequence(info.Sequence, info.FogVariants[j]); for (var i = 0; i < info.Index.Length; i++) { shroudSprites[j * variantStride + i] = shroud.GetSprite(i); fogSprites[j * variantStride + i] = fog.GetSprite(i); } if (info.OverrideFullShroud != null) { var i = (j + 1) * variantStride - 1; shroudSprites[i] = map.SequenceProvider.GetSequence(info.Sequence, info.OverrideFullShroud).GetSprite(0); fogSprites[i] = map.SequenceProvider.GetSequence(info.Sequence, info.OverrideFullFog).GetSprite(0); } } // Mapping of shrouded directions -> sprite index edgesToSpriteIndexOffset = new byte[(byte)(info.UseExtendedIndex ? Edges.All : Edges.AllCorners) + 1]; for (var i = 0; i < info.Index.Length; i++) edgesToSpriteIndexOffset[info.Index[i]] = (byte)i; if (info.OverrideFullShroud != null) edgesToSpriteIndexOffset[info.OverrideShroudIndex] = (byte)(variantStride - 1); notVisibleEdges = info.UseExtendedIndex ? Edges.AllSides : Edges.AllCorners; }