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
using System;
using System.Collections.Generic;
using System.Drawing;
namespace OpenRA.Graphics
@@ -69,10 +70,25 @@ namespace OpenRA.Graphics
{
var tr = new float2(br.X, tl.Y);
var bl = new float2(tl.X, br.Y);
DrawLine(tl, tr, c, c);
DrawLine(tl, bl, c, c);
DrawLine(tr, br, c, c);
DrawLine(bl, br, c, c);
DrawLine(tl, tr, c);
DrawLine(tl, bl, c);
DrawLine(tr, br, 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)
@@ -82,19 +98,52 @@ namespace OpenRA.Graphics
if (nv + 2 > renderer.TempBufferSize)
Flush();
vertices[nv++] = new Vertex(start + Offset,
startColor.R / 255.0f, startColor.G / 255.0f,
startColor.B / 255.0f, startColor.A / 255.0f);
var r = startColor.R / 255.0f;
var g = startColor.G / 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,
endColor.R / 255.0f, endColor.G / 255.0f,
endColor.B / 255.0f, endColor.A / 255.0f);
r = endColor.R / 255.0f;
g = endColor.G / 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)
{
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)
@@ -106,7 +155,7 @@ namespace OpenRA.Graphics
for (var y = r.Top; y <= r.Bottom; y++)
{
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 wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(start + p, end + p, c, c);
wlr.DrawLine(start + q, end + q, c2, c2);
wlr.DrawLine(start + r, end + r, c, c);
wlr.DrawLine(start + p, end + p, c);
wlr.DrawLine(start + q, end + q, c2);
wlr.DrawLine(start + r, end + r, c);
wlr.DrawLine(start + p, z + p, barColor2, barColor2);
wlr.DrawLine(start + q, z + q, barColor, barColor);
wlr.DrawLine(start + r, z + r, barColor2, barColor2);
wlr.DrawLine(start + p, z + p, barColor2);
wlr.DrawLine(start + q, z + q, barColor);
wlr.DrawLine(start + r, z + r, barColor2);
}
Color GetHealthColor(Health health)
@@ -125,13 +125,13 @@ namespace OpenRA.Graphics
var z = float2.Lerp(start, end, (float)health.HP / health.MaxHP);
var wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(start + p, end + p, c, c);
wlr.DrawLine(start + q, end + q, c2, c2);
wlr.DrawLine(start + r, end + r, c, c);
wlr.DrawLine(start + p, end + p, c);
wlr.DrawLine(start + q, end + q, c2);
wlr.DrawLine(start + r, end + r, c);
wlr.DrawLine(start + p, z + p, healthColor2, healthColor2);
wlr.DrawLine(start + q, z + q, healthColor, healthColor);
wlr.DrawLine(start + r, z + r, healthColor2, healthColor2);
wlr.DrawLine(start + p, z + p, healthColor2);
wlr.DrawLine(start + q, z + q, healthColor);
wlr.DrawLine(start + r, z + r, healthColor2);
if (health.DisplayHp != health.HP)
{
@@ -143,9 +143,9 @@ namespace OpenRA.Graphics
deltaColor.B / 2);
var zz = float2.Lerp(start, end, (float)health.DisplayHp / health.MaxHP);
wlr.DrawLine(z + p, zz + p, deltaColor2, deltaColor2);
wlr.DrawLine(z + q, zz + q, deltaColor, deltaColor);
wlr.DrawLine(z + r, zz + r, deltaColor2, deltaColor2);
wlr.DrawLine(z + p, zz + p, deltaColor2);
wlr.DrawLine(z + q, zz + q, deltaColor);
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 wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(tl + u, tl, color, color);
wlr.DrawLine(tl, tl + v, color, color);
wlr.DrawLine(tr, tr - u, color, color);
wlr.DrawLine(tr, tr + v, color, color);
wlr.DrawLine(tl + u, tl, color);
wlr.DrawLine(tl, tl + v, color);
wlr.DrawLine(tr, tr - u, color);
wlr.DrawLine(tr, tr + v, color);
wlr.DrawLine(bl, bl + u, color, color);
wlr.DrawLine(bl, bl - v, color, color);
wlr.DrawLine(br, br - u, color, color);
wlr.DrawLine(br, br - v, color, color);
wlr.DrawLine(bl, bl + u, color);
wlr.DrawLine(bl, bl - v, color);
wlr.DrawLine(br, br - u, color);
wlr.DrawLine(br, br - v, color);
}
public void RenderDebugGeometry(WorldRenderer wr) { }

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Graphics
var a = first;
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);
a = b;
}

