http://www.cnblogs.com/hefee/p/3811099.html
OpenGL變換
概述
OpenGL管線中,在光柵化操作之前,包括頂點位置與法線向量的幾何數據經頂點操作與圖元裝配操作進行變換。
模型坐標
它是模型對象的局部坐標系,同時也是任何變換之前模型對象的初始位置與朝向。為了變換模型對象,可以使用glRotatef()、glTranslatef()、glScalef()。
觀察坐標
它由模型坐標乘以GL_MODELVIEW矩陣產生。在OpenGL中,可以使用GL_MODELVIEW矩陣將模型對象從模型空間轉換到觀察空間。GL_MODELVIEW矩陣由模型矩陣與視圖矩陣相結合組成(Mview*Mmodel)。模型變換從模型空間變換到世界空間。視圖變換從世界空間變換到觀察空間。
注意,OpenGL中並沒有獨立的攝像機(視圖)矩陣。因此,為了模仿攝像機變換或視圖變換,場景(3D對象與光照)必須按視圖變換的逆方向變換。換句話所,OpenGL定義定義攝像機總是位於觀察空間坐標的(0,0,0)點且朝向Z軸負方向,且不能夠發生變換。關於GL_MODELVIEW矩陣的更詳細信息,請參考視圖變換矩陣。
為了計算光照,法線向量也將從模型坐標變換到觀察坐標。注意,法線向量的變換與頂點變換不同。它將法線向量與GL_MODELVIEW矩陣的逆矩陣的轉置矩陣相乘。更詳細信息,請參考法線向量變換。
裁剪坐標
此時,觀察坐標乘以GL_PROJECTION矩陣變換為裁剪坐標。GL_PROJECTION矩陣定義視錐體(平頭截面),定義頂點數據如何投影到屏幕(透視或正視)。之所以被稱為裁剪坐標,是因為變換后的頂點(x,y,z)通過與±w比較進行裁剪。關於GL_PROJECTION矩陣的更詳細信息,請參考投影矩陣。
規范化設備坐標(MDC)
它由裁剪坐標除以w產生。這被稱為透視除法。它更接近窗口(屏幕)坐標,不過它並沒有經過移動與按屏幕像素縮放。此時,值得范圍在3個坐標軸上都規范化為-1到1。
窗口坐標(屏幕坐標)
它由將規范化的設備坐標(NDC)進行視口變換產生。NDC被縮放與平移以適應渲染屏幕。窗口坐標最后經過OpenGL管線的光柵化過程變為片段。glViewport()用於定義最終圖像映射的渲染區域矩形。glDepthRange()用於決定窗口坐標的z值。窗口坐標由上述兩個函數的指定參數計算而來:
glViewport(x,y,w,h);
glDepthRange(n,f);
視口變換公式需要再NDC與窗口坐標之間進行線性關系映射:
OpenGL變換矩陣
OpenGL使用4×4矩陣。注意,矩陣中的16個元素以列優先順序存儲在1維數組中。如果你希望將它轉換為標准習慣的行優先格式,你需要進行轉置操作。
OpenGL具有4種不同類別的矩陣:GL_MODELVIEW、GL_PROJECTION、GL_TEXTIRE與GL_COLOR。你可以在代碼中通過使用glMatrixMode()切換當前類型。例如,為了選擇GL_MODELVIRE矩陣,需要使用glMatrixMode(GL_MODELVIEW)。
模型視圖矩陣(GL_MODELVIEW)
GL_MODELVIEW矩陣將視圖矩陣與模型矩陣組合成一個矩陣。為了變換視圖矩陣,需要以逆變換方式移動整個場景。gluLookAt()主要用於設置視圖變換。
最右面3列矩陣元素(m12,m13,m14)為平移變換,glTranslatef()。元素m15為其次坐標。它主要用於投影變換。
3元素集合(m0,m1,m2)、(m4,m5,m6)與(m8,m9,m10)是便於歐幾里得與仿射變換,如旋轉glRotatef()與縮放glScalef()。注意,這3個集合實際表示3個正交坐標軸:
- (m0,m1,m2):+X軸,左向量,默認(1,0,0)
- (m4,m5,m6):+Y軸,上向量,默認(0,1,0)
- (m8,m9,m10):+Z軸,前向量,默認(0,0,1)
我們可以直接通過角度或觀察向量構建GL_MODELVIEW矩陣,而不是變換函數。下面是構造GL_MODELVIEW矩陣的有用代碼:
注意,當多個變換作用於一個頂點上時,OpenGL以相反順序執行矩陣乘法。例如,當頂點首先通過MA進行變換,其次通過MB進行變換,OpenGL先執行MB×MA,然后再乘以該頂點。因此,在代碼中,后一次變換先出現,第一次變換后出現。
1
2
3
4
|
// 注意,模型對象將先平移再旋轉
glRotatef(angle, 1, 0, 0);
// 繞X軸旋轉模型對象angle角度
glTranslatef(x, y, z);
// 移動模型對象到(x,y,z
drawObject();
|
投影矩陣(GL_PROJECTION)
GL_PROJECTION矩陣用於定義視錐體。視錐體決定哪些模型對象或部分模型對象將被裁剪掉。同時,它也決定3D場景如何投影到屏幕。(請閱讀更詳盡的如何構造投影矩陣。)
OpenGL提供兩個GL_PROJECTION變換函數。glFrustum()用於產生一個透視投影,glOrtho()用於產生一個正交(平行)投影。這兩個函數都需要6個參數以指定6個裁剪面:左裁剪面、右裁剪面、下裁剪面、上裁剪面、近裁剪面與遠裁剪面。視錐體的8個頂點如下列圖片。

