C++ 如何制作基本的 FPS 计数器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28530798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 21:00:35  来源:igfitidea点击:

How to Make a Basic FPS Counter?

c++openglframe-rate

提问by Xenonic

I'm trying to display my frames-per-second in my cube-rendering program. I would like to see its performance. So, how can I do it? I have done research on this already, but the examples I've seen use either multiple classes and still don't work, or they use libraries that I don't have. Is there a way to get the FPS by using pre-installed libs like ctime? I am using OpenGL with C++.

我正在尝试在我的立方体渲染程序中显示我的每秒帧数。我想看看它的表现。那么,我该怎么做呢?我已经对此进行了研究,但是我所看到的示例要么使用了多个类但仍然不起作用,要么使用了我没有的库。有没有办法通过使用像 ctime 这样的预安装库来获得 FPS?我在 C++ 中使用 OpenGL。

Here is my (empty) function:

这是我的(空)函数:

void GetFPS()
{

}

and then I display my FPS in my render function with:

然后我在渲染函数中显示我的 FPS:

std::cout << xRot << " " << yRot << " " << zRot << " " << FPS << "\n"; //xRot, yRot, and zRot are my cube's rotation.

My program is set to 60FPS, but I would like to see the actual FPS, not what it's set to.

我的程序设置为 60FPS,但我想查看实际的 FPS,而不是它的设置。

回答by CoffeDeveloper

You have to sample 2 different time intervals using clock()however notes that there are several problems:

您必须使用 2 个不同的时间间隔进行采样,clock()但请注意存在几个问题:

  • resolution of clock is several milliseconds (you may workaround using std::chrono etc, however even chrono may have not so high resolution depending on implementation. On my PC with GCC 4.9.1 I never get better resolution than 16 milliseconds even with std::chrono.
  • tipically using clock()you will get 0 many times and at some time you will measure a real time (in my case it just make a jump of 15/16 milliseconds)
  • unless you are using vertical syncronization (vsync), you will not measure real frametime but just the CPU time spent in your render loop (to activate vsync you have to SetSwapInterval(1) wich your OS function or for example using a library like SDL that provide portable cross platform implementaiton)
  • To measure real rendering time you may use a GL'S time query (you may have only 1 timer bound at any time so if you are measuring framerate you cann't measure how long takes render something specific).
  • Do not measure FPS (well unless you want just to show it to users), instead measure frame time in milliseconds, that gives much more intuitive approximation of performance. (you know going from 100 to 80 FPS is 2,5 ms difference, going from 40 to 20 FPS is 25 ms difference!)
  • 时钟的分辨率是几毫秒(您可以使用 std::chrono 等解决方法,但是即使是 chrono 也可能没有那么高的分辨率,具体取决于实现。在我的带有 GCC 4.9.1 的 PC 上,即使使用 std,我也永远无法获得比 16 毫秒更好的分辨率: :计时。
  • 通常使用clock()你会得到 0 多次,有时你会测量实时(在我的情况下它只是跳跃 15/16 毫秒)
  • 除非您使用垂直同步 (vsync),否则您将不会测量实际帧时间,而只会测量渲染循环中花费的 CPU 时间(要激活 vsync,您必须使用 SetSwapInterval(1) 至您的 OS 功能,或者例如使用像 SDL 这样的库)提供可移植的跨平台实现)
  • 要测量实际渲染时间,您可以使用 GL 的时间查询(您可能在任何时候都只绑定了 1 个计时器,因此如果您正在测量帧速率,则无法测量渲染特定内容所需的时间)。
  • 不要测量 FPS(除非您只想向用户展示),而是以毫秒为单位测量帧时间,这样可以更直观地估计性能。(你知道从 100 到 80 FPS 有 2.5 毫秒的差异,从 40 到 20 FPS 有 25 毫秒的差异!)

Do that:

去做:

double clockToMilliseconds(clock_t ticks){
    // units/(units/time) => time (seconds) * 1000 = milliseconds
    return (ticks/(double)CLOCKS_PER_SEC)*1000.0;
}
//...

clock_t deltaTime = 0;
unsigned int frames = 0;
double  frameRate = 30;
double  averageFrameTimeMilliseconds = 33.333;

while(rendering){

    clock_t beginFrame = clock();
    render();
    clock_t endFrame = clock();

    deltaTime += endFrame - beginFrame;
    frames ++;

    //if you really want FPS
    if( clockToMilliseconds(deltaTime)>1000.0){ //every second
        frameRate = (double)frames*0.5 +  frameRate*0.5; //more stable
        frames = 0;
        deltaTime -= CLOCKS_PER_SEC;
        averageFrameTimeMilliseconds  = 1000.0/(frameRate==0?0.001:frameRate);

        if(vsync)
            std::cout<<"FrameTime was:"<<averageFrameTimeMilliseconds<<std::endl;
        else
           std::cout<<"CPU time was:"<<averageFrameTimeMilliseconds<<std::endl;
    }
}

The above code works also when you do something that takes several seconds. I do a computation that is updated every second, you could as well update it more often. (note I use exactly that code in most of my projects that need FPS)

当你做一些需要几秒钟的事情时,上面的代码也有效。我做一个每秒更新一次的计算,你也可以更频繁地更新它。(请注意,我在大多数需要 FPS 的项目中都使用了该代码)

回答by Pilpel

Simply save the time "ticks" before and after you render your scene, then do a simple calculation.

只需在渲染场景之前和之后保存时间“滴答”,然后做一个简单的计算。

Here's an example that uses <ctime>'s clock()function. (note that clock()works differently on different platform)

这是一个使用<ctime>'sclock()函数的示例。(请注意,clock()在不同平台上的工作方式不同)

clock_t current_ticks, delta_ticks;
clock_t fps = 0;
while(true)// your main loop. could also be the idle() function in glut or whatever
{
    current_ticks = clock();

    render();

    delta_ticks = clock() - current_ticks; //the time, in ms, that took to render the scene
    if(delta_ticks > 0)
        fps = CLOCKS_PER_SEC / delta_ticks;
    cout << fps << endl;
}

回答by user_number153

some modern c++ just pop this in any loop to measure the number of calls a second.

一些现代 C++ 只是在任何循环中弹出它来测量每秒的调用次数。

#include <chrono>

void printFPS() {
    static std::chrono::time_point<std::chrono::steady_clock> oldTime = std::chrono::high_resolution_clock::now();
    static int fps;

    fps++;

    if (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::high_resolution_clock::now() - oldTime) >= std::chrono::seconds{ 1 }) {
        oldTime = std::chrono::high_resolution_clock::now();
        std::cout << "FPS: " << fps <<  std::endl;
        fps = 0;
    }
}



while(1){
     printFPS();
}