我目前正在制作一款游戏,我想限制每秒帧数,但我遇到了问题。这就是我正在做的事情:
我通过这个每帧执行的方法得到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) { }
}
}
但是我仍然得到超过60 fps,我仍然得到大约72 fps ...我做错了什么或有更好的方法来做这个?
答案 0 :(得分:3)
睡眠可能非常不准确。一个常见的现象是实际睡眠时间的分辨率为14-15毫秒,这使你的帧速率达到70左右。
答案 1 :(得分:3)
将周期返回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 fps。如果你正在做任何高性能定位(游戏或3D图形),避免任何睡眠,除非你想使用多线程。
答案 2 :(得分:1)
我已经放弃了尝试限制这样的fps ...正如你所说的Windows与Sleep非常不一致。我的fps平均值总是64 fps而不是60.问题是Sleep将整数(或长整数)作为参数,所以我使用static_cast进行转换。但我需要将其作为双重传递给它。每帧16毫秒不同于16.6666 ......这可能是这个额外4 fps的原因(所以我认为)。
我也尝试过:
std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<long>(1.0 / MAXFPS - deltaTime) * 1000.0)));
sleep_for
也发生了同样的事情。然后我尝试将剩余的十进制值从毫秒传递到chrono::microseconds
和chrono::nanoseconds
,将它们一起使用3以获得更好的精度但是猜测我仍然得到了64 fps的怪异。
另一个奇怪的事情是表达式(1.0 / MAXFPS - deltaTime)* 1000.0)有时(是的,这是完全随机的)当我将1000.0更改为const整数时使表达式变为(1.0 / MAXFPS - deltaTime)* 1000 )由于某种原因,我的fps只是跳到74,而表达式完全相同,没有任何事情发生。它们都是双重表达,我认为这里不会发生任何类型的推广。
所以我决定通过函数wglSwapIntervalEXT(1)强制V-sync;为了避免屏幕撕裂。然后我将使用deltaTime与每个值相乘的方法,这些值可能非常依赖于执行我游戏的计算机的速度。这将是一种痛苦,因为我可能会忘记增加一些价值,而不是在我自己的计算机上注意到它会造成不一致,但我没有别的办法......感谢大家的帮助。
答案 3 :(得分:0)
我最近开始使用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);
}
添加您可以通过调整end
轻松调整FPS偏好设置。
现在说,我知道glfw限制在60fps但我必须在while循环之前用glfwSwapInterval(0);
禁用限制。
答案 4 :(得分:-1)
您确定您的睡眠功能是否接受浮点值。如果只接受int
,您的睡眠将是睡眠(0),这将解释您的问题。