gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 17:49:14 26 4
gpt4 key购买 nike

我正在编写一个粒子引擎并注意到它比它应该的慢得多(我已经编写了高度未优化的 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com