前置步驟(安裝依賴庫):
- sudo apt-get update
- sudo apt-get install build-essential
- sudo apt-get install libgl1-mesa-dev
- sudo apt-get install libglu1-mesa-dev
- $sudo apt-get install freeglut3-dev
- sudo apt-get install libfreeimage3 sudo apt-get install libfreeimage-dev
1.測試OpenGL環境
#include<GL/glut.h> void init() { glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); glOrtho(-5, 5, -5, 5, 5, 15); gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0); return ; } void display(void) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 0, 0); glutWireTeapot(3); glFlush(); return; } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowPosition(0, 0); glutInitWindowSize(300, 300); glutCreateWindow("OpenGL #D View"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; }
編譯:
gcc test.c -o test -lGL -lGLU -lglut
運行:
如果能出現這個圖片,證明環境配置成功。
2.旋轉地球模型
#include<stdio.h> #include<stdlib.h> #include<GL/glut.h> #include<GL/gl.h> #include<GL/glu.h> #include<FreeImage.h> #define GLUT_WHEEL_UP 3 #define GLUT_WHEEL_DOWN 4 struct _AUX_RGBImageRec { unsigned long sizeX; unsigned long sizeY; unsigned char *data; }; typedef struct _AUX_RGBImageRec AUX_RGBImageRec; GLuint texture[1]; //存儲一個紋理 GLfloat rtri; //存儲旋轉變量,不斷改變器值 GLfloat zoom = 1.0f; //縮放程度,默認位1,用於放大或縮小 GLfloat xpos = 0.f; //x方向移動 GLfloat ypos = 0.f; //y方向移動 void init(); void display(void); void reshape(int w, int h); void keyboard(unsigned char key, int x, int y); void processMouse(int button, int state, int x, int y); void changeParam(); int LoadGLTextures(); GLboolean LoadBmp(const char *filename, AUX_RGBImageRec* texture_image); int main(int argc, char **argv) { glutInit(&argc, argv); //GLUT環境初始化 //顯示模式初始化 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); //定義窗口daxiao glutInitWindowSize(600, 600); //定義窗口位置 glutInitWindowPosition(400, 600); //顯示窗口位置,窗口標題為執行函數名 glutCreateWindow("EarthDemo"); //調用OpenGL初始化函數 init(); //注冊OpenGL繪圖函數 glutDisplayFunc(display); //注冊窗口大小改變時的響應函數 glutReshapeFunc(reshape); //注冊鍵盤響應事件 glutKeyboardFunc(keyboard); //注冊鼠標響應事件 glutMouseFunc(processMouse); ////注冊自動旋轉的函數 glutIdleFunc(changeParam); //進入GLUT消息循環,開始執行函數 glutMainLoop(); return 0; } /*初始化openGL*/ void init() { LoadGLTextures(); //載入紋理 glEnable(GL_TEXTURE_2D); //啟動紋路映射 glShadeModel(GL_SMOOTH); //啟用陰影平滑 glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //黑色背景 glClearDepth(1.0f); //設置深度緩存 glClearDepth(GL_DEPTH_TEST); //啟用深度測試 glDepthFunc(GL_LEQUAL); //所作深度測試的類型 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //真正精細的透視修正 } /*載入位圖(調用上面的代碼)轉換成紋理*/ int LoadGLTextures() { int Status = FALSE; //狀態指示器 AUX_RGBImageRec *textureImage; //創建紋理的存儲空間 textureImage = malloc(sizeof(AUX_RGBImageRec)); //載入位圖,檢查有無錯誤,如果位圖沒找到則退出 if (LoadBmp("earth.bmp", textureImage)) { Status = TRUE; glGenTextures(1, &texture[0]); //創建紋理的存儲空間 /*使用來自位圖數據生成的典型紋理*/ glBindTexture(GL_TEXTURE_2D, texture[0]); /*生成紋理*/ glTexImage2D(GL_TEXTURE_2D, 0, 3, textureImage->sizeX, textureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, textureImage->data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } //紋理是否存在 if (textureImage) { //紋理圖像是否存在 if (textureImage->data) { free(textureImage->data); //釋放紋理圖像占用的內存 } free(textureImage); //釋放圖像結構 } return Status; } void display(void) { glClear(GL_COLOR_BUFFER_BIT); //清楚平面和深度緩存 glLoadIdentity(); //重置當前的模型觀察矩陣 //加上xpos,ypos產生移動效果 glTranslatef(0.0f+xpos, 0.0f+ypos, -5.0f); //移入屏幕5個單位 //此處進行縮放, x,y,z,方向均按此比例縮放 glScalef(zoom, zoom, zoom); glRotatef(rtri, 0.0f, 1.0f, 0.0f); //繞Y軸旋轉 glBindTexture(GL_TEXTURE_2D, texture[0]); glBegin(GL_QUADS); //繪制四邊形 GLUquadric* quadricObj = gluNewQuadric(); //gluNewQuadric創建一個新的二次曲面對象 gluQuadricTexture(quadricObj, GL_TRUE); /*參數1:二次曲面對象指針 **參數2:球半徑 **參數3:Z軸方向片數,經度方向 **參數4:Y周方向片數,緯度方向 */ gluSphere(quadricObj, 1, 100, 100); //gluDeleteQuadric刪除一個二次曲面對象 gluDeleteQuadric(quadricObj); glEnd(); //通知硬件繪制圖像 glFinish(); return ; } /*窗口大小發生變化時調用*/ void reshape(int w, int h) { glViewport(0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //利用glOrtho創建一個正交平行的視景體 if (w <= h) { glOrtho(-1.5, 1.5, -1.5*(GLfloat)h / (GLfloat)w, 1.5 *(GLfloat)h / (GLfloat)w, -10.0, 10.0); } else { glOrtho(-1.5*(GLfloat)w / (GLfloat)h, 1.5*(GLfloat)w / (GLfloat)h, -1.5, 1.5, -10.0, 10.0); } glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } /*定義對鍵盤的響應函數*/ void keyboard(unsigned char key, int x, int y) { switch ((key)) { /*ESC鍵退出*/ case 27: exit(0); break; case '+': //放大 zoom += 0.03; break; case '-': //縮小 zoom -= 0.03; break; case 'w': //上移 ypos += 0.03; break; case 's': //下移 ypos -= 0.03; break; case 'a': //左移 xpos -= 0.03; break; case 'd': //右移 xpos += 0.03; break; default: break; } printf("Enter Key %c zoom = %lf, xpos = %lf, ypos = %lf \n", key, zoom, xpos, ypos); } //處理鼠標事件 void processMouse(int button, int state, int x, int y) { if (state == GLUT_UP && button == GLUT_WHEEL_UP) { //滾輪向上,表示放大,增大縮放比例 zoom += 0.02; printf("Mouse Wheel UP\n"); glutPostRedisplay(); } if (state == GLUT_UP && button == GLUT_WHEEL_DOWN) { //滾輪向下,表示縮小,減少縮放比例 if (zoom > 0.02) { printf("Mouse Wheel Down\n"); zoom -= 0.02; } glutPostRedisplay(); } } // 自動旋轉函數,用於修改繪制時所需要的參數 void changeParam() { rtri += 0.05f; glutPostRedisplay(); } /* *利用freeimage加載bmp圖像 *此函數在Linux系統上可以作為util調用 */ GLboolean LoadBmp(const char *filename, AUX_RGBImageRec* texture_image) { FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(filename, 0); FIBITMAP *dib = FreeImage_Load(fifmt, filename, 0); dib = FreeImage_ConvertTo24Bits(dib); int width = FreeImage_GetWidth(dib); int height = FreeImage_GetHeight(dib); BYTE *pixels = (BYTE*) FreeImage_GetBits(dib); int pix = 0; if (texture_image == NULL) { return FALSE; } texture_image->data = (BYTE*) malloc(width * height * 3); texture_image->sizeX = width; texture_image->sizeY = height; for (pix = 0; pix < width * height; pix++) { texture_image->data[pix*3 + 0] = pixels[pix * 3 + 2]; texture_image->data[pix*3 + 1] = pixels[pix * 3 + 1]; texture_image->data[pix*3 + 2] = pixels[pix * 3 + 0]; } FreeImage_Unload(dib); return TRUE; }
編譯:
gcc main.c -o main -lGL -lGLU -lglut -lfreeimage
運行: