在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>
<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;
}
// 繪制月球
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.0和425.0
gluPerspective(45.0f,fAspect, 1.0, 425.0);
// 設定目前操作的矩陣為模型視圖矩陣
// 計時器函數,每秒觸發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);
// 設定計時器函數
// 設定渲染狀态
SetupRC();
// 啟動GLUT架構的運作,一經調用便不再傳回,直到程式終止
glutMainLoop();
return0;