经过一些研究,似乎有两种方法:
1. GDI +路线,其中将图形绘制到WriteableBitmap或InteropBitmap中。 2. SlimDX或DirectX变体(托管在D3DImage中)
考虑以下因素,哪种方法最好:
1. 即使查看整个图表,与图表的交互也必须快速。 2. 更新视觉效果应该很快(颜色或大小更改)。 3. 命中测试必须快速(点和矩形)。 4. 必须及时完成开发。
你会选择哪种方法?为什么?
编辑:
看起来有一个相似的问题被提出了,但没有得到回答。
我在我的制图应用程序中使用了GDI。虽然GDI+比DirectX等其他引擎速度慢,但我发现有很多技巧和方法可以用来加速。在绘制数据之前,大量CPU用于准备数据本身,因此GDI不应该是唯一的瓶颈。
需要注意的事项(这些内容足够通用,适用于其他图形引擎):
首先:进行度量。使用分析器查看代码中真正的瓶颈在哪里。 重用GDI原语。这非常重要。如果您必须绘制100,000个外观相同或相似的图形对象,请使用相同的Pen
,Brush
等。创建这些原语是昂贵的。
缓存渲染数据 - 例如:如果您不需要重新计算gfx元素位置,则不要重新计算。
在平移/缩放时,使用较低的GDI+质量(并且不使用昂贵的GDI操作)绘制场景。有许多Graphics
对象设置可以降低质量。用户停止平移后,再以高质量绘制场景。
还有很多小细节可以提高性能。我已经开发了这个应用程序2-3年了(或者已经4年了?),现在我仍然找到改进事物的方法:)。这就是为什么度量很重要 - 代码会改变,这会影响性能,因此您需要对新代码进行度量。
另外一件事:我没有使用过SlimDX,但我尝试了Direct2D(我指的是Microsoft.WindowsAPICodePack.DirectX.Direct2D1
)。在我的情况下,性能比GDI+快得多,但是我在渲染位图方面遇到了一些问题,从未有时间找到正确的解决方案。
最近我将一些绘图代码移植到了DirectX上,并对结果感到非常满意。我们主要使用位操作渲染位图,而现在的渲染时间可以缩短到1-2秒,而之前渲染时间可能需要数分钟。
虽然我们是从C++中的位操作转移到了C#中的SlimDX Direct3D,因此不能直接与您的用法进行比较,但我相信您也会看到性能提升,即使它们并不像我们看到的那样成倍增长。
我建议您尝试使用SlimDX的Direct2D。由于某些原因,您需要使用DirectX 10.1,因为Direct2D与DirectX 11不兼容。如果您已经使用过WPF的绘图API,则应该已经熟悉Direct2D,因为其API基于WPF绘图API。Direct2D的主要问题是缺乏文档,并且仅适用于Vista及以后版本。
我没有尝试过DirectX 10/WPF互操作,但我认为这是可能的(https://dev59.com/2UjSa4cB1Zd3GeqPItAx
编辑:我想给您一个比较,来自我们绘制简单多边形的代码。首先是WPF版本:
StreamGeometry geometry = new StreamGeometry();
using (StreamGeometryContext ctx = geometry.Open())
{
foreach (Polygon polygon in mask.Polygons)
{
bool first = true;
foreach (Vector2 p in polygon.Points)
{
Point point = new Point(p.X, p.Y);
if (first)
{
ctx.BeginFigure(point, true, true);
first = false;
}
else
{
ctx.LineTo(point, false, false);
}
}
}
}
Texture2D maskTexture = helper.CreateRenderTexture(width, height);
RenderTargetProperties props = new RenderTargetProperties
{
HorizontalDpi = 96,
PixelFormat = new PixelFormat(SlimDX.DXGI.Format.Unknown, AlphaMode.Premultiplied),
Type = RenderTargetType.Default,
Usage = RenderTargetUsage.None,
VerticalDpi = 96,
};
using (SlimDX.Direct2D.Factory factory = new SlimDX.Direct2D.Factory())
using (SlimDX.DXGI.Surface surface = maskTexture.AsSurface())
using (RenderTarget target = RenderTarget.FromDXGI(factory, surface, props))
using (SlimDX.Direct2D.Brush brush = new SolidColorBrush(target, new SlimDX.Color4(System.Drawing.Color.Red)))
using (PathGeometry geometry = new PathGeometry(factory))
using (SimplifiedGeometrySink sink = geometry.Open())
{
foreach (Polygon polygon in mask.Polygons)
{
PointF[] points = new PointF[polygon.Points.Count()];
int i = 0;
foreach (Vector2 p in polygon.Points)
{
points[i++] = new PointF(p.X * width, p.Y * height);
}
sink.BeginFigure(points[0], FigureBegin.Filled);
sink.AddLines(points);
sink.EndFigure(FigureEnd.Closed);
}
sink.Close();
target.BeginDraw();
target.FillGeometry(geometry, brush);
target.EndDraw();
}
正如您所看到的,Direct2D版本需要稍微多做一些工作(并且依赖于我编写的几个帮助函数),但实际上它非常相似。
让我试着列出每种方法的优缺点,这或许能帮助你决定使用哪种方法。
GDI 优点
GDI 缺点
SlimDX 优点
SlimDX 缺点
也许还有更多我忘记放在这里的内容,但这些或许已经足够了吧?
-A.