1. 介紹
GLUT 代表 OpenGL 應用工具包,英文全稱爲 OpenGL Utility Toolkit,是一個和窗口系統無關的軟件包,可以跨平臺使用,而 freeglut 是 GLUT 的一個完全開源替代庫,對 GLUT 進行了擴展,本文使用的就是 freeglut 開源庫。
2. glut 部分函數詳解
void glut Init(int *argc, char **argv);
這個函數用來初始化 GLUT 庫,這個函數的參數從 main 函數獲取,也可以直接定義,格式比較固定,如下所示:
int numInit = 1;
char* InitDummy = "";
glutInit(&numInit, &InitDummy);
void glutInitDisplayMode(unsigned int mode);
這個函數設置圖形的顯示模式,參數 mode 可選爲:
- GLUT_RGBA:默認的使用模式,表示欲簡歷 RGBA 模式的窗口。
- GLUT_SINGLE:只使用單緩存
- GLUT_DOUBLE:使用雙緩存,避免在刷新圖形的時候出現
閃屏
,白屏
或者圖形不動的問題,在顯示動畫是很有用。 - GLUT_DEPTH:使用深度緩存
多個選項可以同時使用,如下所示:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); // 雙緩衝緩衝,RGBA格式
void glutInitWindowPosition(int x, int y);
設置初始窗口的位置,窗口左上角相對於桌面座標(x,y),如下所示:
glutInitWindowPosition(1, 1);
void glutInitWindowSize(int width, int height);
設置初始窗口的大小,width 爲窗口圖形的列數,height 爲窗口圖形的行數,如下所示:
glutInitWindowSize(512, 512);
void glutMainLoop(void);
讓glut程序進入事件循環.在一個glut程序中最多隻能調用一次,且必須調用.一旦調用,會直到程序結束才返回。而 freeglut 庫對該函數進行了擴展,對應的是glutMainLoopEvent()
,該函數可以自動退出。
glutMainLoop();
或
glutMainLoopEvent();
int glutCreateWindow(const char *title);
產生一個頂層的窗口。title作爲窗口的名字,也就是窗口標題欄顯示的內容。返回值是生成窗口的標記符,可用函數glutGetWindow()
加以引用,也可以使用glutDestroyWindow(int win)
函數將其銷燬。用法如下:
int win = glutCreateWindow("figure");
...
glutDestroyWindow(win);
void glutPostRedisplay(void);
標記當前窗口的圖像層需要重新繪製,在glutMainLoop
或glutMainLoopEvent
函數的事件處理循環的下一個循環中,將調用該窗口的顯示回調函數重繪該窗口的圖像層。在動畫顯示中非常有用。用法如下:
glutPostRedisplay();
void glutSwapBuffers(void);
當窗口模式爲雙緩存時,此函數的功能就是把後臺緩存的內容交換到前臺顯示。當然,只有單緩存時,使用它的功能跟用glFlush()一樣。而使用雙緩存是爲了把完整圖畫一次性顯示在窗口上,或者是爲了實現動畫。用法如下:
glutSwapBuffers();
void glutSetOption ( GLenum option_flag, int value );
設置窗口的狀態和選項。
+ GLUT_ACTION_ON_WINDOW_CLOSE
+ GLUT_ACTION_EXIT
+ GLUT_ACTION_GLUTMAINLOOP_RETURNS
+ GLUT_ACTION_CONTINUE_EXECUTION
用法如下:
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
void glutDisplayFunc(void (*func)(void));
註冊當前窗口的顯示回調函數。參數 func 爲 void func() 的函數,完成具體的繪製操作這個函數告訴 GLUT 當窗口內容必須被繪製時,那個函數將被調用。當窗口改變大小或者從被覆蓋的狀態中恢復,或者由於調用glutPostRedisplay()
函數要求GLUT更新時,執行func參數指定的函數。用法如下:
static void Display(void)
{
Bitmap *bitmap = *(get_bitmap_ptr());
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawPixels(bitmap->col, bitmap->row, GL_RGBA, GL_UNSIGNED_BYTE, bitmap->pixels);
glFlush();
glutSwapBuffers(); // 雙緩衝緩存
}
...
glutDisplayFunc(Display);
void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y));
註冊當前窗口的鍵盤迴調函數,參數 func 爲 void func(unsigned char key, int x, int y),key 爲按鍵的ASCII碼x,y 爲當按下鍵時鼠標的座標,相對於窗口左上角,以像素爲單位,當敲擊鍵盤按鍵(除了特殊按鍵,即glutSpecialFunc()
中處理的按鍵,詳見glutSpecialFunc()
)時調用。用法如下:
void processKeys(unsigned char key, int x, int y)
{
if (key == 27)
{
glutLeaveMainLoop();
}
}
3. 一個例子
首先定義一個 Bitmap 類,需要把freeglut.h
,freeglut_ext.h
,freeglut_std.h
,glut.h
,freeglut.lib
,freeglut.dll
添加到相應的庫目錄。
class Bitmap
{
public:
unsigned char *pixels; // 指向數據的內存區域
int col, row; // 寬和高
/* 構造函數,初始化 */
Bitmap(int width, int height)
{
Bitmap **bitmap = get_bitmap_ptr();
*bitmap = this;
pixels = (unsigned char*)malloc(width * height * 4 * sizeof(unsigned char));
memset(pixels, 0, width * height * 4 * sizeof(unsigned char));
col = width;
row = height;
}
/* 析構函數 */
~Bitmap()
{
delete[] pixels;
}
/* 圖像內存首地址*/
unsigned char* get_ptr(void) const
{
return pixels;
}
/* 顯示初始化 */
void DisplayInit()
{
int numInit = 1;
char* InitDummy = "";
glutInit(&numInit, &InitDummy); // 初始化
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); // 雙緩衝緩衝,RGBA格式
glutInitWindowPosition(1, 1); // 窗口起始位置,相對顯示器的左上角位置
glutInitWindowSize(col, row); // 窗口初始大小
glutCreateWindow("bitmap"); // 創建窗口
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
}
/* 顯示更新 */
void Imshow()
{
glutDisplayFunc(Display); // 顯示
glutMainLoopEvent(); // 使用glutMainLoop() 將不會退出
glutPostRedisplay(); // 刷新
}
private:
// static method used for glut callbacks
static Bitmap** get_bitmap_ptr(void)
{
static Bitmap *gBitmap;
return &gBitmap;
}
/* 顯示函數 */
static void Display(void)
{
Bitmap *bitmap = *(get_bitmap_ptr());
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawPixels(bitmap->col, bitmap->row, GL_RGBA, GL_UNSIGNED_BYTE, bitmap->pixels);
glFlush();
glutSwapBuffers(); // 雙緩衝緩存
}
};
使用類:
int col = 512;
int row = 512;
Bitmap bitmap(col, row);
unsigned char *ptr = bitmap.get_ptr();
bitmap.DisplayInit(); // 初始化
for(;;)
{
/* 此處完成圖像的更新 */
bitmap.Imshow();
}
上述代碼就可以完成一個動畫的繪製和顯示,其中的幾個如下所示: