Merge pull request #8193 from RoosterDragon/line-render-perf

Improve performance of line rendering
This commit is contained in:
Pavel Penev
2015-05-22 17:51:11 +03:00
12 changed files with 138 additions and 100 deletions

View File

@@ -9,6 +9,7 @@
#endregion #endregion
using System; using System;
using System.Collections.Generic;
using System.Drawing; using System.Drawing;
namespace OpenRA.Graphics namespace OpenRA.Graphics
@@ -69,10 +70,25 @@ namespace OpenRA.Graphics
{ {
var tr = new float2(br.X, tl.Y); var tr = new float2(br.X, tl.Y);
var bl = new float2(tl.X, br.Y); var bl = new float2(tl.X, br.Y);
DrawLine(tl, tr, c, c); DrawLine(tl, tr, c);
DrawLine(tl, bl, c, c); DrawLine(tl, bl, c);
DrawLine(tr, br, c, c); DrawLine(tr, br, c);
DrawLine(bl, br, c, c); DrawLine(bl, br, c);
}
public void DrawLine(float2 start, float2 end, Color color)
{
renderer.CurrentBatchRenderer = this;
if (nv + 2 > 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(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) public void DrawLine(float2 start, float2 end, Color startColor, Color endColor)
@@ -82,19 +98,52 @@ namespace OpenRA.Graphics
if (nv + 2 > renderer.TempBufferSize) if (nv + 2 > renderer.TempBufferSize)
Flush(); Flush();
vertices[nv++] = new Vertex(start + Offset, var r = startColor.R / 255.0f;
startColor.R / 255.0f, startColor.G / 255.0f, var g = startColor.G / 255.0f;
startColor.B / 255.0f, startColor.A / 255.0f); var b = startColor.B / 255.0f;
var a = startColor.A / 255.0f;
vertices[nv++] = new Vertex(start + Offset, r, g, b, a);
vertices[nv++] = new Vertex(end + Offset, r = endColor.R / 255.0f;
endColor.R / 255.0f, endColor.G / 255.0f, g = endColor.G / 255.0f;
endColor.B / 255.0f, endColor.A / 255.0f); b = endColor.B / 255.0f;
a = endColor.A / 255.0f;
vertices[nv++] = new Vertex(end + Offset, r, g, b, a);
}
public void DrawLineStrip(IEnumerable<float2> points, Color color)
{
renderer.CurrentBatchRenderer = this;
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 FillRect(RectangleF r, Color color) public void FillRect(RectangleF r, Color color)
{ {
for (var y = r.Top; y < r.Bottom; y++) for (var y = r.Top; y < r.Bottom; y++)
DrawLine(new float2(r.Left, y), new float2(r.Right, y), color, color); DrawLine(new float2(r.Left, y), new float2(r.Right, y), color);
} }
public void FillEllipse(RectangleF r, Color color) public void FillEllipse(RectangleF r, Color color)
@@ -106,7 +155,7 @@ namespace OpenRA.Graphics
for (var y = r.Top; y <= r.Bottom; y++) for (var y = r.Top; y <= r.Bottom; y++)
{ {
var dx = a * (float)Math.Sqrt(1 - (y - yc) * (y - yc) / b / b); var dx = a * (float)Math.Sqrt(1 - (y - yc) * (y - yc) / b / b);
DrawLine(new float2(xc - dx, y), new float2(xc + dx, y), color, color); DrawLine(new float2(xc - dx, y), new float2(xc + dx, y), color);
} }
} }

View File

@@ -65,13 +65,13 @@ namespace OpenRA.Graphics
var z = float2.Lerp(start, end, value); var z = float2.Lerp(start, end, value);
var wlr = Game.Renderer.WorldLineRenderer; var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(start + p, end + p, c, c); wlr.DrawLine(start + p, end + p, c);
wlr.DrawLine(start + q, end + q, c2, c2); wlr.DrawLine(start + q, end + q, c2);
wlr.DrawLine(start + r, end + r, c, c); wlr.DrawLine(start + r, end + r, c);
wlr.DrawLine(start + p, z + p, barColor2, barColor2); wlr.DrawLine(start + p, z + p, barColor2);
wlr.DrawLine(start + q, z + q, barColor, barColor); wlr.DrawLine(start + q, z + q, barColor);
wlr.DrawLine(start + r, z + r, barColor2, barColor2); wlr.DrawLine(start + r, z + r, barColor2);
} }
Color GetHealthColor(Health health) Color GetHealthColor(Health health)
@@ -125,13 +125,13 @@ namespace OpenRA.Graphics
var z = float2.Lerp(start, end, (float)health.HP / health.MaxHP); var z = float2.Lerp(start, end, (float)health.HP / health.MaxHP);
var wlr = Game.Renderer.WorldLineRenderer; var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(start + p, end + p, c, c); wlr.DrawLine(start + p, end + p, c);
wlr.DrawLine(start + q, end + q, c2, c2); wlr.DrawLine(start + q, end + q, c2);
wlr.DrawLine(start + r, end + r, c, c); wlr.DrawLine(start + r, end + r, c);
wlr.DrawLine(start + p, z + p, healthColor2, healthColor2); wlr.DrawLine(start + p, z + p, healthColor2);
wlr.DrawLine(start + q, z + q, healthColor, healthColor); wlr.DrawLine(start + q, z + q, healthColor);
wlr.DrawLine(start + r, z + r, healthColor2, healthColor2); wlr.DrawLine(start + r, z + r, healthColor2);
if (health.DisplayHp != health.HP) if (health.DisplayHp != health.HP)
{ {
@@ -143,9 +143,9 @@ namespace OpenRA.Graphics
deltaColor.B / 2); deltaColor.B / 2);
var zz = float2.Lerp(start, end, (float)health.DisplayHp / health.MaxHP); var zz = float2.Lerp(start, end, (float)health.DisplayHp / health.MaxHP);
wlr.DrawLine(z + p, zz + p, deltaColor2, deltaColor2); wlr.DrawLine(z + p, zz + p, deltaColor2);
wlr.DrawLine(z + q, zz + q, deltaColor, deltaColor); wlr.DrawLine(z + q, zz + q, deltaColor);
wlr.DrawLine(z + r, zz + r, deltaColor2, deltaColor2); wlr.DrawLine(z + r, zz + r, deltaColor2);
} }
} }

