限制C++中的FPS

Limiting FPS in C++

本文关键字:FPS 中的 C++ 限制      更新时间:2023-10-16

我目前正在制作一款游戏,我想限制每秒帧数,但我遇到了问题。我在做什么:

我通过这个方法获得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帧/秒(大约是72帧/秒)

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

void Time::limitToMAXFPS() {
double diff = 1.0 / MAXFPS - deltaTime;
if(diff > 0) {
double t = glfwGetTime( );
while(glfwGetTime( ) - t < diff) { }
}
}

但我仍然获得了超过60帧/秒的速度,我仍然获得大约72帧/秒。。。我做错了什么吗?或者有更好的方法吗?

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

为什么不简单地使用一个无限循环,如果超过了特定的时间间隔就会执行。尝试:

const double maxFPS = 60.0;
const double maxPeriod = 1.0 / maxFPS;
// approx ~ 16.666 ms
bool running = true;
double lastTime = 0.0;
while( running ) {
double time = glfwGetTime();
double deltaTime = time - lastTime;
if( deltaTime >= maxPeriod ) {
lastTime = time;
// code here gets called with max FPS
}
}

上次我使用GLFW时,它似乎自我限制为每秒60帧。如果你正在做任何高性能的事情(游戏或3D图形),除非你想使用多线程,否则不要做任何睡眠的事情。

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

Sleep()不准确吗?

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

我也试过:

std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<long>(1.0 / MAXFPS - deltaTime) * 1000.0)));

CCD_ 2也发生了同样的情况。然后,我尝试将毫秒剩余的十进制值传递给chrono::microsecondschrono::nanoseconds,将它们一起使用3以获得更好的精度,但猜猜看,我仍然获得了惊人的64帧/秒。

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

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

我最近开始为我正在进行的一个小项目使用glfw,并且我使用std::chronostd::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);
}

要添加,可以通过调整end轻松调整FPS偏好。话虽如此,我知道glfw被限制为60fps,但我不得不在while循环之前用glfwSwapInterval(0);禁用该限制。

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