OpenGL透視椎體
遠(后)平面的頂點可以簡單滴通過簡單三角形比率計算出來,如,左遠平面為:

OpenGL正交椎體
對於正交投影,該比率為1,因此遠平面的左、右、下與上頂點值與近平面上的對應值相同。
你也可以使用更少參數的gluPerspective()與gluOrtho2D()函數。gluPerspective()僅僅需要4個參數:垂直視場(FOV)、寬高縱橫比與遠近裁剪面的距離。從gluPerspective()到glFrustum()的等價變換描述如下的代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// 創建對稱截面體
// 從給定4個參數(fovy, aspect, near, far)
// 轉換到glFrustum()的六個參數(l, r, b, t, n, f)
void
makeFrustum(
double
fovY,
double
aspectRatio,
double
front,
double
back)
{
const
double
DEG2RAD = 3.14159265 / 180;
double
tangent =
tan
(fovY/2 * DEG2RAD);
// 半fovY的正切值
double
height = front * tangent;
// 近平面半高度
double
width = height * aspectRatio;
// 近平面半寬度
// 參數: left, right, bottom, top, near, far
glFrustum(-width, width, -height, height, front, back);
}
|

對稱視錐體示例
然而,如果你需要建立一個非對稱視錐體,你必須直接使用glFrustum()。例如,如果你希望渲染寬場景到2個鄰接屏幕上,你可以將截面體分成兩個對稱截面體(左與右)。然后,使用每一個截面體渲染場景。
紋理矩陣(GL_TEXTURE)
紋理坐標(s,t,r,q)在紋理映射之前乘以GL_TEXTURE矩陣。默認情況下,該紋理矩陣為單位矩陣,因此紋理會完全按照你賦值紋理坐標的方式映射到模型對象。通過改變GL_TEXTURE矩陣,你可以滑動、旋轉、伸展與收縮紋理。
1
2
3
|
// 繞X軸旋轉紋理
glMatrixMode(GL_TEXTURE);
glRotatef(angle, 1, 0, 0);
|
顏色矩陣(GL_COLOR)
顏色分量(r,g,b,a)與GL_COLOR矩陣相乘。這可用於顏色空間轉換與顏色分量交換。GL_COLOR矩陣並不常用且需要GL_ARB_imaging擴展。
其他矩陣函數
glPushMatrix():將當前矩陣壓入當前矩陣棧
glPopMatrix():將當前矩陣彈出當前矩陣棧
glLoadMatrix():設置當前矩陣為單位矩陣
glLoadMatrix{fd}(m):用矩陣m替換當前矩陣
glLoadTransposeMatrix{fd}(m):用行優先矩陣m替換當前矩陣
glMultMatrix{fd}(m):將當前矩陣乘以矩陣m,並更新當前矩陣值
glMultTransposeMatrix{fd}(m):將當前矩陣乘以行優先矩陣m,並更新當前矩陣值
glGetFloatv(GL_MODELVIEW_MATRIX, m):返回GL_MODELVIEW矩陣的16個值到m
實例:模型視圖矩陣
這個例子程序展示如何使用glTranslatef()與glRotatef()操作GL_MODELVIEW矩陣。
下載源程序與二進制程序:matrixModelView.zip
注意,所有OpenGL函數調用在ModelGL.h與ModelGL.cpp中實現。
為了制定模型與相機變換,該實例程序使用自定義的4×4矩陣類與默認OpenGL矩陣函數。在ModelGL.cpp中定義3個矩陣對象:matrixModel、matrixView與matrixModelView。每個矩陣保存先前計算的矩陣,並且使用glLoadMatrix()傳遞這些矩陣元素。實際繪制程序像這樣:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
...
glPushMatrix();
// 為相機變換設置視圖矩陣
glLoadMatrixf(matrixView.getTranspose());
// 在模型變換之前繪制網格
drawGrid();
// 為模型與視圖變換設置模型視圖矩陣
// 從模型對象空間變換到觀察空間
glLoadMatrixf(matrixModelView.getTranspose());
// 在視圖與模型變換之后繪制一個茶壺
drawTeapot();
glPopMatrix();
...
|
使用模型OpenGL矩陣函數的等價代碼為:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
...
glPushMatrix();
//初始化模型視圖矩陣
glLoadIdentity();
// 首先,變換相機(視圖矩陣):從世界空間到觀察空間
// 注意所有變量都為負,因為我們將整個場景超相機變換相反方向移動
glRotatef(-cameraAngle[2], 0, 0, 1);
// roll
glRotatef(-cameraAngle[1], 0, 1, 0);
// heading
glRotatef(-cameraAngle[0], 1, 0, 0);
// pitch
glTranslatef(-cameraPosition[0], -cameraPosition[1], -cameraPosition[2]);
// 在模型變換之前在原點繪制網格
drawGrid();
// 變換模型(模型矩陣)
// GL_MODELVIEW矩陣的結果為:ModelView_M = View_M * Model_M
glTranslatef(modelPosition[0], modelPosition[1], modelPosition[2]);
glRotatef(modelAngle[0], 1, 0, 0);
glRotatef(modelAngle[1], 0, 1, 0);
glRotatef(modelAngle[2], 0, 0, 1);
// 使用模型與視圖變換繪制一個茶壺
drawTeapot();
glPopMatrix();
...
|
實例:投影矩陣
這個例子程序展示如何使用glFrustum()與glOrtho()操作投影變換。
下載源程序與二進制程序:matrixProjection.zip
同樣,ModelGL.h與ModelGL.cpp是OpenGL函數調用放置的地方。
ModelGL類使用自定義矩陣對象,matrixProjection與2個成員函數:setFrustum()與setOrthoFrustum(),這兩個函數與glFrustum()與glOrtho()等價。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
///////////////////////////////////////////////////////////////////////////
// 使用與glFrustum()相同的6個參數(left,right,bottom,top,near,far)設置透視截面體// 注意: 此處為行優先標記法。OpenGL需要對它進行轉置
///////////////////////////////////////////////////////////////////////////
void
ModelGL::setFrustum(
float
l,
float
r,
float
b,
float
t,
float
n,
float
f)
{
matrixProjection.identity();
matrixProjection[0] = 2 * n / (r - l);
matrixProjection[2] = (r + l) / (r - l);
matrixProjection[5] = 2 * n / (t - b);
matrixProjection[6] = (t + b) / (t - b);
matrixProjection[10] = -(f + n) / (f - n);
matrixProjection[11] = -(2 * f * n) / (f - n);
matrixProjection[14] = -1;
matrixProjection[15] = 0;
}
//////////////////////////////////////////////////////////////////////////////
// 使用與glOrtho()相類似的6個參數(left, right, bottom, top, near, far)設置正交投影
// 注意: 此處為行優先標記法。OpenGL需要對它進行轉置
//////////////////////////////////////////////////////////////////////////////
void
ModelGL::setOrthoFrustum(
float
l,
float
r,
float
b,
float
t,
float
n,
float
f)
{
matrixProjection.identity();
matrixProjection[0] = 2 / (r - l);
matrixProjection[3] = -(r + l) / (r - l);
matrixProjection[5] = 2 / (t - b);
matrixProjection[7] = -(t + b) / (t - b);
matrixProjection[10] = -2 / (f - n);
matrixProjection[11] = -(f + n) / (f - n);
}
...
// pass projection matrx to OpenGL before draw
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(matrixProjection.getTranspose());
...
|
英文原文:http://www.songho.ca/opengl/gl_normaltransform.html
OpenGL變換
概述
OpenGL管線中,在光柵化操作之前,包括頂點位置與法線向量的幾何數據經頂點操作與圖元裝配操作進行變換。
模型坐標
它是模型對象的局部坐標系,同時也是任何變換之前模型對象的初始位置與朝向。為了變換模型對象,可以使用glRotatef()、glTranslatef()、glScalef()。
觀察坐標
它由模型坐標乘以GL_MODELVIEW矩陣產生。在OpenGL中,可以使用GL_MODELVIEW矩陣將模型對象從模型空間轉換到觀察空間。GL_MODELVIEW矩陣由模型矩陣與視圖矩陣相結合組成(Mview*Mmodel)。模型變換從模型空間變換到世界空間。視圖變換從世界空間變換到觀察空間。
注意,OpenGL中並沒有獨立的攝像機(視圖)矩陣。因此,為了模仿攝像機變換或視圖變換,場景(3D對象與光照)必須按視圖變換的逆方向變換。換句話所,OpenGL定義定義攝像機總是位於觀察空間坐標的(0,0,0)點且朝向Z軸負方向,且不能夠發生變換。關於GL_MODELVIEW矩陣的更詳細信息,請參考視圖變換矩陣。
為了計算光照,法線向量也將從模型坐標變換到觀察坐標。注意,法線向量的變換與頂點變換不同。它將法線向量與GL_MODELVIEW矩陣的逆矩陣的轉置矩陣相乘。更詳細信息,請參考法線向量變換。
裁剪坐標
此時,觀察坐標乘以GL_PROJECTION矩陣變換為裁剪坐標。GL_PROJECTION矩陣定義視錐體(平頭截面),定義頂點數據如何投影到屏幕(透視或正視)。之所以被稱為裁剪坐標,是因為變換后的頂點(x,y,z)通過與±w比較進行裁剪。關於GL_PROJECTION矩陣的更詳細信息,請參考投影矩陣。
規范化設備坐標(MDC)
它由裁剪坐標除以w產生。這被稱為透視除法。它更接近窗口(屏幕)坐標,不過它並沒有經過移動與按屏幕像素縮放。此時,值得范圍在3個坐標軸上都規范化為-1到1。
窗口坐標(屏幕坐標)
它由將規范化的設備坐標(NDC)進行視口變換產生。NDC被縮放與平移以適應渲染屏幕。窗口坐標最后經過OpenGL管線的光柵化過程變為片段。glViewport()用於定義最終圖像映射的渲染區域矩形。glDepthRange()用於決定窗口坐標的z值。窗口坐標由上述兩個函數的指定參數計算而來:
glViewport(x,y,w,h);
glDepthRange(n,f);
視口變換公式需要再NDC與窗口坐標之間進行線性關系映射:
OpenGL變換矩陣
OpenGL使用4×4矩陣。注意,矩陣中的16個元素以列優先順序存儲在1維數組中。如果你希望將它轉換為標准習慣的行優先格式,你需要進行轉置操作。
OpenGL具有4種不同類別的矩陣:GL_MODELVIEW、GL_PROJECTION、GL_TEXTIRE與GL_COLOR。你可以在代碼中通過使用glMatrixMode()切換當前類型。例如,為了選擇GL_MODELVIRE矩陣,需要使用glMatrixMode(GL_MODELVIEW)。
模型視圖矩陣(GL_MODELVIEW)
GL_MODELVIEW矩陣將視圖矩陣與模型矩陣組合成一個矩陣。為了變換視圖矩陣,需要以逆變換方式移動整個場景。gluLookAt()主要用於設置視圖變換。
最右面3列矩陣元素(m12,m13,m14)為平移變換,glTranslatef()。元素m15為其次坐標。它主要用於投影變換。
3元素集合(m0,m1,m2)、(m4,m5,m6)與(m8,m9,m10)是便於歐幾里得與仿射變換,如旋轉glRotatef()與縮放glScalef()。注意,這3個集合實際表示3個正交坐標軸:
- (m0,m1,m2):+X軸,左向量,默認(1,0,0)
- (m4,m5,m6):+Y軸,上向量,默認(0,1,0)
- (m8,m9,m10):+Z軸,前向量,默認(0,0,1)
我們可以直接通過角度或觀察向量構建GL_MODELVIEW矩陣,而不是變換函數。下面是構造GL_MODELVIEW矩陣的有用代碼:
注意,當多個變換作用於一個頂點上時,OpenGL以相反順序執行矩陣乘法。例如,當頂點首先通過MA進行變換,其次通過MB進行變換,OpenGL先執行MB×MA,然后再乘以該頂點。因此,在代碼中,后一次變換先出現,第一次變換后出現。
1
2
3
4
|
// 注意,模型對象將先平移再旋轉
glRotatef(angle, 1, 0, 0);
// 繞X軸旋轉模型對象angle角度
glTranslatef(x, y, z);
// 移動模型對象到(x,y,z
drawObject();
|
投影矩陣(GL_PROJECTION)
GL_PROJECTION矩陣用於定義視錐體。視錐體決定哪些模型對象或部分模型對象將被裁剪掉。同時,它也決定3D場景如何投影到屏幕。(請閱讀更詳盡的如何構造投影矩陣。)
OpenGL提供兩個GL_PROJECTION變換函數。glFrustum()用於產生一個透視投影,glOrtho()用於產生一個正交(平行)投影。這兩個函數都需要6個參數以指定6個裁剪面:左裁剪面、右裁剪面、下裁剪面、上裁剪面、近裁剪面與遠裁剪面。視錐體的8個頂點如下列圖片。

