C++ 限制C+中的FPS+;

C++ 限制C+中的FPS+;,c++,opengl,sleep,glfw,frame-rate,C++,Opengl,Sleep,Glfw,Frame Rate,我目前正在制作一个游戏,我想限制每秒的帧数,但我有问题。以下是我正在做的: 我通过此方法获取每个帧执行的deltaTime: void Time::calc_deltaTime() { double currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; } deltaTime具有我预期的值(大约0.012…到0.016…) 然后我使用de

我目前正在制作一个游戏,我想限制每秒的帧数,但我有问题。以下是我正在做的:

我通过此方法获取每个帧执行的deltaTime:

void Time::calc_deltaTime() {
    double currentFrame = glfwGetTime();
    deltaTime = currentFrame - lastFrame;
    lastFrame = currentFrame;
}
deltaTime具有我预期的值(大约0.012…到0.016…)

然后我使用deltaTime通过睡眠窗口功能延迟帧,如下所示:

void Time::limitToMAXFPS() {

    if(1.0 / MAXFPS > deltaTime)
        Sleep((1.0 / MAXFPS - deltaTime) * 1000.0);
}
MAXFPS等于60,我乘以1000将秒转换为毫秒。虽然一切似乎都是正确的,但我的速度超过了60 fps(大约72 fps)

我还使用while循环尝试了这种方法:

void Time::limitToMAXFPS() {

    double diff = 1.0 / MAXFPS - deltaTime;

    if(diff > 0) {

        double t = glfwGetTime( );

        while(glfwGetTime( ) - t < diff) { }

    }

}
void Time::limitToMAXFPS(){
双差=1.0/MAXFPS-增量时间;
如果(差异>0){
double t=glfwGetTime();
而(glfwGetTime()-t

但我还是得到了60多fps,我还是得到了72 fps左右。。。我做错了什么,或者有更好的方法吗?

您确定睡眠函数接受浮点值吗。如果它只接受
int
,您的睡眠将是睡眠(0),这将解释您的问题。

睡眠可能非常不准确。一个常见的现象是,睡眠的实际时间分辨率为14-15毫秒,帧速率约为70


我已经放弃了像这样限制fps的尝试。。。正如你所说,Windows与睡眠非常不一致。我的fps平均值总是64 fps,而不是60 fps。问题是Sleep将一个整数(或长整数)作为参数,所以我使用static_cast进行转换。但我需要把它当作替身。每帧16毫秒不同于16.6666。。。这可能是额外4fps的原因(所以我认为)

我还尝试:

std::this_thread::sleep_for(std::chrono::ms(static_cast(1.0/MAXFPS-deltaTime)*1000.0))

同样的事情也发生在
的睡眠中。然后,我尝试将毫秒中剩余的十进制值传递到
chrono::microseconds
chrono::nanoseconds
,将它们3一起使用以获得更高的精度,但猜猜我仍然得到了令人吃惊的64 fps

另一件奇怪的事情是在表达式(1.0/MAXFPS-deltaTime)*1000.0)中,有时(是的,这是完全随机的),当我将1000.0更改为常量整数,使表达式变成(1.0/MAXFPS-deltaTime)*1000)时,出于某种原因,我的fps会跳到74,而表达式是完全相等的,不应该发生任何事情。这两个词都是双重表达,我不认为这里会发生任何类型的促销活动


因此,我决定通过wglSwapIntervalEXT(1)函数强制V同步;以避免筛网撕裂。然后我会用deltaTime乘以每一个值的方法,这可能非常取决于计算机执行游戏的速度。这将是一个痛苦,因为我可能会忘记乘以一些值,而没有注意到它在我自己的计算机上造成了不一致,但我看不到其他方法。。。谢谢大家的帮助。

将循环返回CPU有多重要?对我来说,使用睡眠似乎是个坏主意。如果我错了,请有人纠正我,但我认为应该避免使用睡眠功能

为什么不简单地使用一个无限循环,在超过某个时间间隔时执行该循环呢。尝试:

const double maxFPS=60.0;
常数双最大周期=1.0/maxFPS;
//约16.666毫秒
bool running=true;
双lastTime=0.0;
(跑步时){
double time=glfwGetTime();
双增量时间=时间-上次时间;
如果(deltaTime>=maxPeriod){
lastTime=时间;
//这里的代码使用max FPS调用
}
}

上次我使用GLFW时,它似乎自我限制为60 fps。如果您正在做任何面向高性能的事情(游戏或3D图形),除非您想使用多线程,否则请避免任何休眠的操作

我最近开始在我正在进行的一个小型项目中使用glfw,我使用
std::chrono
沿
std::this_thread::sleep_until
来实现60fps

auto start = std::chrono::steady_clock::now();
while(!glfwWindowShouldClose(window))
{
    ++frames;
    auto now = std::chrono::steady_clock::now();
    auto diff = now - start;
    auto end = now + std::chrono::milliseconds(16);
    if(diff >= std::chrono::seconds(1))
    {
        start = now;
        std::cout << "FPS: " << frames << std::endl;
        frames = 0;

    }
    glfwPollEvents();

    processTransition(countit);
    render.TickTok();
    render.RenderBackground();
    render.RenderCovers(countit);

    std::this_thread::sleep_until(end);
    glfwSwapBuffers(window);
}
auto start=std::chrono::staid_clock::now();
而(!glfwWindowShouldClose(窗口))
{
++框架;
自动现在=标准::计时::稳定时钟::现在();
自动差异=现在-开始;
自动结束=现在+标准::计时::毫秒(16);
如果(差异>=std::chrono::秒(1))
{
开始=现在;

std::你能如何计算你当前的fps吗?我个人会这样写
Sleep
表达式:
Sleep(1000/MAXFPS-deltaTime*1000)
,但这不会有太大的不同。@AlgirdasPreidžius:如果
MAXFPS
是整数类型呢?我建议您使用
std::chrono
std::this_thread::sleep_for()
睡眠。但是,在您向我们展示如何测量fps之前,我无法给出一个好的答案,因为可能会出现错误。为什么要睡眠?opengl有一个“等待vsync”选项,这可能是一个更好的选择。如果我在没有纸和笔的情况下正确计算,他会用20-40左右的参数调用Sleep,而不是0。@doron是的,这是一个问题,我给Sleep加了两倍的参数,而它期望的DWORD是无符号整数。我像这样将它转换为DWORD(DWORD)((1.0/MAXFPS-deltaTime)*1000.0)现在我的速度大约是64 fps。我认为斯文·尼尔森是对的,我必须寻找一种替代睡眠的方法。@MagnoSilva:通常的方法是使用轮询高分辨率计时器,然后忙着等待,直到所需的时间过去。一般来说,“睡眠”是一个进程(即将其CPU周期交给系统的其余部分)将导致相当粗糙的时间分辨率。在现代桌面系统上,调度程序计时器在250Hz到1000Hz之间运行,因此有效的计时精度介于1ms到5ms之间。添加到