c# - Graphics.Transform 效率极低,我该怎么办?

标签 c# winforms performance graphics

我正在编写一个粒子引擎并注意到它比它应该的慢得多(我已经编写了高度未优化的 3D C++ 粒子引擎,可以以 60 fps 渲染 50k 粒子,这个下降到 32 fps 大约1.2k ..),我对代码进行了一些分析,假设粒子渲染或旋转是 CPU 最密集的操作,但我发现实际上图形对象的这两个小属性实际上占用了 70% 以上我的表现....

    public void RotateParticle(Graphics g, RectangleF r, 
                                RectangleF rShadow, float angle, 
                                Pen particleColor, Pen particleShadow)
    {
        //Create a matrix
        Matrix m = new Matrix();
        PointF shadowPoint = new PointF(rShadow.Left + (rShadow.Width / 1),
                                        rShadow.Top + (rShadow.Height / 1));
        PointF particlePoint = new PointF(r.Left + (r.Width / 1),
                                          r.Top + (r.Height / 2));
        //Angle of the shadow gets set to the angle of the particle, 
        //that way we can rotate them at the same rate
        float shadowAngle = angle;                
        m.RotateAt(shadowAngle, shadowPoint);

        g.Transform = m;

        //rotate and draw the shadow of the Particle
        g.DrawRectangle(particleShadow, rShadow.X, rShadow.Y, rShadow.Width, rShadow.Height);

        //Reset the matrix for the next draw and dispose of the first matrix
        //NOTE: Using one matrix for both the shadow and the partice causes one 
        //to rotate at half the speed of the other.
        g.ResetTransform();
        m.Dispose();

        //Same stuff as before but for the actual particle
        Matrix m2 = new Matrix();
        m2.RotateAt(angle, particlePoint);

        //Set the current draw location to the rotated matrix point
        //and draw the Particle
        g.Transform = m2;

        g.DrawRectangle(particleColor, r.X, r.Y, r.Width, r.Height);
        m2.Dispose();
    }

阻碍我表现的特别是这些行:

g.Transform = m;
g.Transform = m2;

一点背景知识,图形对象是从 painteventargs 中获取的,然后在渲染粒子方法中将粒子渲染到屏幕上,该方法调用此方法进行任何旋转,多线程不是解决方案,因为图形对象不能在多个线程之间共享。这是我运行的代码分析的链接,您也可以看到发生了什么:

https://gyazo.com/229cfad93b5b0e95891eccfbfd056020

我有点认为这是无能为力的事情,因为看起来属性本身正在破坏性能,而不是我实际做过的任何事情(尽管我确信还有改进的余地),尤其是因为类调用的 dll 使用最多的 cpu 能力。无论如何,在尝试优化此方面的任何帮助将不胜感激...也许我会启用/禁用旋转以提高性能,我们会看到...

最佳答案

好吧,您应该为看到的配置文件结果挠头一会儿。当您分配 Transform 属性时,else 发生了一些事情。您可以通过注意到 ResetTransform() 不花费任何费用来推断出一些事情。当然没有意义,该方法还会更改 Transform 属性。

请注意,DrawRectangle() 应该是最昂贵的方法,因为这是实际将踏板踩到金属上并生成真实绘图命令的方法。我们无法从您的屏幕截图中看到它的成本,不能超过 30%。这还远远不够。

我认为您在这里看到的是 GDI/plus 的一个不起眼的功能,它批处理 绘图命令。换句话说,它在内部生成一个绘图命令列表,并且在必要时才将它们传递给视频驱动程序。 native winapi 具有明确强制刷新该列表的函数,它是 GdiFlush() .然而,.NET Graphics 类并没有公开它,它是自动完成的。

一个非常有吸引力的理论是,当您分配 Transform 属性时,GDI+ 在内部调用 GdiFlush()。因此,您看到的成本实际上是之前 DrawRectangle() 调用的成本。

您需要通过为其提供更多批处理机会来取得成功。非常喜欢让您绘制大量项目的 Graphics 类方法。换句话说,不要绘制每个单独的粒子,而是绘制许多粒子。您会喜欢 DrawRectangles()、DrawLines()、DrawPath()。不幸的是,没有 DrawPolygons(),您真正喜欢的那个,从技术上讲,您可以调用 PolyPolygon(),但这很难开始。

如果我的理论不正确,请注意您不需要 Graphics.Transform。您还可以使用 Matrix.TransformPoints() 和 Graphics.DrawPolygon()。能否真正领先还有些疑问,Graphics 类不直接使用 GPU 加速,因此它永远无法与 DirectX 竞争。

关于c# - Graphics.Transform 效率极低,我该怎么办?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34430786/

相关文章:

c# - MVC2 和 session

c# - 绑定(bind)在没有 INotifyPropertyChanged 的​​情况下工作,为什么?

c# - 在 Web API 中 Controller 初始化之前执行一些操作(设置语言)

c# - 在视觉继承的情况下,事件处理的标准方法是什么?

javascript - JavaScript 中 function() 和 () => 有什么区别

performance - 某些通用寄存器是否比其他寄存器更快?

c# - 这也太……hacky了吧? XML 到一个对象

.net - 如何在 .NET 单选按钮中获取 DoubleClick 事件?

c# - 在 Gecko 浏览器中渲染 html

JAVA:循环内定义的引用