Direct2D 绘图方法/性能
Direct2D plot approach / performance
使用 Direct2D (Sharpdx) 绘制复杂图形的方法如何?
实际上我正在使用 WindowsRenderTarget,将其与 Direct2D1.Factory 连接并绘制到 RenderControl。
Factory2D = new SharpDX.Direct2D1.Factory(FactoryType.MultiThreaded);
FactoryWrite = new SharpDX.DirectWrite.Factory();
var properties = new HwndRenderTargetProperties();
properties.Hwnd = this.Handle;
properties.PixelSize = new Size2(this.ClientSize.Width, this.ClientSize.Height);
properties.PresentOptions = PresentOptions.RetainContents;
RenderTarget2D = new WindowRenderTarget(Factory2D, new RenderTargetProperties(new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)), properties);
RenderTarget2D.AntialiasMode = AntialiasMode.PerPrimitive;
绘图是在窗体的 Paint 事件中完成的:
RenderTarget2D.BeginDraw();
RenderTarget2D.Clear(Color4.Black);
drawProgress(); // Doing Paintings like DrawLine, Multiple PathGeometrys, DrawEllipse and DrawText
RenderTarget2d.EndDraw();
在 MouseMove/MouseWheel 事件中,绘图将被重新计算(用于缩放或计算将要显示的元素)。这个过程大约需要 8-10ms。
下一步其实是
this.Refresh();
这里估计是问题所在,这个进度最多需要140ms。
所以剧情的scaling/moving大概是7fps.
而且刷新控件时程序占用内存越来越多
////编辑
画线:
private void drawLines(Pen pen, PointF[] drawElements)
{
SolidColorBrush tempBrush = new SolidColorBrush(RenderTarget2D, SharpDX.Color.FromRgba(pen.Color.ToArgb()));
int countDrawing = (drawElements.Length / 2) + drawElements.Length % 2;
for (int i = 0; i < countDrawing; i++)
{
drawLine(new Vector2(drawElements[i].X, drawElements[i].Y), new Vector2(drawElements[i + 1].X, drawElements[i + 1].Y), brushWhite);
}
}
绘画几何:
RenderTarget2D.DrawGeometry(graphicPathToPathGeometry(p), penToSolidColorBrush(pen));
private PathGeometry graphicPathToPathGeometry(GraphicsPath path)
{
geometry = new PathGeometry(Factory2D);
sink = geometry.Open();
if (path.PointCount > 0)
{
sink.BeginFigure(new Vector2(path.PathPoints[path.PointCount - 1].X, path.PathPoints[path.PointCount - 1].Y), FigureBegin.Hollow);
sink.AddLines(pointFToVector2(path.PathPoints));
sink.EndFigure(new FigureEnd());
sink.Close();
}
return geometry;
}
在鼠标移动中,将通过构建 Cursor.Position.X/Y old 和 Cursor.Position.X/Y new 之间的差异来重新计算绘图。所以这些行会经常重新计算:)
问题的一部分是:
SolidColorBrush tempBrush = new SolidColorBrush(RenderTarget2D, SharpDX.Color.FromRgba(pen.Color.ToArgb()));
在渲染循环中创建任何类型的对象都会导致应用程序内存不足。绘制现有值是可行的方法。
估计性能问题也会基于这个问题
主要瓶颈是您的 graphicPathToPathGeometry()
功能。您正在渲染循环中创建 "filling" 一个 PathGeometry
。正如我上面提到的,一个核心原则是您必须立即创建您的资源,然后在您的绘图例程中重复使用它们。
关于您的内存泄漏...您的代码示例没有提供足够的信息,但很可能您没有释放正在创建的资源(即 PathGeometry
、SolidColorBrush
和那些我们看不到的)。
最简单的建议是 - 仅将渲染循环用于 rendering/drawing 并重用资源而不是重新创建它们。
使用 Direct2D (Sharpdx) 绘制复杂图形的方法如何?
实际上我正在使用 WindowsRenderTarget,将其与 Direct2D1.Factory 连接并绘制到 RenderControl。
Factory2D = new SharpDX.Direct2D1.Factory(FactoryType.MultiThreaded);
FactoryWrite = new SharpDX.DirectWrite.Factory();
var properties = new HwndRenderTargetProperties();
properties.Hwnd = this.Handle;
properties.PixelSize = new Size2(this.ClientSize.Width, this.ClientSize.Height);
properties.PresentOptions = PresentOptions.RetainContents;
RenderTarget2D = new WindowRenderTarget(Factory2D, new RenderTargetProperties(new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)), properties);
RenderTarget2D.AntialiasMode = AntialiasMode.PerPrimitive;
绘图是在窗体的 Paint 事件中完成的:
RenderTarget2D.BeginDraw();
RenderTarget2D.Clear(Color4.Black);
drawProgress(); // Doing Paintings like DrawLine, Multiple PathGeometrys, DrawEllipse and DrawText
RenderTarget2d.EndDraw();
在 MouseMove/MouseWheel 事件中,绘图将被重新计算(用于缩放或计算将要显示的元素)。这个过程大约需要 8-10ms。 下一步其实是
this.Refresh();
这里估计是问题所在,这个进度最多需要140ms。
所以剧情的scaling/moving大概是7fps.
而且刷新控件时程序占用内存越来越多
////编辑
画线:
private void drawLines(Pen pen, PointF[] drawElements)
{
SolidColorBrush tempBrush = new SolidColorBrush(RenderTarget2D, SharpDX.Color.FromRgba(pen.Color.ToArgb()));
int countDrawing = (drawElements.Length / 2) + drawElements.Length % 2;
for (int i = 0; i < countDrawing; i++)
{
drawLine(new Vector2(drawElements[i].X, drawElements[i].Y), new Vector2(drawElements[i + 1].X, drawElements[i + 1].Y), brushWhite);
}
}
绘画几何:
RenderTarget2D.DrawGeometry(graphicPathToPathGeometry(p), penToSolidColorBrush(pen));
private PathGeometry graphicPathToPathGeometry(GraphicsPath path)
{
geometry = new PathGeometry(Factory2D);
sink = geometry.Open();
if (path.PointCount > 0)
{
sink.BeginFigure(new Vector2(path.PathPoints[path.PointCount - 1].X, path.PathPoints[path.PointCount - 1].Y), FigureBegin.Hollow);
sink.AddLines(pointFToVector2(path.PathPoints));
sink.EndFigure(new FigureEnd());
sink.Close();
}
return geometry;
}
在鼠标移动中,将通过构建 Cursor.Position.X/Y old 和 Cursor.Position.X/Y new 之间的差异来重新计算绘图。所以这些行会经常重新计算:)
问题的一部分是:
SolidColorBrush tempBrush = new SolidColorBrush(RenderTarget2D, SharpDX.Color.FromRgba(pen.Color.ToArgb()));
在渲染循环中创建任何类型的对象都会导致应用程序内存不足。绘制现有值是可行的方法。
估计性能问题也会基于这个问题
主要瓶颈是您的 graphicPathToPathGeometry()
功能。您正在渲染循环中创建 "filling" 一个 PathGeometry
。正如我上面提到的,一个核心原则是您必须立即创建您的资源,然后在您的绘图例程中重复使用它们。
关于您的内存泄漏...您的代码示例没有提供足够的信息,但很可能您没有释放正在创建的资源(即 PathGeometry
、SolidColorBrush
和那些我们看不到的)。
最简单的建议是 - 仅将渲染循环用于 rendering/drawing 并重用资源而不是重新创建它们。