Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: FPS calculations with SFML2.0  (Read 11764 times)

0 Members and 1 Guest are viewing this topic.

Mars_999

  • Full Member
  • ***
  • Posts: 103
    • View Profile
    • Email
FPS calculations with SFML2.0
« on: October 15, 2011, 06:17:29 am »
I know SFML 2.0 moved to unsigned int vs. float but maybe I just lost it, but I can't get my FPS to come out right... I get a 1 now vs. say 60fps

Code: [Select]

inline unsigned int GetFrameRate(void)
{
static unsigned int frameCounter = 0, fps = 0;
static float nextSecond = 0.0f, prevSecond = 0.0f;
frameCounter++;
nextSecond += window.GetFrameTime() * .001f;
std::cout << nextSecond << std::endl;

if(nextSecond - prevSecond > 1.0f)
{
prevSecond = nextSecond;
fps = frameCounter;
frameCounter = 0;
}
return fps;
}

OniLinkPlus

  • Hero Member
  • *****
  • Posts: 500
    • View Profile
FPS calculations with SFML2.0
« Reply #1 on: October 15, 2011, 07:12:09 am »
Your code... doesn't make any sense. The only values you CAN get from it are 1 and 0. To calculate FPS using the new system, you need to calculate the FPS as 1000/time_elapsed. The 1000 comes from the fact that time is measured in milliseconds.
I use the latest build of SFML2

Mars_999

  • Full Member
  • ***
  • Posts: 103
    • View Profile
    • Email
FPS calculations with SFML2.0
« Reply #2 on: October 15, 2011, 07:23:54 am »
Quote from: "OniLink10"
Your code... doesn't make any sense. The only values you CAN get from it are 1 and 0. To calculate FPS using the new system, you need to calculate the FPS as 1000/time_elapsed. The 1000 comes from the fact that time is measured in milliseconds.


Ok, but I get division by zero errors when I do 1000/elapsedTime

bah here is what I have now...
Code: [Select]

inline unsigned int GetFrameRate(void)
{
static unsigned int frameCounter = 0, fps = 0;
static float nextSecond = 0.0f, prevSecond = 0.0f;
frameCounter++;
nextSecond += window.GetFrameTime() * .001f;
std::cout << nextSecond << std::endl;

if(nextSecond - prevSecond > 1.0f)
{
prevSecond = nextSecond;
fps = frameCounter;
frameCounter = 0;
}
return fps;
}

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
FPS calculations with SFML2.0
« Reply #3 on: October 15, 2011, 01:24:33 pm »
Doing Doing this with 1000 / elapsed_time is not a 100% accurate because of it's limited to 1000 fps or we get an division by zero and we infact do not actually show the fps but only a mathematical approximation. What you can do is have a check performed if the elapsed time is zero then output "+1000 FPS".

I don't like this method as the framerate will jump a lot every frame. And it makes it completly unreadable. I prefer what you do because the framerate is 100% accurate and it is only updated once every second mmaking it readable.

My code for it is:
Code: [Select]
#include <GDE/RuntimeDisplayer.hpp>
#include <GDE/GDE.hpp>
#include <GDE/Macros.hpp>

#ifdef _WIN32
    #include <windows.h>
    #include <psapi.h>
#else
    #error Have not been defined for target operating system!
#endif

static sf::Text localFPSText( "0 FPS", sf::Font::GetDefaultFont(), 15 );
static sf::Text localMemoryText( "0/0 Bytes", sf::Font::GetDefaultFont(), 15 );
static sf::Uint32 localFrameCounter = 0;
static sf::Uint32 localFrameTime = 0;
static sf::Uint32 localFPS = 0;

namespace GDE
{
    namespace RuntimeDisplayer
    {
        void Init();
        void MemoryUsage( sf::Uint64 &someUsedMemory, sf::Uint64 &someAllocatedMemory );
    }
}

void GDE::RuntimeDisplayer::Init()
{
    localFPSText.SetPosition( 5, 5 );
    localMemoryText.SetPosition( 5, 25 );

    localFPSText.SetColor( sf::Color::Yellow );
    localMemoryText.SetColor( sf::Color::Yellow );
}

void GDE::RuntimeDisplayer::MemoryUsage( sf::Uint64 &someUsedMemory, sf::Uint64 &someAllocatedMemory )
{
    PROCESS_MEMORY_COUNTERS memoryData;
    assert( GetProcessMemoryInfo( GetCurrentProcess(), &memoryData, sizeof( memoryData ) ) == TRUE );

    someUsedMemory = memoryData.WorkingSetSize;
    someAllocatedMemory = memoryData.PagefileUsage;
}

void GDE::RuntimeDisplayer::Update( const sf::Uint32 someTime )
{
    localFrameCounter += 1;
    localFrameTime += someTime;
    if( localFrameTime >= 1000 )
    {
        localFPS = localFrameCounter;
        localFrameCounter = 0;
        localFrameTime -= 1000;

        localFPSText.SetString( GDE::ConvertToString( localFPS ) + " FPS" );

        sf::Uint64 usedMemory = 0;
        sf::Uint64 allocatedMemory = 0;
        GDE::RuntimeDisplayer::MemoryUsage( usedMemory, allocatedMemory );

        localMemoryText.SetString( GDE::ConvertToString( static_cast< float >( usedMemory / 1024 ) / 1024.f ) + "/" + GDE::ConvertToString( static_cast< float >( allocatedMemory / 1024 ) / 1024.f ) + " Megabytes" );
    }
}