View File

@@ -55,15 +55,15 @@ namespace OpenRA.Graphics
var v = new float2(0, 4f / wr.Viewport.Zoom); var v = new float2(0, 4f / wr.Viewport.Zoom);
var wlr = Game.Renderer.WorldLineRenderer; var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(tl + u, tl, color, color); wlr.DrawLine(tl + u, tl, color);
wlr.DrawLine(tl, tl + v, color, color); wlr.DrawLine(tl, tl + v, color);
wlr.DrawLine(tr, tr - u, color, color); wlr.DrawLine(tr, tr - u, color);
wlr.DrawLine(tr, tr + v, color, color); wlr.DrawLine(tr, tr + v, color);
wlr.DrawLine(bl, bl + u, color, color); wlr.DrawLine(bl, bl + u, color);
wlr.DrawLine(bl, bl - v, color, color); wlr.DrawLine(bl, bl - v, color);
wlr.DrawLine(br, br - u, color, color); wlr.DrawLine(br, br - u, color);
wlr.DrawLine(br, br - v, color, color); wlr.DrawLine(br, br - v, color);
} }
public void RenderDebugGeometry(WorldRenderer wr) { } public void RenderDebugGeometry(WorldRenderer wr) { }

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Graphics
var a = first; var a = first;
foreach (var b in waypoints.Skip(1).Select(pos => wr.ScreenPxPosition(pos))) foreach (var b in waypoints.Skip(1).Select(pos => wr.ScreenPxPosition(pos)))
{ {
Game.Renderer.WorldLineRenderer.DrawLine(a, b, color, color); Game.Renderer.WorldLineRenderer.DrawLine(a, b, color);
wr.DrawTargetMarker(color, b); wr.DrawTargetMarker(color, b);
a = b; a = b;
} }

View File

@@ -202,7 +202,7 @@ namespace OpenRA.Graphics
{ {
var pa = pos + offset.Rotate(WRot.FromFacing(8 * i)); var pa = pos + offset.Rotate(WRot.FromFacing(8 * i));
var pb = pos + offset.Rotate(WRot.FromFacing(8 * i + 6)); var pb = pos + offset.Rotate(WRot.FromFacing(8 * i + 6));
Game.Renderer.WorldLineRenderer.DrawLine(ScreenPosition(pa), ScreenPosition(pb), c, c); Game.Renderer.WorldLineRenderer.DrawLine(ScreenPosition(pa), ScreenPosition(pb), c);
} }
} }
@@ -214,10 +214,10 @@ namespace OpenRA.Graphics
var tr = new float2(br.X, tl.Y); var tr = new float2(br.X, tl.Y);
var wlr = Game.Renderer.WorldLineRenderer; var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(location + tl, location + tr, c, c); wlr.DrawLine(location + tl, location + tr, c);
wlr.DrawLine(location + tr, location + br, c, c); wlr.DrawLine(location + tr, location + br, c);
wlr.DrawLine(location + br, location + bl, c, c); wlr.DrawLine(location + br, location + bl, c);
wlr.DrawLine(location + bl, location + tl, c, c); wlr.DrawLine(location + bl, location + tl, c);
} }
public void RefreshPalette() public void RefreshPalette()

