簡體   English   中英

在C ++中限制FPS

[英]Limiting FPS in C++

我目前正在制作一款游戲,其中我想限制每秒的幀數,但是我遇到了問題。 這是我在做什么:

我正在通過每幀執行的此方法獲取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的速度...我做錯了什么嗎?或者有更好的方法來做到這一點嗎?

將周期返回給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圖形),請避免執行任何休眠操作,除非您想使用多線程。

睡眠可能非常不准確。 常見的現象是實際睡眠時間的分辨率為14-15毫秒,這使您的幀速率約為70。

Sleep()是否不正確?

我已經放棄嘗試像這樣限制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::microsecondschrono::nanoseconds將它們一起使用3以獲得更好的精度,但是我仍然可以得到驚人的64 fps。

當我將1000.0更改為const整數,使表達式變為(1.0 / MAXFPS-deltaTime)* 1000)我的fps時,表達式中有時會出現另一個奇怪的事情(1.0 / MAXFPS-deltaTime)* 1000.0)(是的,這是完全隨機的)只是由於某種原因跳到74,而表達式完全相等,什么也不會發生。 它們都是雙重表達式,我認為這里沒有發生任何類型提升。

因此,我決定通過功能wglSwapIntervalEXT(1)強制進行V同步; 為了避免屏幕撕裂。 然后,我將使用那種將deltaTime與每個值相乘的方法,該值可能非常取決於執行游戲的計算機的速度。 這會很痛苦,因為我可能會忘記增加一些值,而沒有在自己的計算機上注意到它,這會導致不一致,但是我看不到其他方式...謝謝大家的幫助。

我最近開始將glfw用於正在進行的一個小型項目,並且在std::this_thread::sleep_until旁邊使用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,但是我不得不使用glfwSwapInterval(0);禁用該限制glfwSwapInterval(0); 在while循環之前。

您確定“睡眠”功能接受浮點值嗎? 如果它只接受int ,則您的睡眠將是Sleep(0),它將解釋您的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM