OpenGL 以相機模型模擬三維場景渲染管線,核心涉及四大座標變換:模型視圖、投影、裁剪、視口。本文系統梳理各階段數學原理、OpenGL API 對應關係與矩陣堆疊機制,助你建立清晰的三維座標空間心智模型。
| 座標系 | 定義 | 用途 |
|---|---|---|
| 物件/局部座標 | 以模型中心為原點 | 建模、旋轉/縮放以此為基準 |
| 世界座標 | 場景統一參考系 | 所有物件經模型變換後置於此 |
| 視點/相機座標 | 以相機位置為原點,-Z 為視線方向 | 視點變換結果 |
| 裁剪座標 | 投影變換後,齊次座標 (x,y,z,w) | 視景體裁剪,-w ≤ x,y,z ≤ w |
| 規範化裝置座標 (NDC) | 裁剪座標除以 w,範圍 [-1,1]³ | 裝置無關中間表示 |
| 視口/螢幕座標 | 像素座標,原點左下 | 最終光柵化輸出 |

圖 1:相機模型對應 OpenGL 座標變換管線
合併模型變換與視點變換,由 GL_MODELVIEW 矩陣控制。
glTranslatef、glRotatef、glScalef 操作物件局部座標系。gluLookAt(eyeX,eyeY,eyeZ, centerX,centerY,centerZ, upX,upY,upZ) 直觀設定相機位置、目標點、上方向。順序注意:程式碼中最後呼叫的變換最先作用於頂點(矩陣左乘)。典型順序:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(...); // 視點變換(最後呼叫,最先作用)
glTranslatef(...); // 模型平移
glRotatef(...); // 模型旋轉
glScalef(...); // 模型縮放
// 繪製物件...
由 GL_PROJECTION 矩陣控制,定義視景體,將三維場景投影至二維平面。
| 類型 | API | 視景體形狀 | 特性 | 應用 |
|---|---|---|---|---|
| 透視投影 | glFrustum/gluPerspective | 截頭錐體 | 近大遠小,符合人眼視覺 | 遊戲、模擬、漫遊 |
| 正交投影 | glOrtho/gluOrtho2D | 長方體 | 尺寸不隨距離變化 | CAD、建築圖、2D UI |

圖 2:透視投影視景體 (glFrustum/gluPerspective)

圖 3:正交投影視景體 (glOrtho/gluOrtho2D)
gluPerspective 參數:fovy (垂直視野角)、aspect (寬高比)、zNear, zFar (裁剪面距離)。
glViewport(x, y, width, height) 將 NDC [-1,1] 映射至螢幕像素區域。通常在 reshape 回呼中根據視窗大小設定。
視景體 6 面隱式裁剪外,可用 glClipPlane(GL_CLIP_PLANEi, eqn) 定義額外裁剪平面(Ax+By+Cz+D=0),需 glEnable(GL_CLIP_PLANEi) 啟用。
GLdouble eqn[4] = {1.0, 0.0, 0.0, 0.0}; // x=0 平面
glClipPlane(GL_CLIP_PLANE0, eqn);
glEnable(GL_CLIP_PLANE0);
// 繪製球體,僅保留 x≥0 部分
glDisable(GL_CLIP_PLANE0);

圖 4:自訂裁剪平面切割球體
OpenGL 維護兩個矩陣堆疊:GL_MODELVIEW (至少 32 層) 與 GL_PROJECTION (至少 2 層)。
glPushMatrix():複製當前矩陣壓入堆疊頂。glPopMatrix():彈出頂部矩陣恢復為當前。應用場景:層級模型(機械臂、骨骼動畫),子節點變換不影響父節點。
glPushMatrix(); // 保存肩關節矩陣
glTranslatef(...); // 上臂位移
glRotatef(...); // 上臂旋轉
DrawUpperArm();
glPushMatrix(); // 保存肘關節矩陣
glTranslatef(...); // 前臂位移
glRotatef(...); // 前臂旋轉
DrawForeArm();
glPopMatrix(); // 還原肘關節
glPopMatrix(); // 還原肩關節
void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)w/h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0); // 相機在 (0,0,5) 看原點
glPushMatrix();
glRotatef(angle, 0, 1, 0); // 物件自轉
glutWireTeapot(1.0);
glPopMatrix();
glutSwapBuffers();
}
掌握 OpenGL 座標變換關鍵在於:
GL_MODELVIEW/GL_PROJECTION 矩陣模式切換。gluLookAt 簡化相機控制。這是進入三維圖形程式設計的基石,建議配合實驗觀察矩陣數值變化深化理解。