Search code examples
c++sleepglfwframe-rate

C++ How to correctly cap FPS (Using GLFW)


So I have been trying to limit my fps to 60:


//Those are members inside the Display class
double tracker = glfwGetTime();
const float frameCap = 1 / 60.0f;

void Display::present() {
    glfwSwapBuffers( _window );

    //Getting the time between each call
    double now = glfwGetTime( );
    double frameTime=now - tracker;
    tracker=now;
    
    //delaying if required
    if ( frameTime < frameCap )
        delay( frameCap - frameTime );
}

void game() {
//Creating window and opengl context
.....

//Disabling "vsync" so i can cap fps by my own
glfwSwapInterval(0);

 while(running) {
   //Rendering and updating
   .........   

   //Swap buffers and delay if required
   display.present();
 }
}

My delay/sleep function

#ifdef _WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif

void delay( uint32_t ms )
{
#ifdef _WIN32
    Sleep( ms );
#else
    usleep( ms * 1000 );
#endif
}

Basically the idea to cap the framerate in each Display::present() call.

It looks like that nothing is being capped at all in fact the fps is 4000+


Solution

  • For the first call of present your double frameTime=glfwGetTime( ) - tracker;, sets frameTime to the difference between the current time (glfwGetTime() and the inital value of tracker you set with glfwGetTime().

    In the next line, you set tracker=frameTime; (frameTime is not the time but the difference here.)

    For the next call of present, the value tracker is really small (as it is the difference and not the time), as of that your double frameTime=glfwGetTime( ) - tracker; becomes really large (larger than frameCap), so there the sleep won't happen.

    For the next call of present the condition of ( frameTime < frameCap ) might be true again, but for the flow up it definitely won't be anymore again.

    So for at least every second invocation of present the delay won't be called.

    Besides that glfwGetTime returns seconds, frameCap also represents how many seconds a frame should last, but your void delay( uint32_t ms ) expects milliseconds.