View File

@@ -49,7 +49,7 @@ namespace OpenRA.Mods.Common.Graphics
var oldWidth = wlr.LineWidth; var oldWidth = wlr.LineWidth;
wlr.LineWidth = wr.Viewport.Zoom * width; wlr.LineWidth = wr.Viewport.Zoom * width;
wlr.DrawLine(src, dest, color, color); wlr.DrawLine(src, dest, color);
wlr.LineWidth = oldWidth; wlr.LineWidth = oldWidth;
} }

View File

@@ -135,10 +135,10 @@ namespace OpenRA.Mods.Common.Graphics
// Draw transformed shadow sprite rect // Draw transformed shadow sprite rect
var c = Color.Purple; var c = Color.Purple;
var psb = renderProxy.ProjectedShadowBounds; var psb = renderProxy.ProjectedShadowBounds;
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[1], shadowOrigin + psb[3], c, c); Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[1], shadowOrigin + psb[3], c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[3], shadowOrigin + psb[0], c, c); Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[3], shadowOrigin + psb[0], c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[0], shadowOrigin + psb[2], c, c); Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[0], shadowOrigin + psb[2], c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[2], shadowOrigin + psb[1], c, c); Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[2], shadowOrigin + psb[1], c);
// Draw voxel bounding box // Draw voxel bounding box
var draw = voxel.voxels.Where(v => v.DisableFunc == null || !v.DisableFunc()); var draw = voxel.voxels.Where(v => v.DisableFunc == null || !v.DisableFunc());
@@ -171,20 +171,20 @@ namespace OpenRA.Mods.Common.Graphics
corners[i] = pxPos + new float2(screen[0], screen[1]); corners[i] = pxPos + new float2(screen[0], screen[1]);
} }
Game.Renderer.WorldLineRenderer.DrawLine(corners[0], corners[1], c, c); Game.Renderer.WorldLineRenderer.DrawLine(corners[0], corners[1], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[1], corners[3], c, c); Game.Renderer.WorldLineRenderer.DrawLine(corners[1], corners[3], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[3], corners[2], c, c); Game.Renderer.WorldLineRenderer.DrawLine(corners[3], corners[2], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[2], corners[0], c, c); Game.Renderer.WorldLineRenderer.DrawLine(corners[2], corners[0], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[4], corners[5], c, c); Game.Renderer.WorldLineRenderer.DrawLine(corners[4], corners[5], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[5], corners[7], c, c); Game.Renderer.WorldLineRenderer.DrawLine(corners[5], corners[7], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[7], corners[6], c, c); Game.Renderer.WorldLineRenderer.DrawLine(corners[7], corners[6], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[6], corners[4], c, c); Game.Renderer.WorldLineRenderer.DrawLine(corners[6], corners[4], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[0], corners[4], c, c); Game.Renderer.WorldLineRenderer.DrawLine(corners[0], corners[4], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[1], corners[5], c, c); Game.Renderer.WorldLineRenderer.DrawLine(corners[1], corners[5], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[2], corners[6], c, c); Game.Renderer.WorldLineRenderer.DrawLine(corners[2], corners[6], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[3], corners[7], c, c); Game.Renderer.WorldLineRenderer.DrawLine(corners[3], corners[7], c);
} }
public Rectangle ScreenBounds(WorldRenderer wr) public Rectangle ScreenBounds(WorldRenderer wr)

View File