void GDE::RuntimeDisplayer::Render( sf::RenderTarget &aTarget )
{
    sf::View oldView = aTarget.GetView();
    aTarget.SetView( aTarget.GetDefaultView() );
    aTarget.Draw( localFPSText );
    aTarget.Draw( localMemoryText );
    aTarget.SetView( oldView );
}


Feel free to use it, it does the same thing except that it will also display the current use of memory and how much has been allocated by the system. You can comment that out if not interested ^^
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Mars_999

  • Full Member
  • ***
  • Posts: 103
    • View Profile
    • Email
FPS calculations with SFML2.0
« Reply #4 on: October 15, 2011, 02:18:47 pm »
localFrameTime -= 1000;

that concerns me... If the variable is e.g. 1200 you are already 200 milliseconds over 0...

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
FPS calculations with SFML2.0
« Reply #5 on: October 15, 2011, 02:22:25 pm »
Yeah? Because a frame took pretty much time. If we reset it to 0 then we will start skipping seconds. Meaning that if we have 20 FPS and it took 1200 ms( So the last frame was pretty heavy ) and we reset it to zero, we will have somehow magically gained 1/5th performance from nowhere and get 20 FPS again next "second" when we should have only had 16 FPS!

Trust me, removing a second instead of resetting is the accurate way.

EDIT: Why that last frame was "extra" heavy can be anything from windows thread scheduling screwing you over or special case being handled like a trigger being activated. And since this is handled with a >= operator it will work even if that happens every second( that we reach over 1000 ) because it will be invoked some frames earlier each second iteration.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Yours3lf

  • Newbie
  • *
  • Posts: 43
    • View Profile
FPS calculations with SFML2.0
« Reply #6 on: October 17, 2011, 10:21:08 am »
ok guys so here's how I do it:


Code: [Select]

float fps = 1.0f;
int frames = 0;
std::wstringstream ws;
timer render_timer;
font the_font;

while(true)
{
    frames++; //increment frame counter
    //check if a 1000ms (a second) has passed
    if ( render_timer.get_time_passed() > 1000.0f )
    {
        int timepassed = render_timer.get_time_passed();
        //if a second has passed, then fps equals, lets say:
        //60.099 = 1000 / ( 1015 / 61 )
        //so 61 frames have been drawn in 1015 ms --> 16.64 ms is the average time spent on one frame
        // so in 1000ms (a second) we have 1000 / 16.64 ms = 60.099 fps
        fps = 1000.0f / ( ( float ) timepassed / ( float ) frames );
        frames = 0;
        timepassed = 0;
        //reset timer
        render_timer.set_timerbegin();
    }

    ws << L"FPS:" << fps;
    the_font.render ( ws.str() );
    ws.str ( L"" );

    //check for error
    objs::get()->check_for_opengl_error();

    //show our work
    swap_buffer();
}


happy coding :)

sbroadfoot90

  • Jr. Member
  • **
  • Posts: 77
    • View Profile
FPS calculations with SFML2.0
« Reply #7 on: October 18, 2011, 01:48:05 am »
Quote from: "Groogy"
Yeah? Because a frame took pretty much time. If we reset it to 0 then we will start skipping seconds. Meaning that if we have 20 FPS and it took 1200 ms( So the last frame was pretty heavy ) and we reset it to zero, we will have somehow magically gained 1/5th performance from nowhere and get 20 FPS again next "second" when we should have only had 16 FPS!

Trust me, removing a second instead of resetting is the accurate way.

EDIT: Why that last frame was "extra" heavy can be anything from windows thread scheduling screwing you over or special case being handled like a trigger being activated. And since this is handled with a >= operator it will work even if that happens every second( that we reach over 1000 ) because it will be invoked some frames earlier each second iteration.


Groogy is right. Although your code might be a bit hard to understand for the OP considering he was struggling so badly with his own attempt.

@OP, to see why your code outputs only 0 or 1, just step through it line by line.

Quote
Code: [Select]

Code:
1inline unsigned int GetFrameRate(void)
2   {
3      static unsigned int frameCounter = 0, fps = 0;
4      static float nextSecond = 0.0f, prevSecond = 0.0f;
5      frameCounter++;
6      nextSecond += window.GetFrameTime() * .001f;
7      std::cout << nextSecond << std::endl;
8
9      if(nextSecond - prevSecond > 1.0f)
10      {
11         prevSecond = nextSecond;
12         fps = frameCounter;
13         frameCounter = 0;
14      }
15      return fps;
16   }


I numbered your lines so I can refer to them. Here is what happens in your code.

Line 3 - fps = 0, frameCounter = 0
Line 5 - fps = 0, frameCounter =1
Line 12 - fps = 0 or 1, frameCounter = 1
Line 15 - return fps (which is 0 or 1)

Also, did you actually make any changes between your two posts? I can't see any.

I think the main problem is that you're reassigning frameCounter to 0 each time you call the function

Mars_999

  • Full Member
  • ***
  • Posts: 103
    • View Profile
    • Email
FPS calculations with SFML2.0
« Reply #8 on: October 18, 2011, 03:16:20 am »
this is what I currently using and seems to work fine...

Code: [Select]

inline unsigned int GetFrameRate(void)
{
static unsigned int frameCounter = 0;
static unsigned int frameTime = 0;
static unsigned int fps = 0;
frameCounter++;
frameTime += window.GetFrameTime();
if(frameTime >= 1000)
{
fps = frameCounter;
frameCounter = 0;
frameTime -= 1000;
}
return fps;
}

 

anything