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。正如我上面提到的,一个核心原则是您必须立即创建您的资源,然后在您的绘图例程中重复使用它们。

关于您的内存泄漏...您的代码示例没有提供足够的信息,但很可能您没有释放正在创建的资源(即 PathGeometrySolidColorBrush 和那些我们看不到的)。

最简单的建议是 - 仅将渲染循环用于 rendering/drawing 并重用资源而不是重新创建它们。

Improving the performance of Direct2D apps