@@ -69,8 +69,8 @@ namespace OpenRA.Mods.Common.Traits
var o = wr.ScreenPosition(pos); var o = wr.ScreenPosition(pos);
var a = wr.ScreenPosition(pos + da * 224 / da.Length); var a = wr.ScreenPosition(pos + da * 224 / da.Length);
var b = wr.ScreenPosition(pos + db * 224 / db.Length); var b = wr.ScreenPosition(pos + db * 224 / db.Length);
wlr.DrawLine(o, a, c, c); wlr.DrawLine(o, a, c);
wlr.DrawLine(o, b, c, c); wlr.DrawLine(o, b, c);
} }
return; return;
@@ -85,7 +85,7 @@ namespace OpenRA.Mods.Common.Traits
var sm = wr.ScreenPosition(muzzle); var sm = wr.ScreenPosition(muzzle);
var sd = wr.ScreenPosition(muzzle + dirOffset); var sd = wr.ScreenPosition(muzzle + dirOffset);
wlr.DrawLine(sm, sd, c, c); wlr.DrawLine(sm, sd, c);
wr.DrawTargetMarker(c, sm); wr.DrawTargetMarker(c, sm);
} }
} }

View File

@@ -118,21 +118,18 @@ namespace OpenRA.Mods.Common.Widgets
if (points.Any()) if (points.Any())
{ {
points = points.Reverse().Take(xAxisSize).Reverse(); points = points.Reverse().Take(xAxisSize).Reverse();
var scaledData = points.Select(d => d * scale); var lastX = 0;
var x = 0; var lastPoint = 0f;
scaledData.Aggregate((a, b) => Game.Renderer.LineRenderer.DrawLineStrip(
{ points.Select((point, x) =>
Game.Renderer.LineRenderer.DrawLine( {
origin + new float2(x, -a), lastX = x;
origin + new float2(x + xStep, -b), lastPoint = point;
color, color); return origin + new float2(x * xStep, -point * scale);
x += xStep; }), color);
return b;
});
var value = points.Last(); if (lastPoint != 0f)
if (value != 0) tiny.DrawText(GetValueFormat().F(lastPoint), origin + new float2(lastX * xStep, -lastPoint * scale - 2), color);
tiny.DrawText(GetValueFormat().F(value), origin + new float2(x, -value * scale - 2), color);
} }
tiny.DrawText(key, new float2(rect.Left, rect.Top) + new float2(5, 10 * keyOffset + 3), color); tiny.DrawText(key, new float2(rect.Left, rect.Top) + new float2(5, 10 * keyOffset + 3), color);
@@ -142,7 +139,7 @@ namespace OpenRA.Mods.Common.Widgets
// TODO: make this stuff not draw outside of the RenderBounds // TODO: make this stuff not draw outside of the RenderBounds
for (int n = pointStart, x = 0; n <= pointEnd; n++, x += xStep) for (int n = pointStart, x = 0; n <= pointEnd; n++, x += xStep)
{ {
Game.Renderer.LineRenderer.DrawLine(origin + new float2(x, 0), origin + new float2(x, -5), Color.White, Color.White); Game.Renderer.LineRenderer.DrawLine(origin + new float2(x, 0), origin + new float2(x, -5), Color.White);
tiny.DrawText(GetXAxisValueFormat().F(n), origin + new float2(x, 2), Color.White); tiny.DrawText(GetXAxisValueFormat().F(n), origin + new float2(x, 2), Color.White);
} }
@@ -151,16 +148,16 @@ namespace OpenRA.Mods.Common.Widgets
for (var y = GetDisplayFirstYAxisValue() ? 0 : yStep; y <= height; y += yStep) for (var y = GetDisplayFirstYAxisValue() ? 0 : yStep; y <= height; y += yStep)
{ {
var yValue = y / scale; var yValue = y / scale;
Game.Renderer.LineRenderer.DrawLine(origin + new float2(width - 5, -y), origin + new float2(width, -y), Color.White, Color.White); Game.Renderer.LineRenderer.DrawLine(origin + new float2(width - 5, -y), origin + new float2(width, -y), Color.White);
tiny.DrawText(GetYAxisValueFormat().F(yValue), origin + new float2(width + 2, -y), Color.White); tiny.DrawText(GetYAxisValueFormat().F(yValue), origin + new float2(width + 2, -y), Color.White);
} }
bold.DrawText(GetYAxisLabel(), origin + new float2(width + 40, -(height / 2)), Color.White); bold.DrawText(GetYAxisLabel(), origin + new float2(width + 40, -(height / 2)), Color.White);
Game.Renderer.LineRenderer.DrawLine(origin, origin + new float2(width, 0), Color.White, Color.White); Game.Renderer.LineRenderer.DrawLine(origin, origin + new float2(width, 0), Color.White);
Game.Renderer.LineRenderer.DrawLine(origin, origin + new float2(0, -height), Color.White, Color.White); Game.Renderer.LineRenderer.DrawLine(origin, origin + new float2(0, -height), Color.White);
Game.Renderer.LineRenderer.DrawLine(origin + new float2(width, 0), origin + new float2(width, -height), Color.White, Color.White); Game.Renderer.LineRenderer.DrawLine(origin + new float2(width, 0), origin + new float2(width, -height), Color.White);
Game.Renderer.LineRenderer.DrawLine(origin + new float2(0, -height), origin + new float2(width, -height), Color.White, Color.White); Game.Renderer.LineRenderer.DrawLine(origin + new float2(0, -height), origin + new float2(width, -height), Color.White);
} }
public override Widget Clone() public override Widget Clone()