View File

@@ -202,7 +202,7 @@ namespace OpenRA.Graphics
{
var pa = pos + offset.Rotate(WRot.FromFacing(8 * i));
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 wlr = Game.Renderer.WorldLineRenderer;
wlr.DrawLine(location + tl, location + tr, c, c);
wlr.DrawLine(location + tr, location + br, c, c);
wlr.DrawLine(location + br, location + bl, c, c);
wlr.DrawLine(location + bl, location + tl, c, c);
wlr.DrawLine(location + tl, location + tr, c);
wlr.DrawLine(location + tr, location + br, c);
wlr.DrawLine(location + br, location + bl, c);
wlr.DrawLine(location + bl, location + tl, c);
}
public void RefreshPalette()

View File

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

View File

@@ -135,10 +135,10 @@ namespace OpenRA.Mods.Common.Graphics
// Draw transformed shadow sprite rect
var c = Color.Purple;
var psb = renderProxy.ProjectedShadowBounds;
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[1], shadowOrigin + psb[3], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[3], shadowOrigin + psb[0], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[0], shadowOrigin + psb[2], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[2], shadowOrigin + psb[1], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[1], shadowOrigin + psb[3], c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[3], shadowOrigin + psb[0], c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[0], shadowOrigin + psb[2], c);
Game.Renderer.WorldLineRenderer.DrawLine(shadowOrigin + psb[2], shadowOrigin + psb[1], c);
// Draw voxel bounding box
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]);
}
Game.Renderer.WorldLineRenderer.DrawLine(corners[0], corners[1], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[1], corners[3], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[3], corners[2], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[2], corners[0], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[0], corners[1], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[1], corners[3], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[3], corners[2], 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[5], corners[7], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[7], corners[6], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[6], corners[4], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[4], corners[5], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[5], corners[7], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[7], corners[6], 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[1], corners[5], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[2], corners[6], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[3], corners[7], c, c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[0], corners[4], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[1], corners[5], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[2], corners[6], c);
Game.Renderer.WorldLineRenderer.DrawLine(corners[3], corners[7], c);
}
public Rectangle ScreenBounds(WorldRenderer wr)

View File

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

View File

@@ -118,21 +118,18 @@ namespace OpenRA.Mods.Common.Widgets
if (points.Any())
{
points = points.Reverse().Take(xAxisSize).Reverse();
var scaledData = points.Select(d => d * scale);
var x = 0;
scaledData.Aggregate((a, b) =>
{
Game.Renderer.LineRenderer.DrawLine(
origin + new float2(x, -a),
origin + new float2(x + xStep, -b),
color, color);
x += xStep;
return b;
});
var lastX = 0;
var lastPoint = 0f;
Game.Renderer.LineRenderer.DrawLineStrip(
points.Select((point, x) =>
{
lastX = x;
lastPoint = point;
return origin + new float2(x * xStep, -point * scale);
}), color);
var value = points.Last();
if (value != 0)
tiny.DrawText(GetValueFormat().F(value), origin + new float2(x, -value * scale - 2), color);
if (lastPoint != 0f)
tiny.DrawText(GetValueFormat().F(lastPoint), origin + new float2(lastX * xStep, -lastPoint * scale - 2), 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
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);
}
@@ -151,16 +148,16 @@ namespace OpenRA.Mods.Common.Widgets
for (var y = GetDisplayFirstYAxisValue() ? 0 : yStep; y <= height; y += yStep)
{
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);
}
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(0, -height), Color.White, 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(0, -height), origin + new float2(width, -height), 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);
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);
}
public override Widget Clone()

View File

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

View File

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

View File

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