OpenGL透視椎體
遠(后)平面的頂點可以簡單滴通過簡單三角形比率計算出來,如,左遠平面為:

OpenGL正交椎體
對於正交投影,該比率為1,因此遠平面的左、右、下與上頂點值與近平面上的對應值相同。
你也可以使用更少參數的gluPerspective()與gluOrtho2D()函數。gluPerspective()僅僅需要4個參數:垂直視場(FOV)、寬高縱橫比與遠近裁剪面的距離。從gluPerspective()到glFrustum()的等價變換描述如下的代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// 創建對稱截面體
// 從給定4個參數(fovy, aspect, near, far)
// 轉換到glFrustum()的六個參數(l, r, b, t, n, f)
void
makeFrustum(
double
fovY,
double
aspectRatio,
double
front,
double
back)
{
const
double
DEG2RAD = 3.14159265 / 180;
double
tangent =
tan
(fovY/2 * DEG2RAD);
// 半fovY的正切值
double
height = front * tangent;
// 近平面半高度
double
width = height * aspectRatio;
// 近平面半寬度
// 參數: left, right, bottom, top, near, far
glFrustum(-width, width, -height, height, front, back);
}
|

對稱視錐體示例
然而,如果你需要建立一個非對稱視錐體,你必須直接使用glFrustum()。例如,如果你希望渲染寬場景到2個鄰接屏幕上,你可以將截面體分成兩個對稱截面體(左與右)。然后,使用每一個截面體渲染場景。
紋理矩陣(GL_TEXTURE)
紋理坐標(s,t,r,q)在紋理映射之前乘以GL_TEXTURE矩陣。默認情況下,該紋理矩陣為單位矩陣,因此紋理會完全按照你賦值紋理坐標的方式映射到模型對象。通過改變GL_TEXTURE矩陣,你可以滑動、旋轉、伸展與收縮紋理。
1
2
3
|
// 繞X軸旋轉紋理
glMatrixMode(GL_TEXTURE);
glRotatef(angle, 1, 0, 0);
|
顏色矩陣(GL_COLOR)
顏色分量(r,g,b,a)與GL_COLOR矩陣相乘。這可用於顏色空間轉換與顏色分量交換。GL_COLOR矩陣並不常用且需要GL_ARB_imaging擴展。
其他矩陣函數
glPushMatrix():將當前矩陣壓入當前矩陣棧
glPopMatrix():將當前矩陣彈出當前矩陣棧
glLoadMatrix():設置當前矩陣為單位矩陣
glLoadMatrix{fd}(m):用矩陣m替換當前矩陣
glLoadTransposeMatrix{fd}(m):用行優先矩陣m替換當前矩陣
glMultMatrix{fd}(m):將當前矩陣乘以矩陣m,並更新當前矩陣值
glMultTransposeMatrix{fd}(m):將當前矩陣乘以行優先矩陣m,並更新當前矩陣值
glGetFloatv(GL_MODELVIEW_MATRIX, m):返回GL_MODELVIEW矩陣的16個值到m
實例:模型視圖矩陣
這個例子程序展示如何使用glTranslatef()與glRotatef()操作GL_MODELVIEW矩陣。
下載源程序與二進制程序:matrixModelView.zip
注意,所有OpenGL函數調用在ModelGL.h與ModelGL.cpp中實現。
為了制定模型與相機變換,該實例程序使用自定義的4×4矩陣類與默認OpenGL矩陣函數。在ModelGL.cpp中定義3個矩陣對象:matrixModel、matrixView與matrixModelView。每個矩陣保存先前計算的矩陣,並且使用glLoadMatrix()傳遞這些矩陣元素。實際繪制程序像這樣:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
...
glPushMatrix();
// 為相機變換設置視圖矩陣
glLoadMatrixf(matrixView.getTranspose());
// 在模型變換之前繪制網格
drawGrid();
// 為模型與視圖變換設置模型視圖矩陣
// 從模型對象空間變換到觀察空間
glLoadMatrixf(matrixModelView.getTranspose());
// 在視圖與模型變換之后繪制一個茶壺
drawTeapot();
glPopMatrix();
...
|
使用模型OpenGL矩陣函數的等價代碼為:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
...
glPushMatrix();
//初始化模型視圖矩陣
glLoadIdentity();
// 首先,變換相機(視圖矩陣):從世界空間到觀察空間
// 注意所有變量都為負,因為我們將整個場景超相機變換相反方向移動
glRotatef(-cameraAngle[2], 0, 0, 1);
// roll
glRotatef(-cameraAngle[1], 0, 1, 0);
// heading
glRotatef(-cameraAngle[0], 1, 0, 0);
// pitch
glTranslatef(-cameraPosition[0], -cameraPosition[1], -cameraPosition[2]);
// 在模型變換之前在原點繪制網格
drawGrid();
// 變換模型(模型矩陣)
// GL_MODELVIEW矩陣的結果為:ModelView_M = View_M * Model_M
glTranslatef(modelPosition[0], modelPosition[1], modelPosition[2]);
glRotatef(modelAngle[0], 1, 0, 0);
glRotatef(modelAngle[1], 0, 1, 0);
glRotatef(modelAngle[2], 0, 0, 1);
// 使用模型與視圖變換繪制一個茶壺
drawTeapot();
glPopMatrix();
...
|
實例:投影矩陣
這個例子程序展示如何使用glFrustum()與glOrtho()操作投影變換。
下載源程序與二進制程序:matrixProjection.zip
同樣,ModelGL.h與ModelGL.cpp是OpenGL函數調用放置的地方。
ModelGL類使用自定義矩陣對象,matrixProjection與2個成員函數:setFrustum()與setOrthoFrustum(),這兩個函數與glFrustum()與glOrtho()等價。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
///////////////////////////////////////////////////////////////////////////
// 使用與glFrustum()相同的6個參數(left,right,bottom,top,near,far)設置透視截面體// 注意: 此處為行優先標記法。OpenGL需要對它進行轉置
///////////////////////////////////////////////////////////////////////////
void
ModelGL::setFrustum(
float
l,
float
r,
float
b,
float
t,
float
n,
float
f)
{
matrixProjection.identity();
matrixProjection[0] = 2 * n / (r - l);
matrixProjection[2] = (r + l) / (r - l);
matrixProjection[5] = 2 * n / (t - b);
matrixProjection[6] = (t + b) / (t - b);
matrixProjection[10] = -(f + n) / (f - n);
matrixProjection[11] = -(2 * f * n) / (f - n);
matrixProjection[14] = -1;
matrixProjection[15] = 0;
}
//////////////////////////////////////////////////////////////////////////////
// 使用與glOrtho()相類似的6個參數(left, right, bottom, top, near, far)設置正交投影
// 注意: 此處為行優先標記法。OpenGL需要對它進行轉置
//////////////////////////////////////////////////////////////////////////////
void
ModelGL::setOrthoFrustum(
float
l,
float
r,
float
b,
float
t,
float
n,
float
f)
{
matrixProjection.identity();
matrixProjection[0] = 2 / (r - l);
matrixProjection[3] = -(r + l) / (r - l);
matrixProjection[5] = 2 / (t - b);
matrixProjection[7] = -(t + b) / (t - b);
matrixProjection[10] = -2 / (f - n);
matrixProjection[11] = -(f + n) / (f - n);
}
...
// pass projection matrx to OpenGL before draw
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(matrixProjection.getTranspose());
...
|