OpenGL 计算帧率/FPS的方法

當我們要比較 3D 程式的效率, frame rate 是一個很重要的資料.

 

但是, 算 frame rate 也算得正確才有意思呀. 這次, 我就介紹一下如何算 frame rate.

首先, 讀者們, 你要先了解一件事, 現代的顯示卡, 已經不再是純粹把 digital 資料 轉成 analog 資料的低檔硬體, 它, 已經變成了一個 精密 而 架構複雜的系統. 因此, 算 frame rate 時, 也得了解它多一些.

算 frame rate, 最直接的想法, 就是把 display() 重複呼叫器一定的次數, 把 次數 除以 所需時間 就是 frame rate. 但是, 這是不正確的, 因為 glutSwapBuffers() 會等待 顯示器 完成最近一次更新, 才會完結的. 結果, 如果你的程式比 顯示器更新率 跑得更快, 所算出來的 frame rate 再多也只可能是 顯示器更新率. 舉例說, 在顯示器的更新率, 一般是 75 fps, 如上述算 frame rate, 最快也只會是 75 fps.

又說, 如果我們把 glutSwapBuffers() 拿掉, 就不用等待 顯示器 完成更新呀. 但是, 這樣算 frame rate 也不正確. 因為, 顯示卡是有一個指令緩衝的機制, 就是說, 你給 顯示卡 下繪圖指令時, 指令並不會被立即執行, 指令會先儲存在 顯示卡的指令緩衝區, 直到 緩衝區爆滿 或是 被特別地指令 緩衝區內的指令才會被執行. 因此, 只把 glutSwapBuffers() 拿掉, 所算出來的 frame rate, 只反映指令由 主記憶體 傳到 顯示卡緩衝區 的速度而已.

說到這裡, 聰明的讀者們大概也估計到要甚麼做, 就是, 把 glutSwapBuffers() 換成為 強制顯示卡執行指令. 這個指令, 就是 glFinish(). 只要把 glutSwapBuffers() 換成為 glFinish(), 所有繪令指令就會被執行, 又不用被 顯示器更新率 限制. 這樣算出來的 frame rate, 才能有效的反映 3D 程式效能.

好, 我們去寫程式算 frame rate 吧...


  
  
1 #include < stdio.h >
2 #include < time.h >
3
4 #include " glut.h "
5
6   void display();
7   void keyboard( unsigned char key, int x, int y );
8
9   float g_fps( void ( * func)( void ), int n_frame );
10
11   bool finish_without_update = false ;
12
13   void main()
14 {
15 glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB );
16 glutInitWindowSize( 640 , 640 );
17 glutCreateWindow( " glutTest10 " );
18
19 glutDisplayFunc(display);
20 glutKeyboardFunc(keyboard);
21
22 glutMainLoop();
23 }
24
25 void keyboard( unsigned char key, int x, int y )
26 {
27 switch ( key )
28 {
29 case ' F ' :
30 case ' f ' :
31 finish_without_update = true ;
32 printf( " %f fps/n " , g_fps( display, 100 ) );
33 finish_without_update = false ;
34 break ;
35 }
36 }
37
38 void display()
39 {
40 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
41
42 glMatrixMode(GL_PROJECTION);
43 glLoadIdentity();
44 gluPerspective( 20 , 1 , 0.1 , 10 );
45
46 glMatrixMode(GL_MODELVIEW);
47 glLoadIdentity();
48 gluLookAt(
49 0 , 0 , 1 ,
50 0 , 0 , 0 ,
51 0 , 1 , 0 );
52
53 glEnable( GL_LIGHTING );
54 glEnable( GL_LIGHT0 );
55 glEnable( GL_DEPTH_TEST );
56 glutSolidTeapot( . 1 );
57
58 if ( finish_without_update )
59 glFinish();
60 else
61 glutSwapBuffers();
62 }
63
64 float g_fps( void ( * func)( void ), int n_frame )
65 {
66 clock_t start, finish;
67 int i;
68 float fps;
69
70 printf( " Performing benchmark, please wait " );
71 start = clock();
72 for ( i = 0 ; i < n_frame; i ++ )
73 {
74 func();
75 }
76 printf( " done/n " );
77 finish = clock();
78
79 fps = float (n_frame) / (finish - start) * CLOCKS_PER_SEC;
80 return fps;
81 }

 

 

void display()
{
// ... 
  if( finish_without_update )
    glFinish();
  else
    glutSwapBuffers();
}

 

display() function 最後的幾行, 就是用來選擇用 glFinish() 還是用 glutSwapBuffers(), 算 frame rate 時, 我們用 glFinish(), 其他時間我們用 glutSwapBuffers().

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了设置OpenGL的帧速率,可以使用glut库中的glutTimerFunc()函数。该函数允许您指定一个时间间隔,以便在该时间间隔后调用一个函数。通过在该函数中调用glutPostRedisplay()函数,可以告诉OpenGL重新绘制场景。以下是一个简单的示例,演示如何使用glutTimerFunc()函数来设置OpenGL的帧速率: ```python from OpenGL.GL import * from OpenGL.GLUT import * from OpenGL.GLU import * # 定义场景绘制函数 def drawScene(): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # 在此处绘制场景 glutSwapBuffers() # 定义帧速率函数 def frameRate(value): glutPostRedisplay() glutTimerFunc(1000 // value, frameRate, value) # 初始化OpenGL glutInit() glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH) glutInitWindowSize(640, 480) glutCreateWindow("OpenGL Frame Rate Test") # 设置场景绘制函数 glutDisplayFunc(drawScene) # 设置帧速率函数 frameRate(60) # 开始主循环 glutMainLoop() ``` 在上面的示例中,我们定义了一个名为frameRate()的函数,该函数使用glutTimerFunc()函数来设置帧速率。在初始化OpenGL之后,我们将frameRate()函数传递给glutTimerFunc()函数,以便在每个时间间隔后调用该函数。在frameRate()函数中,我们使用glutPostRedisplay()函数告诉OpenGL重新绘制场景,并使用glutTimerFunc()函数来设置下一个时间间隔。最后,我们使用glutMainLoop()函数开始主循环,以便OpenGL可以处理事件并绘制场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值