如何制作一个基本的FPS计数器
How to Make a Basic FPS Counter?
我正在尝试在多维数据集渲染程序中显示每秒帧数。我想看看它的表演。那么,我该怎么做呢?我已经对此进行了研究,但我看到的例子要么使用了多个类,但仍然不起作用,要么使用了我没有的库。有没有一种方法可以通过使用像ctime这样的预装库来获得FPS?我正在使用OpenGL和C++。
这是我的(空)函数:
void GetFPS()
{
}
然后我用在渲染函数中显示我的FPS
std::cout << xRot << " " << yRot << " " << zRot << " " << FPS << "n"; //xRot, yRot, and zRot are my cube's rotation.
我的程序设置为60FPS,但我想看看实际的FPS,而不是它的设置。
您必须使用clock()
对2个不同的时间间隔进行采样但是注意到有几个问题:
- 时钟的分辨率是几毫秒(你可以使用std::chrono等来解决问题,但即使是chrono也可能没有那么高的分辨率,这取决于具体的实现方式。在我的GCC 4.9.1电脑上,即使是std::chrono,我的分辨率也从未超过16毫秒
- 技巧性地使用
clock()
,你会多次得到0,在某个时候你会测量一个实时(在我的情况下,它只跳了15/16毫秒) - 除非您使用垂直同步(vsync),否则您将不会测量实际帧时间,而只测量渲染循环中花费的CPU时间(要激活vsync,您必须使用操作系统函数SetWapInterval(1),或者例如使用类似SDL的库来提供可移植的跨平台实现)
- 要测量真实渲染时间,可以使用GL的时间查询(任何时候可能只有1个定时器绑定,因此如果测量帧速率,则无法测量渲染特定内容所需的时间)
- 不要测量FPS(除非你只是想向用户展示它),而是以毫秒为单位测量帧时间,这样可以更直观地近似性能。(你知道,从100到80 FPS相差2.5毫秒,从40到20 FPS相差25毫秒!)
这样做:
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;
}
}
当你做一些需要几秒钟时间的事情时,上面的代码也能工作。我做了一个每秒更新的计算,你也可以更频繁地更新它。(注意,我在大多数需要FPS的项目中都使用了该代码)
只需在渲染场景前后保存时间"滴答",然后进行简单计算。
下面是一个使用<ctime>
的clock()
函数的示例。(注意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;
}
只需在任何循环中调用它即可测量每秒调用的次数。
#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;
}
}
如果您只想为了打印而测量FPS,您可以使用std::chrono
来测量挂钟。使用std::clock()
会得到比std::chrono
更准确的值,因为它测量处理时间,但可能您不想打印精度如此之高的FPS。
下面的解决方案使用std::chrono
来计算程序的正常运行时间,并在每次帧更新后递增帧计数器。将帧计数器除以程序的正常运行时间可以得到FPS。
#include <chrono>
#include <iostream>
#include <thread>
using namespace std::chrono;
steady_clock::time_point first_tp;
unsigned long frame_count = 0;
duration<double> uptime()
{
if (first_tp == steady_clock::time_point{})
return duration<double>{ 0 };
return steady_clock::now() - first_tp;
}
double fps()
{
const double uptime_sec = uptime().count();
if (uptime_sec == 0)
return 0;
return frame_count / uptime_sec;
}
void time_consuming_function()
{
std::this_thread::sleep_for(milliseconds{ 100 });
}
void run_forever()
{
std::cout << "fps at first: " << fps() << 'n';
first_tp = std::chrono::steady_clock::now();
while (true)
{
std::cout << "fps: " << fps() << 'n';
time_consuming_function();
frame_count++;
}
}
int main()
{
run_forever();
}
在我的机器上运行它产生:
$ ./measure_fps
fps at first: 0
fps: 0
fps: 9.99108
fps: 9.99025
fps: 9.98997
fps: 9.98984
而将其适应std::clock()
则会产生
$ ./measure_fps
fps at first: 0
fps: 0
fps: 37037
fps: 25316.5
fps: 23622
fps: 22346.4
快速完整的
#include <time.h> // clock
#include <stdio.h> // snprintf
unsigned int iMemClock, iCurClock, iLoops;
char aFPS[12];
/* main loop */
{
if (iMemClock > (iCurClock = clock()))
iLoops++;
else
{
snprintf(aFPS, sizeof(aFPS),"FPS: %d",iLoops);
iMemClock = iCurClock + CLOCKS_PER_SEC;
iLoops = 0;
}
/*
someRoutines();
*/
}
/* main loop */
相关文章:
- 循环在计数器中不起作用
- python集合的C++等价物是什么.计数器
- phytec phyBOARD iMX-6在从闪存而不是SD卡运行qt5 opengles应用程序时表现不佳(FPS减半
- Python 集合.计数器,如何避免重复查找
- 请解释字谜的代码,我看不懂计数器数组,每个值已经是0
- std::shared_ptr 自定义参考计数器
- 英特尔 TBB 程序不会终止,可能会误用参考计数器
- 不正确的比较和交换计数器输出用于快速排序功能
- OpenSSL API,使用GCM(伽罗瓦计数器模式)进行AES加密
- C++ 在循环中添加计数器变量并再次初始化其值
- 使用 sfml 计算 FPS
- 从 OpenCV 3 切换到 OpenCV 4 会导致网络摄像头以最大 5 fps 的速度录制,而不是通常的 30 f
- 需要帮助才能在C++中创建类计数器
- 漂亮的计数器习语的错误或格式错误的静态订单惨败?
- 几乎总是自动和带计数器的循环
- 线程使用计数器C++
- 为什么使用 2 个嵌套循环 O(n^2) 复杂度来解决二和问题,当只改变循环计数器逻辑时运行得更快?
- 对于循环计数器不递增
- 如何制作一个基本的FPS计数器
- 窗口标题GLFW中的FPS计数器