🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

More about framerates

Started by
8 comments, last by Asdas 24 years, 5 months ago
When I read TOOM''s thread about the framerates achieved by his engine i was amazed. I havnt yet tested the framerate of my engine, but it is definitely less than 30fps, while running in 800x600x16. This was when it was rendering a screen of 64x32 iso tiles. In comparison, running TOOM''s engine, my Celeron300@375 with a VirgeDX gets 37-42 fps in much more detailed scenes. What kind of framerate should I expect to be able to achive rendering a map such as mine bearing in mind all tile need to be rendered everyloop - it ultima 8/xcom style where the camera follows the player every step? Also, any hints about general frame rate improving techniques would be great! btw, hope I didnt make too many mistakes in this post, its 3am and im damn tired
Advertisement
At first I wasn''t getting anywhere near the frame rates I''m getting now. I discovered a few things that made a difference for me (one of which I only added yesterday and isn''t in the demo that people have been trying).

The main thing I learned is that Blt() is S-L-O-W, especially if you use a clipper. BltFast() is way better, but it can''t do clipping. So I do my own clipping before calling BltFast(). It almost doubled my frame rate when I had a large number of tiles on-screen. I will post this routine if anyone wants me to.

The second thing only makes a difference on slower CPUs since it''s not a graphics operation (although it seemed to add up to 10 FPS or better on a P166 at work).

The demo I uploaded has a 128x128 map. The loop that determines which map cells need to be drawn is literally:

for( y = 0; y < 128; y++ )
for( x = 0; x < 128; x++ )
{
Do stuff;
}

That sucks and gets worse if the map size increases.

Yesterday I came up with an alogorithm that restricts the looping to a diamond shape around the map cursor. It never has to consider any map location that doesn''t have a chance of being visible. And the size of the map won''t affect the loop in any way. When I''ve had a chance to clean it up and optimize some of the calculations I''ll post more info about it if anyone is interested.

Oh, one more thing. Your tile blitting may not be the limiting factor. At first I was using Windows routines to draw text (the FPS counter). Then I wrote my own little text routines and that made a HUGE difference.

//TOOM
Could you post that routine?

altair
altair734@yahoo.com
crawlegend.iwarp.com
altairaltair734@yahoo.comwww.geocities.com/altair734
i''m interested in your clipping code. could you post that, pleeeeeeze?


_________________Gecko___

_________________Gecko___Gecko Design
Ok, here's how I do my tile blitting...

In my game library I have the following structure defined (my most basic Graphic OBject, aka a Sprite):

typedef struct gob{   int width;   int height;   LPDIRECTDRAWSURFACE7 surface;} GOB;  


I also have four global variables called ClipX, ClipY, ClipX2, and ClipY2 which define the clipping region. I set these via another function.

Then I have this routine to blit the GOB onto the back buffer (which is a global variable):

void glBlitGOB( GOB* g, int x, int y ){   RECT src;   // First I eliminate GOBs that are totally outside   // the clipping region.   if( x > ClipX2 )      return;   if( y > ClipY2 )      return;   if( x + g->width < ClipX )      return;   if( y + g->height < ClipY )      return;   // By default I want to blit the entire GOB   src.left = 0;   src.top = 0;   src.right = g->width;   src.bottom = g->height;   // But then I adjust the area to be blitted based on   // whether or not parts fall outside the clipping   // region.   if( x + src.right > ClipX2 )      src.right -= x + src.right - ClipX2 - 1;   if( y + src.bottom > ClipY2 )      src.bottom -= y + src.bottom - ClipY2 - 1;   if( x < ClipX )   {      src.left += ClipX - x;      x = ClipX;   }   if( y < ClipY )   {      src.top += ClipY - y;      y = ClipY;   }   // Then I blit it.   BackBuffer->BltFast( x, y, g->surface, &src, DDBLTFAST_SRCCOLORKEY / DDBLTFAST_WAIT );}  


//TOOM

Edited by - toom on 1/24/00 3:00:29 PM

Edited by - toom on 1/24/00 3:05:41 PM
quote: Original post by Toom

   BackBuffer->BltFast( x, y, g->surface, &src, DDBLTFAST_SRCCOLORKEY / DDBLTFAST_WAIT );} 



Hmm... this forum software seems to replace the pipe character with a slash.

//TOOM
Thanks for the reply TOOM, just after i had finished writing the post I implemented my own clipping similar to yours (I noticed it in another post)- i was origionally using blt with clippers on the back buffer. My main problem now is displaying text, it is INCREADIBLY slow - it takes a very noticable performance hit displaying just 1 word. I am also using the windows TextOut function, could you explain your new text system a little?

Thanks for reading,
Michael Cleaver
quote: Original post by Asdas

My main problem now is displaying text, it is INCREADIBLY slow - it takes a very noticable performance hit displaying just 1 word. I am also using the windows TextOut function, could you explain your new text system a little?



I have two methods I''m using. The first is real easy. I create a bitmap that has all the characters in ASCII order starting with a SPACE up to the TILDE character. The bitmap is one character high and 95 characters wide. To print a string I simply blit a rectangle from the character strip onto the surface in question.

The math to extract any given character is trivial as long as you don''t mind a fixed width font. And speaking of fonts, with this method you aren''t limited to single colors. Each letter can be as ornate and colorful as you choose.

The second method I''m using is to plot each character pixel by pixel. I store the font data in a large array which basically consists of on/off bits. Again, as long as you use fixed width characters you can use simple math to extract pixel info. This method isn''t as efficient, but it takes far less memory to store the font data.

//TOOM
To the original poster: i guess you will also have fillrate problems! 800x600x16 IS a lot of data which has to be tranferred from memory to graphic card, and if you have an older machine with PCI and not that much video memory, it has to get slow!

Chris
the best way to determine FPS is to get the time at the start of the frame, and at the end of the frame. the reciprocal of the difference is your framerate for that frame.

// loops once per frame
while (1)
{
startframe = gettime();

// do stuff

endframe = gettime();
print("%.0f", 1.0 / (endframe - startframe));
}

This gives you pinpoint accurate FPS regardless of monitor refresh rates, and the FPS is updated every frame. i suggest you use QueryPerformanceCounter() for the gettime().

This topic is closed to new replies.

Advertisement