Drawing.Graphics, poor performance
I am currently working on a C# application that uses Drawing.Graphics to draw to a Bitmap which I display in a picture box. I am rendering a graph with a grid, so I have to draw about 200 grid lines in addition to a number of points onscreen. I can scroll to move around the graph, but while doing so, I notice that my drawing function has poor performance as it stutters. Replacing this approach with OpenTK and its GLControl class makes rendering so efficient that scrolling is very smooth.
Is there any way to get faster performance from Drawing.Graphics?
// This is only done when the window is resized
Bitmap bmp = new Bitmap(picRender.Width, picRender.Height);
Graphics g = Graphics.FromImage(bmp);
// Drawing code
g.Clear(picRender.BackColor);
g.SmoothingMode = System.D开发者_JS百科rawing.Drawing2D.SmoothingMode.HighSpeed;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
if (background != null)
{
g.DrawImage(background, new Rectangle(0, 0, picRender.Width, picRender.Height));
}
for (int n = 0; n < trajectories.Count; n++)
{
Trajectory trajectory = trajectories[n];
Pen pen = new Pen(new SolidBrush(TrajectoryColors[n % TrajectoryColors.Length]));
if (RenderLines)
{
for (int i = 0; i < trajectory.samples.Count - 1; i++)
{
if (Interval_Start > trajectory.samples[i + 1].time ||
Interval_End < trajectory.samples[i].time) { continue; }
g.DrawLine(pen, coordinate_system.ToPoint(trajectory.samples[i].coordinates),
coordinate_system.ToPoint(trajectory.samples[i + 1].coordinates));
}
}
}
// End of drawing
Next to optimizing the drawing code another tactic that can be used is buffering the results.
By not redrawing the entire image each and every time but only update parts that just scrolled into view (or better: are about to scroll into view)
If you need more information we need to see some code to help you profile.
You can turn off anti-aliasing by setting the Graphics.SmoothingMode
property to SmoothingMode.None
.
OpenGL and System.Graphics (GDI+) use differenty kinds of "drawing".
OpenGL uses graphics card, thus redrawing is fast and cheap. System.Graphics in WindowsForms uses GDI+, which is executed by CPU, thus being awfuly slow compared to GPU.
There are many trics to speed up renderin using GDI+. One is to change code to only redraw the part, that has changed/shifted. But keep the rest.
You create a new brush and a new pen for every trajectory, for every frame:
Pen pen = new Pen(new SolidBrush(TrajectoryColors[n % TrajectoryColors.Length]));
Pen
(for sure) and SolidBrush
(eventually) implement IDisposable
- they should be disposed explicitely and, if possible, they should not live on high perf rendering loops. If you need dynamic coloring, you might be able to cache the pens.
Without measuring the timing, I would suspect this could improve your rendering. GDI rendering is usually very fast (opposed to WPF vector graphics) and 200 lines is nothing. Antialiasing performance probably depends on your GPU driver. It just looks so much better that you can't turn it off.
精彩评论