Milliseconds is not good enoughFiled Under: Weekly Tuesday Dose of goodness
Hi all, as promised, I’ll try to write an article by today. I’m currently waiting for my flight back to SG at KL, LCC-T; going to board the plane soon, therefore I’m trying to sneak in a little post for this week.
Many people in Windows programming uses GetTickCount() as the function to retrieve the number of milliseconds passed since the computer has started.
While this is mostly useful enough to measure the time differences between 2 moments, it might not be good enough for a finely-tuned engine fraction of movement.
Why is it so? Read on….
Most engines nowaday use at least 2 loop calls to handle rendering and logic processing separately. This is to reduce the amount of unnecessary logic processing done while the graphics are being rendered nicely. More importantly, it allows rendering to skip frames if required.
Logic processing usually takes about 10-20 milliseconds for a full-fledged engine, which roughly equates to 50 frames per second. This can be fixed to ensure a more or less normalized logic processing.
However, for rendering, it’s not always the case. To allow a graphics engine to render more than 200 frames per second, you must realise a few things:
1) This kind of frame rate is not always possible
2) To render 100 fps, the delay time is 10 milliseconds.
3) To render 200 fps, the delay time is at most 5 milliseconds.
4) How about the potential 300 frames per second? 2.5 millisecond? I don’t think so.
Even rendering at 300 frames per second, without a few smaller sub-systems to control the rendering, your graphics, movement and animation will still remain strobby and jerky.
To be able to do this, first you’ll need to revamp your rendering loop to take in a factor. This factor is measured against a maximum 1.0f which is also tied to logic-processing frames per second.
For example, if my logical processing time is 20 milliseconds, which calculates to 50 frames per second, my 1.0f would be 20 milliseconds.
If I manage to render a single frame within 2 millisecond, then instead of using 1.0f, I’ll pass in 0.1f instead. This would mean that the internal calculations of the engine for rendering is divided by 10 times. So, for an object moving at 5 pixels per logical frame, it’ll now move 0.5 pixels per render frame.
Another thing to note, this is not possible with typical 2D renderers like DirectDraw. It’s possible to have very silky smooth rendering as long as vector/floating pointer graphics is supported by the rendering API.
So since I can afford to render a factor of 0.1f per frame, and logical processing is 50 fps, we’re talking abt rendering a whooping 500 frames per second while your logic is being processed 50 times.
This certainly means that your graphics be silky smooth!
Next, to be able to even measure the small difference for factors, time is no longer used. Instead, delay between frames is used instead.
To achieve this, you’ll need a High Performance Counter. The golden technique is as goes:
1) You measure the difference of the high performance counter which is usually a 64-bit integer.
2) The first measurement is taken between 1 second without ANY rendering or processing.
3) That 1 second can be achieved by using Sleep(1000) or GetTickCount() methodology.
4) You’ll probably get a relatively large number, say a few millions or hundreds of thousands. Let’s assume it to be 4,565,256.
5) This would be used as THE reference delay for 1 single second. Divide this number by logical frames per second. So it’ll be 4565256/50 = 91,305.12 ~ 91,305.
6) This number will be the total delay your rendering can afford per second.
7) Now begin your rendering and logical processing loop
8 ) Measure the high performance delay between the last rendering cycle and current rendering cycle.
9) The first render call should always be 1.0f factor.
10) Subsequent render factors are calculated based on the difference. Let’s assume the difference to be 12512
11) Factor of rendering = 1251 / 91,305 = 0.1370352
12) This means 0.137 factor out of 50 frames per second.
13) That also means in the space between 20 milliseconds, you can render 7.2 frames
14) Which in the end means, you can render up to 145 frames per second.
GET the technique?
So, let’s summarize what you really need for a silky rendering performance.
1) Vector-graphics/Floating-point graphics rendering API (such as Direct3D and OpenGL)
2) High Performance Counter (64-bit, system dependent though =( )
3) Graphic rendering process to take in rendering in factors, strain on the calculations to multiply a factor but gives a great boost frame quality
4) Code the above given technique
I hope this has been an informative session for you! Good Luck!
Regards,
Jeremy
- Permalink
- Admin
- 10 Apr 2009 8:51 PM
- Comments (0)