日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenGL-动画

發布時間:2023/12/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenGL-动画 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
動畫:就是連續播放一系列圖片的過程,如果每秒播放超過24張圖片則會認為是連續的,每秒播放的越多,則越平滑。

1.雙緩沖技術

計算機上的動畫和實際動畫的不同之處:實際的動畫都是提前畫好了,播放的時候直接拿出來顯示就可以。計算機動畫則是,畫一張,拿一張,并不是提前畫好的。這樣會出現一個問題,就是對于簡單動畫,計算機畫的速度可以跟上播放的速度,那么對于復雜的動畫,則繪制時間較長,可能還沒繪制完畢,就得顯示,那么對于這種問題,提出了一種解決方案,稱之為 雙緩沖技術。所謂的雙緩沖技術就是:就是設置兩塊畫面繪制區域,一塊作為發送到顯示器的數據,一塊作為繪畫的區域,在適當的時候交換它們,由于交換兩塊內存區域實際上只需交換兩個指針即可,這一方法效率非常高,所以被廣泛采用。 // 啟用雙緩沖功能, 使用GLUT 工具包 main函數里面這樣寫 glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); // GLUT_SINGLE 表示單緩沖,改成GLUT_DOUBLE 就表示雙緩沖

2. 實現連續動畫

在實現連續動畫的時候,一般方法是:如果你需要繪制窗口了,那就請調用 myDispaly函數。單由于我們的程序無法知道究竟在什么時候該繪制,因為 一般的窗口操作系統,都是支持多窗口同時顯示。恰好你的程序窗口被別的 窗口遮住,然后用戶又把原來的窗口移開,這樣就需要對窗口進行重新繪制。 然而這一切,我們無法預料,只能委托操作系統代為辦理。這里我們使用glutIdleFunc 來實現在 cpu 空閑時間來調用繪制窗口函數, 重新繪制窗口,實現動畫效果。 // 太陽 月亮 地球案例 #include <GL/glut.h> static int day = 200; void myDispay(void) {glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(75, 1, 1, 400000000);glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(0, -200000000, 200000000, 0, 0, 0, 0, 0, 1);// 繪制紅色的“太陽”glColor3f(1.0f, 0.0f, 0.0f);glutSolidSphere(69600000, 20, 20);// 繪制藍色的“地球”glColor3f(0.0f, 0.0f, 1.0f);glRotatef(day/360.0*360.0, 0.0f, 0.0f, -1.0f);glTranslatef(150000000, 0.0f, 0.0f);glutSolidSphere(15945000, 20, 20);// 繪制黃色的“月亮”glColor3f(1.0f, 1.0f, 0.0f);glRotatef(day/30.0*360.0 - day/360.0*360.0, 0.0f, 0.0f, -1.0f);glTranslatef(38000000, 0.0f, 0.0f);glutSolidSphere(4345000, 20, 20);glFlush();// 這里繪制完畢后,需要交換緩沖區glutSwapBuffers(); } void myIdle(void) {/*作用是把日期往后移動一天,并重新繪制 達到動畫效果*/if(++day >= 360){day = 0;}myDisplay(); // 重新繪制窗口 } int main(int argc,char *argv[]) {glutInit(&argc,argv);// 使用雙緩沖區glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);glutInitWindowPostion(100,100);glutInitWindowSize(400,400);glutCreateWindow("太陽,地球和月亮");glutDisplayFunc(&myDisplay);// 該句 改變day 重新繪制窗口、 實現動畫效果// glutIdleFunc 可以使得CPU 在空閑時間 調用某一函數干某些事情glutIdleFunc(&myIdle);glutMainLoop();return 0; }

3. 垂直同步

由于顯示器的刷新頻率有限,如果讓計算機繪制一個簡單圖形,則有可能一秒鐘 繪制上萬次,因此,如果最大限度的利用計算機處理能力,繪制出很多副畫面, 但是顯示器的刷新速度卻跟不上,這樣不僅造成性能的浪費,還有可能帶來一些負 面影響(比如 當顯示器只刷新到一半時候,需要繪制的內容變化了,由于顯示器 是逐行刷新,所以會導致顯示器上半部分和下班部分是來自兩幅不同的畫面。)采用垂直同步技術可以解決這一問題。當只有在顯示器刷新時候,才把繪制好的圖 像傳輸顯示。這樣,計算機就不必去繪制大量的根本用不到的圖像了。單也存在問題:若刷新頻率為60Hz,在簡單場景,繪制一幅畫需要的時間很短, 幀速可以恒定60FPS(60幀/s),若場景復雜,繪制一幅畫的時間超過了1/60秒,則 幀速將急劇下降,如果繪制一幅畫時間為 1/50,則在第一個1/ 60 秒時,顯示器 需要刷新了,但由于新的圖沒有繪制好,所以只能顯示原來的圖畫,等到下一個 1/60 秒時才顯示新圖畫,于是顯示一幅畫實際上用了1 /30 秒,幀數為30FPS。試想如果一幅圖的復雜程度不一致,且繪制它們的時間都在1/60,則在1/60時間內 畫完,則幀數為60FPS,,在1/60時間未完成,幀速為30FPS,這樣就造成幀速跳動。

4. 計算幀速

定義: 幀速就是一秒鐘內播放的畫面數目(FPS) #include <time.h> double CalFrequency() {/*幀速計算*/static int cout;static double save;static clock_t last,current;double timegap;++count;if(cout <= 50){return save;}count = 0;last = current;current = clock();timegap = (current - last) / (double)CLK_TCK;save = 50.0 / timegap; // 按照 50FPS 計算 瞬時幀速return save; }

天體運動完整代碼

#include <GL/glut.h> #include <stdio.h> #include <time.h>static int day = 200; double CalFrequency() {/* 計算幀速*/static int count;static double save;static clock_t last, current;double timegap;++count;if( count <= 50 ){return save;}count = 0;last = current;current = clock();timegap = (current-last)/(double)CLK_TCK;save = 50.0/timegap;return save; } void myDisplay(void) {double FPS = CalFrequency();printf("FPS = %lf\n", FPS);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(75, 1, 1, 400000000);glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(0, -200000000, 200000000, 0, 0, 0, 0, 0, 1);// 繪制紅色的“太陽”glColor3f(1.0f, 0.0f, 0.0f);glutSolidSphere(69600000, 20, 20);// 繪制藍色的“地球”glColor3f(0.0f, 0.0f, 1.0f);glRotatef(day/360.0*360.0, 0.0f, 0.0f, -1.0f);glTranslatef(150000000, 0.0f, 0.0f);glutSolidSphere(15945000, 20, 20);// 繪制黃色的“月亮”glColor3f(1.0f, 1.0f, 0.0f);glRotatef(day/30.0*360.0 - day/360.0*360.0, 0.0f, 0.0f, -1.0f);glTranslatef(38000000, 0.0f, 0.0f);glutSolidSphere(4345000, 20, 20);glFlush();glutSwapBuffers(); } void myIdle(void) {++day;if( day >= 360 ){day = 0;}myDisplay(); } int main(int argc,char* argv[]) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);glutInitWindowPosition(100, 100);glutInitWindowSize(400, 400);glutCreateWindow("太陽,地球和月亮");glutDisplayFunc(&myDisplay);glutIdleFunc(&myIdle);glutMainLoop();return 0; }

總結

以上是生活随笔為你收集整理的OpenGL-动画的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。