View File

@@ -23,34 +23,26 @@ namespace OpenRA.Mods.Common.Widgets
var origin = new float2(rect.Right, rect.Bottom); var origin = new float2(rect.Right, rect.Bottom);
var basis = new float2(-rect.Width / 100, -rect.Height / 100); var basis = new float2(-rect.Width / 100, -rect.Height / 100);
Game.Renderer.LineRenderer.DrawLine(origin, origin + new float2(100, 0) * basis, Color.White, Color.White); Game.Renderer.LineRenderer.DrawLine(origin, origin + new float2(100, 0) * basis, Color.White);
Game.Renderer.LineRenderer.DrawLine(origin + new float2(100, 0) * basis, origin + new float2(100, 100) * basis, Color.White, Color.White); Game.Renderer.LineRenderer.DrawLine(origin + new float2(100, 0) * basis, origin + new float2(100, 100) * basis, Color.White);
var k = 0; var k = 0;
foreach (var item in PerfHistory.Items.Values) foreach (var item in PerfHistory.Items.Values)
{ {
var n = 0; Game.Renderer.LineRenderer.DrawLineStrip(
item.Samples().Aggregate((a, b) => item.Samples().Select((sample, i) => origin + new float2(i, (float)sample) * basis), item.C);
{
Game.Renderer.LineRenderer.DrawLine(
origin + new float2(n, (float)a) * basis,
origin + new float2(n + 1, (float)b) * basis,
item.C, item.C);
++n;
return b;
});
var u = new float2(rect.Left, rect.Top); var u = new float2(rect.Left, rect.Top);
Game.Renderer.LineRenderer.DrawLine( Game.Renderer.LineRenderer.DrawLine(
u + new float2(10, 10 * k + 5), u + new float2(10, 10 * k + 5),
u + new float2(12, 10 * k + 5), u + new float2(12, 10 * k + 5),
item.C, item.C); item.C);
Game.Renderer.LineRenderer.DrawLine( Game.Renderer.LineRenderer.DrawLine(
u + new float2(10, 10 * k + 4), u + new float2(10, 10 * k + 4),
u + new float2(12, 10 * k + 4), u + new float2(12, 10 * k + 4),
item.C, item.C); item.C);
++k; ++k;
} }

View File

@@ -256,9 +256,9 @@ namespace OpenRA.Mods.Common.Widgets
var pingCell = world.Map.CellContaining(radarPing.Position); var pingCell = world.Map.CellContaining(radarPing.Position);
var points = radarPing.Points(CellToMinimapPixel(pingCell)).ToArray(); var points = radarPing.Points(CellToMinimapPixel(pingCell)).ToArray();
lr.DrawLine(points[0], points[1], c, c); lr.DrawLine(points[0], points[1], c);
lr.DrawLine(points[1], points[2], c, c); lr.DrawLine(points[1], points[2], c);
lr.DrawLine(points[2], points[0], c, c); lr.DrawLine(points[2], points[0], c);
} }
lr.LineWidth = oldWidth; lr.LineWidth = oldWidth;

View File

@@ -92,7 +92,7 @@ namespace OpenRA.Mods.Common.Widgets
top.Y -= 1; top.Y -= 1;
} }
Game.Renderer.LineRenderer.DrawLine(bottom, top, color, color); Game.Renderer.LineRenderer.DrawLine(bottom, top, color);
} }
} }
else else
@@ -122,7 +122,7 @@ namespace OpenRA.Mods.Common.Widgets
right.X -= 1; right.X -= 1;
} }
Game.Renderer.LineRenderer.DrawLine(left, right, color, color); Game.Renderer.LineRenderer.DrawLine(left, right, color);
} }
} }
else else