当前位置:  开发笔记 > 编程语言 > 正文

Graphics.Transform非常低效,我该怎么办呢?

如何解决《Graphics.Transform非常低效,我该怎么办呢?》经验,为你挑选了1个好方法。

我正在编写一个粒子引擎,并注意到它的速度比应有的慢得多(我编写的高度未经优化的3D C++粒子引擎能够以60 fps渲染50k粒子,这一粒子在1.2k左右下降到32 fps. .),我对代码做了一些分析,假设渲染粒子或旋转是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 class calls是使用最大的cpu功率.无论如何,任何帮助都会在尝试优化这一点时非常感激...也许我只是启用/禁用旋转来提高性能,我们会看到......



1> Hans Passant..:

好吧,您应该在看到的配置文件结果上花些时间。分配Transform属性时,还有其他事情发生。您可以通过注意到ResetTransform()不花费任何费用来推断出某些原因。当然没有意义,该方法还会更改Transform属性。

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

我认为您在这里看到的是GDI / plus的晦涩功能,它会批量绘制绘图命令。换句话说,它在内部生成绘制命令的列表,并且直到需要时才将其传递给视频驱动程序。本机winapi具有显式强制刷新该列表的功能,它是 GdiFlush()。但是,.NET Graphics类未公开该内容,它是自动完成的。

因此,一个颇具吸引力的理论是,当您分配Transform属性时,GDI +内部调用GdiFlush()。所以您看到的成本是的成本实际上是先前DrawRectangle()调用的成本。

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

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

推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有