SRL Archive - C/C++ Help and Tutorials

C# Need super fast bitmap drawing


Phoenix13nl

2009-04-12 09:52:56

Hi, I've got a bit of a problem here. I'm creating a engine for 2D games (Without Xna or DirectX or anything like that).

After some testing I found that the best update interval was 17ms, it gave only 5% CPU usage, and a framerate of 32FPS, the max FPS was 62, but CPU usage was 100% then. the interval seems very sensitive though, just by changing it with 1ms can make up to 80% difference on the CPU, so I might need to make it auto-adjustable in some way, but that's not the problem why I'm here.

Now to display everything on the screen, im using two Graphics objects and a bitmap, in the Draw call of my engine, everything will be draw the Graphics object of the bitmap, after the drawing is done, I draw the bitmap onto the other Graphics object, which is the Graphics object of my viewport.

All of this drawing however, is done by using the Graphics.DrawImage and Graphics.DrawImageUnscaled methods. knowing the most GDI methods are slow, I'm asking, is there any faster way of drawing bitmaps, or displaying just a color onto the screen? On the internet I found that alot of people are using the GDI32 BitBlt function, when i tried this, it took 15ms, while GDI took under 1ms, I also found something about (double)BufferedGraphics, but it seemed to me that it was only used to prevent 'flickering', which I already did, and in some cases it looks like BitBlt is used for that too. Are there any faster ways???

Another problem I have, is that I want to be able to change the bitmap's color, I tried with a loop trough the bitmaps ColorPalette, but that doesnt work, and even though I can use the unmanaged way for bitmap GetPixel and SetPixel I prefer not doing so, as that has to be done for any pixel for any texture I want to draw. Anyone has a solution or should I just try my GetPixel and SetPixel functions? (Im not talking about my own methods, not the slow GDI ones).

oh, and just to show of, I also included some pixtures rendered by my Ray-Tracer im creating, the plan is to make it real-time but I guess I'll never manage :) I can rotate, scale(Not with Quaternion), and translate(Not with Matrix3 or Quaternion) the cube, and all other triangle-based primitives with my Matrix3, Matrix4, Quaternion and Vector3 classes, pretty cool xD

btw, they're in a .Zip because of the size, though I resized the're format, changing the ImageFormat f*cks up the images,

boberman

2009-04-12 10:50:47

The only GDI methods that are slow are SetPixel and GetPixel. The rest are pretty good for speed.

Without using DirectX, it is pretty hard to make a fast video render. Your essentially taking the video card out of the calculation loop by excluding DirectX.

I would suggest making all changes that you need to the image before calling the drawimage/bltblt function. Modifying memory is fast, where you see the slowdown is in the transfer of that memory to the video card. By limiting the number of transfers you should be able to obtain higher speeds.

Barring that, check out you algorithm, see if there are inefficiencies that can be removed. Consider using a lower level language (C++) as C# is an interpreted language.

Phoenix13nl

2009-04-12 12:13:55

From: boberman
The only GDI methods that are slow are SetPixel and GetPixel. The rest are pretty good for speed.

Without using DirectX, it is pretty hard to make a fast video render. Your essentially taking the video card out of the calculation loop by excluding DirectX.

I would suggest making all changes that you need to the image before calling the drawimage/bltblt function. Modifying memory is fast, where you see the slowdown is in the transfer of that memory to the video card. By limiting the number of transfers you should be able to obtain higher speeds.

Barring that, check out you algorithm, see if there are inefficiencies that can be removed. Consider using a lower level language (C++) as C# is an interpreted language.


Thank you for the fast reply!

On the internet I see everyone complaining that GDI is slow, but after alot of testing I found out myself that it has a good speed indeed. (Except for Get- and SetPixel, but there are faster ways to do that.)

My algoritme is about as fast as i could get it, I've already seen the importance of good algorithmes in my Ray-Tracer, just by improving a single algorimthe of only ~20 lines, It rendered about 0.5 seconds faster per triangle.

Though I know using C++ would be faster, I prefer not to use it, I simply like C# alot better.

I guess learning Multi-threaded and Parallel Programming would help me some further. The reason im not using DirectX is because I'm just doing this to learn myself new things :)

Btw, here is my FPS testing data, pretty intresting to see what difference 1ms can make… :S

FPS CPU Timer Interval(ms)
62 90% 1
62 90% 10
62 90% 15
40 16% 16
32 5% 17
31 10% 18
31 17% 20
31 17% 25
31 45% 30
21 11% 35
20 20% 40
12 15% 50
9 8% 100

Edit: Currently reading a good tutorial on Multi-threaded Asynchronous Programming in C#, Maybe that well give me the knowledge to improve some things :)

Another edit:
I implented some Async Multi-Threading, and I must say, the results shocked me, When drawing alot of stuf without threading, I got only 7FPS, with threading I got 31FPS, the only downside is the my CPU usage shoots up to 100%, which I was trying to avoid, so I could just try to get my FPS as high as possible because the CPU will reach eventualy reach 100% when alot of stuff is drawn.

Edited again:
It's updated 31 times a second now, but it's still only drawn 9 times a second. Well.. it's an improvement. I guess it would make more of a difference at multi-core computers.

Once more edited:
I found the source of my extreme slow drawing, I put in some integers to count the time, and found that resizing the texture took 16ms, while the rest (copying, rotating, drawing) took under 1ms… so I guess once that's fixed I can have a pretty good framerate xD

Another edit xD:
hmm, this is extremely weird, I tested it some more, and it seems sometimes rotating takes 16ms, other times copying does, and some times resizing does, while the other things that just went slow suddenly take under 1ms…. weird :S:S

Another edit again:
Ok, though the time is random per texture, the totaltime is about the same each time:
Init:298 | Copy:782 | Rotate:2591 | Resize:3483 | Draw:1887
*with init I mean: Bitmap b = new Bitmap(width, height);

ShowerThoughts

2009-04-25 23:09:47

Hmm, use OpenGL I got some tuts on it. or DirectX

Phoenix13nl

2009-04-26 01:41:02

From: Hermpie
Hmm, use OpenGL I got some tuts on it. or DirectX


Well, the whole purpose of what I did was to try to avoid those xD but I now realize if I want something real-time I need my GPU, So I stopped working on this, It was fun anyway.

(I did achieve real-time, over 60FP with 3 300x300 textures, but once you're rotating/scaling the textures the framerate drops drammaticaly)

My goal was to write some kind of game engine, but I think of anything because Direct3D and XNA already offer everything you need.

So I'm creating a new ray-tracer now, once that is done I'll start games again with XNA and DirectX.

Wizzup?

2009-04-26 17:24:05

From: Phoenix13nl
Well, the whole purpose of what I did was to try to avoid those xD but I now realize if I want something real-time I need my GPU, So I stopped working on this, It was fun anyway.

(I did achieve real-time, over 60FP with 3 300x300 textures, but once you're rotating/scaling the textures the framerate drops drammaticaly)

My goal was to write some kind of game engine, but I think of anything because Direct3D and XNA already offer everything you need.

So I'm creating a new ray-tracer now, once that is done I'll start games again with XNA and DirectX.


I'd recommend OpenGL rather than DirectX. DirectX is not portable to other operating systems. I also prefer GLSL.

Phoenix13nl

2009-04-27 11:21:59

From: Wizzup?
I'd recommend OpenGL rather than DirectX. DirectX is not portable to other operating systems. I also prefer GLSL.


Ok, I'll remember that, thanks!

ShowerThoughts

2009-04-27 13:02:10

DirectX = MS only = fail monopoly.

Freddy1990

2009-04-27 23:40:06

Try SDL