C++ 如何进行精确的帧率限制?

Mic*_*LoL 5 c++ windows opengl glfw

我正在尝试使用 C++ 创建一个游戏,我想为 fps 创建限制,但我总是得到比我想要的更多或更少的 fps。当我查看具有 fps 限制的游戏时,它总是精确的帧速率。尝试使用Sleep() std::this_thread::sleep_for(sleep_until). 例如Sleep(0.01-deltaTime),获得 100 fps 但最终得到 +-90fps。当任何睡眠不精确时,这些游戏如何如此精确地处理 fps?我知道我可以使用无限循环来检查时间是否过去,但它使用了 CPU 的全部功率,但我想在没有 VSync 的情况下通过此限制减少 CPU 使用率。

Ted*_*gmo 6

您可以记录开始时的时间点,为其添加固定的持续时间并休眠,直到计算出的时间点出现在每个循环的结束(或开始)。例子:

#include <chrono>
#include <iostream>
#include <ratio>
#include <thread>

template<std::intmax_t FPS>
class frame_rater {
public:
    frame_rater() :                 // initialize the object keeping the pace
        time_between_frames{1},     // std::ratio<1, FPS> seconds
        tp{std::chrono::steady_clock::now()}
    {}

    void sleep() {
        // add to time point
        tp += time_between_frames;

        // and sleep until that time point
        std::this_thread::sleep_until(tp);
    }

private:
    // a duration with a length of 1/FPS seconds
    std::chrono::duration<double, std::ratio<1, FPS>> time_between_frames;

    // the time point we'll add to in every loop
    std::chrono::time_point<std::chrono::steady_clock, decltype(time_between_frames)> tp;
};

// this should print ~10 times per second pretty accurately
int main() {
    frame_rater<10> fr; // 10 FPS
    while(true) {
        std::cout << "Hello world\n";
        fr.sleep();                   // let it sleep any time remaining
    }
}
Run Code Online (Sandbox Code Playgroud)


hac*_*soi 4

是的,睡眠通常是不准确的。这就是为什么你的睡眠时间少于完成该帧所需的实际时间。例如,如果您还需要 5 毫秒来完成该帧,则休眠 4 毫秒。睡眠后,只需对帧的其余部分进行自旋锁定即可。就像是

float TimeRemaining = NextFrameTime - GetCurrentTime();
Sleep(ConvertToMilliseconds(TimeRemaining) - 1);
while (GetCurrentTime() < NextFrameTime) {};
Run Code Online (Sandbox Code Playgroud)

编辑:如另一个答案所述,应该调用 timeBeginPeriod() 来提高 Sleep() 的准确性。另外,据我所知,如果您之前没有调用,Windows 将在您的进程退出时自动调用 timeEndPeriod() 。