OpenGL中的投影使用

OpenGL中的投影使用


         在OpenGL中,投影矩陣指定了可視區域的大小和形狀。對於正投影與透視投影這兩種不同的投影類型,它們分別有各自的用途。

 

正投影

         它適用於2D圖形,如文本、建築繪圖等。在它的應用場合,我們希望在屏幕上展示準確的物體大小和度量。

 



透視投影

         它使用透視除法,對距離觀察者較遠的物體進行縮短和收縮。因爲可視區域前端和後端的寬度度量方法並不相同,導致兩個邏輯大小相同的物體,當它們分別位於可視區域的前面和後面時,前者看上去要比後者大一些。

         下圖展示了平截頭體(frustum)所定義的透視投影,它的觀察方向是從狹窄端到寬闊端。工具函數gluPerspective可以方便的定義一個平截頭體:

      

         void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far);

        

         參數 fovy表示垂直方向的視野角度,aspect表示寬度與高度的縱橫比,near與far表示近端和遠端裁剪平面之間的距離。





 

         下面的代碼設置使用了透視投影,展示了一個由太陽(黃色)、地球(紅色)、月亮(灰色)三者構成的運動系統。這是一個經典的嵌套變換的例子,我們使用矩陣堆棧將一個物體根據另一個物體進行變換,運行結果如圖所示:






/* 程序清單 4-3

 * 2014/5/18

 */

#include <glut.h>

#include <math.h>

 

// 旋轉的步進值

static float fMoonRot =0.0f;

static float fEarthRot= 0.0f;

 

// 設置渲染狀態

void SetupRC()

{

         // 設置清除窗口的顏色(黑色背景)

         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

         // 設置繪圖顏色爲綠色

         glColor3f(0.0f, 1.0f, 0.0f);

         // 打開深度測試

         glEnable(GL_DEPTH_TEST);

}

 

// 繪製場景(顯示回調函數)

void RenderScene()

{

         // 用當前的清除顏色清除窗口

         glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);

         // 保存矩陣狀態(模型視圖矩陣)

         glMatrixMode(GL_MODELVIEW);

         glPushMatrix();

         // 平移座標系,注意是相對於視覺座標的位置

         glTranslatef(0.0f, 0.0f, -300.0f);

 

         // 繪製太陽

         glColor3ub(255, 255, 0);

         glutSolidSphere(15.0f, 15, 15);

         // 旋轉座標系,累加效果

         glRotatef(fEarthRot, 0.0f, 1.0f, 0.0f);

 

         // 繪製地球

         glColor3ub(255, 0, 0);

         // 平移座標系,累加效果

         glTranslatef(105.0f, 0.0f, 0.0f);

         // 設置地球的旋轉步進

         fEarthRot += 5.0f;

         if(fEarthRot > 360.0f) {

                  fEarthRot = 0.0f;

         }

         glutSolidSphere(15.0f, 15, 15);

 

         // 繪製月球

         glColor3ub(200, 200, 200);

         // 旋轉座標系,累加效果

         glRotatef(fMoonRot, 0.0f, 1.0f, 0.0f);

         // 平移座標系,累加效果

         glTranslatef(30.0f, 0.0f, 0.0f);

         // 設置月亮的旋轉步進

         fMoonRot += 15.0f;

         if(fMoonRot > 360.0f) {

                  fMoonRot = 0.0f;

         }

         glutSolidSphere(6.0f, 15, 15);

 

         // 恢復矩陣狀態(當前座標系與視覺座標重合)

         glPopMatrix();

 

         // 交換緩衝區,顯示畫面

         glutSwapBuffers();

}

 

// 當窗口大小改變時由GLUT函數庫調用

void ChangeSize(GLsizei w, GLsizei h)

{

         // 窗口的縱橫比

         GLfloat fAspect;

         // 防止被0

         if (0== h) {

                  h = 1;

         }

         // 將視口設置爲窗口的大小

         glViewport(0, 0, w, h);

         // 計算窗口的縱橫比

         fAspect = (GLfloat)w / (GLfloat)h;

         // 設置當前操作的矩陣爲投影矩陣

         glMatrixMode(GL_PROJECTION);

         glLoadIdentity();

         // 定義平截頭體, 45度視野,近、遠平面爲1.0425.0

         gluPerspective(45.0f,fAspect, 1.0, 425.0);

         // 設置當前操作的矩陣爲模型視圖矩陣

         glMatrixMode(GL_MODELVIEW);

         glLoadIdentity();

}

 

// 計時器函數,每秒觸發10次窗口重繪事件

void TimerFunc(intvalue)

{

         glutPostRedisplay();

         glutTimerFunc(100, TimerFunc, 1);

}

 

int main(int argc,char *argv[])

{

         // 傳遞命令行參數,並對GLUT函數庫進行初始化

         glutInit(&argc, argv);

         // 設置創建窗口時的顯示模式(雙緩衝區、RGB顏色模式)

         glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);

         // 設置窗口的初始大小

         glutInitWindowSize(480, 320);

         // 創建窗口

         glutCreateWindow("Bounce");

         // 設置顯示回調函數

         glutDisplayFunc(RenderScene);

         // 設置當窗口的大小發生變化時的回調函數

         glutReshapeFunc(ChangeSize);

         // 設置計時器函數

         glutTimerFunc(100, TimerFunc, 1);

         // 設置渲染狀態

         SetupRC();

         // 啓動GLUT框架的運行,一經調用便不再返回,直到程序終止

         glutMainLoop();

 

         return0;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章