OpenGL變換【轉】

 

http://www.cnblogs.com/hefee/p/3811099.html

OpenGL變換

概述

OpenGL管線中,在光柵化操做以前,包括頂點位置與法線向量的幾何數據經頂點操做與圖元裝配操做進行變換。html

  OpenGL頂點變換

模型座標

它是模型對象的局部座標系,同時也是任何變換以前模型對象的初始位置與朝向。爲了變換模型對象,可使用glRotatef()、glTranslatef()、glScalef()。數組

觀察座標

它由模型座標乘以GL_MODELVIEW矩陣產生。在OpenGL中,可使用GL_MODELVIEW矩陣將模型對象從模型空間轉換到觀察空間。GL_MODELVIEW矩陣由模型矩陣與視圖矩陣相結合組成(Mview*Mmodel)。模型變換從模型空間變換到世界空間。視圖變換從世界空間變換到觀察空間。ide

注意,OpenGL中並無獨立的攝像機(視圖)矩陣。所以,爲了模仿攝像機變換或視圖變換,場景(3D對象與光照)必須按視圖變換的逆方向變換。換句話所,OpenGL定義定義攝像機老是位於觀察空間座標的(0,0,0)點且朝向Z軸負方向,且不可以發生變換。關於GL_MODELVIEW矩陣的更詳細信息,請參考視圖變換矩陣函數

爲了計算光照,法線向量也將從模型座標變換到觀察座標。注意,法線向量的變換與頂點變換不一樣。它將法線向量與GL_MODELVIEW矩陣的逆矩陣的轉置矩陣相乘。更詳細信息,請參考法線向量變換post

裁剪座標

此時,觀察座標乘以GL_PROJECTION矩陣變換爲裁剪座標。GL_PROJECTION矩陣定義視錐體(平頭截面),定義頂點數據如何投影到屏幕(透視或正視)。之因此被稱爲裁剪座標,是由於變換後的頂點(x,y,z)經過與±w比較進行裁剪。關於GL_PROJECTION矩陣的更詳細信息,請參考投影矩陣url

規範化設備座標(MDC)

它由裁剪座標除以w產生。這被稱爲透視除法。它更接近窗口(屏幕)座標,不過它並無通過移動與按屏幕像素縮放。此時,值得範圍在3個座標軸上都規範化爲-1到1。spa

窗口座標(屏幕座標)

它由將規範化的設備座標(NDC)進行視口變換產生。NDC被縮放與平移以適應渲染屏幕。窗口座標最後通過OpenGL管線的光柵化過程變爲片斷。glViewport()用於定義最終圖像映射的渲染區域矩形。glDepthRange()用於決定窗口座標的z值。窗口座標由上述兩個函數的指定參數計算而來:3d

glViewport(x,y,w,h);code

glDepthRange(n,f);orm

視口變換公式須要再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透視椎體

遠(後)平面的頂點能夠簡單滴經過簡單三角形比率計算出來,如,左遠平面爲:

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管線中,在光柵化操做以前,包括頂點位置與法線向量的幾何數據經頂點操做與圖元裝配操做進行變換。

  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透視椎體

遠(後)平面的頂點能夠簡單滴經過簡單三角形比率計算出來,如,左遠平面爲:

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

相關文章
相關標籤/搜索