《深入了解OpenGL》第二講:頂點(diǎn)線性變換_第1頁(yè)
《深入了解OpenGL》第二講:頂點(diǎn)線性變換_第2頁(yè)
《深入了解OpenGL》第二講:頂點(diǎn)線性變換_第3頁(yè)
《深入了解OpenGL》第二講:頂點(diǎn)線性變換_第4頁(yè)
《深入了解OpenGL》第二講:頂點(diǎn)線性變換_第5頁(yè)
已閱讀5頁(yè),還剩11頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、深入了解OpenGL第二講:頂點(diǎn)線性變換時(shí)間: 2010-05-11 12:56 點(diǎn)擊: 2157 次上周發(fā)布了 深入了解OpenGL第一講:繪制基本圖元,今天CocoaChina會(huì)員 zenny_chen 帶來(lái)了OpenGL知識(shí)第二講。帖子地址 這一章節(jié)可能會(huì)比較枯燥, 上周發(fā)布了深入了解OpenGL第一講:繪制基本圖元,今天CocoaChina會(huì)員 “zenny_chen” 帶來(lái)了OpenGL知識(shí)第二講。帖子地址 這一章節(jié)可能會(huì)比較枯燥,當(dāng)然示例代碼將會(huì)非常有趣??菰锏氖菍?huì)有很多線性代數(shù)的知識(shí)夾雜其中。在本章中我們將對(duì)3D圖形進(jìn)行繪制。我們會(huì)介紹 頂點(diǎn)變換的過程,以及法線向量與繪制順序。

2、這里將首先介紹一下一個(gè)三維空間上的頂點(diǎn)被映射到二維屏幕坐標(biāo)的步驟,請(qǐng)各位務(wù)必牢記:物體頂點(diǎn)坐標(biāo)(頂點(diǎn))模型視圖變換 -> 視覺坐標(biāo)投影變換 -> 裁剪坐標(biāo)透視劃分 -> 規(guī)格化設(shè)備坐標(biāo)視口變換 -> 窗口坐標(biāo)上圖中,表示經(jīng)過某種變換;-> 表示得到某個(gè)坐標(biāo)。下面我們將根據(jù)這個(gè)順序來(lái)依次介紹各個(gè)變 換。這里將主要介紹模型視圖變換和投影變換。先介紹OpenGL中物體頂點(diǎn)坐標(biāo)的表示。OpenGL中,物體的頂點(diǎn)坐標(biāo)是由一個(gè)四維的行向量來(lái)表示的,表示為:(x, y, z, w)。其中,x, y, z分別對(duì)應(yīng)x軸、y軸和z軸,而w用于輔助做線性變換。我們會(huì)理所當(dāng)然地認(rèn)為,三維

3、坐標(biāo)系只要三個(gè)分量就夠了,w到底有何用呢?我們這里首先要說(shuō) 明一下,在OpenGL中,線性變換矩陣的變換都是用矩陣的乘法,沒有加減法,因此所有線性變換都是通過矩陣的乘法來(lái)完成的。所以,比如說(shuō)我們要把一個(gè)頂 點(diǎn):(1, 1, 1)沿x軸向右平移5個(gè)單位,那要用三維變換矩陣表示的話就要是:M = 6, 0, 0; 0, 1, 0; 0, 0, 1。那么v' = v * M = (6, 1, 1)。但很多場(chǎng)合下使用三維空間做變換將會(huì)使計(jì)算變得非常復(fù)雜,甚至很難進(jìn)行變換,因此引入 四維空間使得變換更加靈活。比如,頂點(diǎn)v = (1, 1, 1, 1)沿x軸向右平移5個(gè)單位,那么變換矩陣M = 1

4、, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 5, 0, 0, 1。我們將看到這個(gè)4x4的變換矩陣與3x3的相比就顯得簡(jiǎn)單很多。因 為對(duì)于平移來(lái)說(shuō),本身就是加法,而三維空間中就需要使用乘法,從而加大了計(jì)算負(fù)荷。在OpenGL中,物體的頂點(diǎn)坐標(biāo)在進(jìn)行計(jì)算時(shí)總是以行向量的 形式表示,并且計(jì)算時(shí)總是在最左邊。下面將正式介紹視圖各種變換。先貼代碼:推薦精選1. - (void)prepareOpenGL2. 3.     glShadeModel(GL_SMOOTH);4.     5.  

5、;   glClearColor(0.0, 0.0, 0.0, 0.0);6.     glViewport(0, 0, 320, 320);7.  8.     glMatrixMode(GL_PROJECTION);9.     glLoadIdentity();10.     glOrtho(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0);11.   &#

6、160; 12.     glMatrixMode(GL_MODELVIEW);13.     glLoadIdentity();14.     glTranslatef(0.3f, 0.2f, 0.0f);15.     glRotatef(-30.0f, 0.0f, 0.0f, 1.0f);16.     17.     glFrontFace

7、(GL_CCW);18.     glEnable(GL_CULL_FACE | GL_DEPTH_TEST);19. 20.  21. - (void)drawRect:(NSRect)dirtyRect 22.     23.     static struct24.     25.         GLubyte colours4;26. &

8、#160;       GLfloat vertices3;27.         28.     vertexInfoList = 29.          255, 0, 0, 255, -0.5f, 0.5f, -1.0f ,30.        

9、60; 0, 255, 0, 255, -0.5f, -0.5f, -1.0f ,31.          0, 0, 255, 255, 0.5f, 0.5f, -2.0f ,推薦精選32.          255, 0, 255, 255, 0.5f, -0.5f, -2.0f 33.     34.     35.    

10、; / Drawing code here.36.     glClear(GL_COLOR_BUFFER_BIT);37.     38.     glInterleavedArrays(GL_C4UB_V3F, 0, vertexInfoList);39.     40.     glCullFace(GL_BACK);41.     glDr

11、awArrays(GL_TRIANGLE_STRIP, 0, 4);42.     43.     glFlush();44. 下面介紹視圖模型變換。視圖模型變換是將三維物體的頂點(diǎn)做平移、旋轉(zhuǎn)等操作。我們可以這么理解,我們把攝像機(jī)鏡頭固定好,然后觀察物體的移動(dòng)行 為。在上述代碼的第12行,glMatrixMode(GL_MODELVIEW);用于將當(dāng)前矩陣變換的操作作用到視圖模型變換棧上。 glLoadIdentity();作用是將當(dāng)前的矩陣作為單位矩陣,即:1, 0, 0, 0; 0, 1, 0, 0; 0, 0

12、, 1, 0; 0, 0, 0, 1。其實(shí)際效果就是:C = I;其中,C表示本矩陣模式的當(dāng)前矩陣,I表示單位矩陣。glTranslatef(0.3f, 0.2f, 0.0f);是平移變換,函數(shù)原型為: void glTranslated( GLdouble x, GLdouble y, GLdouble z);void glTranslatef( GLfloat x, GLfloat y, GLfloat z); 其中,x表示沿x軸平移多少單位;y表示沿y軸平移多少單 位;z表示沿z軸平移多少單位。而,其對(duì)應(yīng)的平移變換矩陣就是:1, 0, 0, 0; 0, 1, 0, 0

13、; 0, 0, 1, 0; x, y, z, 1。那么glTranslatef(0.3f, 0.2f, 0.0f);實(shí)際效果就是:C' = T * C = T * I。因?yàn)槲覀儎偛耪{(diào)用了glLoadIdentity,因此在調(diào)用此函數(shù)時(shí)的當(dāng)前矩陣就是I。而下面的glRotatef(-30.0f, 0.0f, 0.0f, 1.0f);則是將所要繪制的物體的每個(gè)頂點(diǎn)坐標(biāo)繞z軸,順時(shí)針旋轉(zhuǎn)30度。下面給出glRotatef的原型:推薦精選 void glRotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z);void

14、glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z);其中,angle表示角度制的角度;x、y和z表示繞著由x、 y和z構(gòu)成的向量進(jìn)行旋轉(zhuǎn)。如果angle大于0,則做逆時(shí)針旋轉(zhuǎn),小于0做順時(shí)針旋轉(zhuǎn),等于0不動(dòng)。由于glRotate所對(duì)應(yīng)的變換矩陣比較 復(fù)雜,各位可以參考OpenGL官網(wǎng)上的手冊(cè)。如果將旋轉(zhuǎn)變換矩陣表示為R的話,那么這里調(diào)用R的效果其實(shí)就是:C' = R * C。那么將上面所有的串起來(lái)就是:C' = R * (T * I)。如果頂點(diǎn)單純地只經(jīng)過視圖模型變換,那么對(duì)于物體其中一個(gè)頂點(diǎn)v而言,變換后的頂點(diǎn)

15、v' = v * (R * (T * I)。我們這 里實(shí)際上是先對(duì)物體做繞z軸旋轉(zhuǎn),然后再平移。但是調(diào)用的時(shí)候必須先調(diào)平移函數(shù),再調(diào)旋轉(zhuǎn)函數(shù)。下面在介紹投影變換前再介紹幾個(gè)對(duì)矩陣操作的函數(shù),首先是glLoadMatrix,下面先給出函數(shù)原型: void glLoadMatrixd( const GLdouble * m); / 只能用于OpenGLvoid glLoadMatrixf( const GLfloat * m);void glLoadMatrixx( const GLfixed * m); / 只能用于OpenGL ES 該函數(shù)表示在當(dāng)前變換矩陣模式下將

16、矩陣m取代當(dāng)前的變換矩陣。 比如,glLoadIdentity可以用一下代碼替換:  glLoadMatrixf(const GLfloat) 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); 推薦精選然后是再介紹一下glMultMatrix函數(shù),請(qǐng)參 看函數(shù)原型: void glMultMatrixd( const GLdouble * m); / 僅用于OpenGLvoid glMultMatrixf( const G

17、Lfloat * m);void glMultMatrixx( const GLfixed * m); / 僅用于OpenGL ES 這個(gè)函數(shù)就很直白地表示用矩陣m與當(dāng)前矩陣相乘,然后將結(jié)果再 給回當(dāng)前矩陣。即:C' = M * C。我們可以用一下代碼替換glTranslatef:  glMultMatrixf(const GLfloat) 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.3f, 0.2f, 0.0f, 1.0f); 將上述代碼替換掉3樓的第

18、14行,效果不變。下面介紹投影變換。投影變換就好像為照相機(jī)選擇鏡頭。我們可以認(rèn)為這種變換的目的就是確定視野(或視景體)。并且確定哪些物體位于視野之內(nèi)以及它 們能夠被看到的程度。投影變換主要有兩種,一種是透視投影(Perspective Projection)。這種投影效果就像是玩第一人稱游戲或是第一人稱的賽車類游戲。你向前看具有透視效果,遠(yuǎn)處的物體顯得小,近處的物體顯得大。還 有一種投影是正交投影(Orthographic Projection)。這種投影是將頂點(diǎn)以平行于視野的角度垂直地映射到屏幕上。物體不管離你多遠(yuǎn),其大小都是一樣的。透視投影對(duì)應(yīng)的函數(shù) 為:glFrustum,函數(shù)原型如下:

19、 void glFrustum( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearVal, GLdouble farVal); / OpenGL推薦精選void glFrustumf( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far); / OpenGL ES   void glFrustumx( GLfixed left, GLfixed right,

20、GLfixed bottom, GLfixed top, GLfixed near, GLfixed far); / OpenGL ES  其中,left表示x軸坐標(biāo)最左端的值,right表示x坐標(biāo) 最右端的值,bottom表示y軸坐標(biāo)最下端的值,top表示y軸最上端的值,near表示與攝像機(jī)或你的眼鏡最近的距離,far表示攝像機(jī)或離你的眼鏡 最遠(yuǎn)的距離。near和far都大于0方有效。而正交投影的定義與透視投影的類似,下面給出函數(shù)原型: void glOrtho( GLdouble left, GLdouble right, GLdouble bottom, GLdoub

21、le top, GLdouble nearVal, GLdouble farVal); / OpenGL void glOrthof( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far); / OpenGL ES void glOrthox( GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed near, GLfixed far); / OpenGL ES首先,各位可以先用glF

22、rustum來(lái)替換glOrtho,看看效果,呵呵。然后我們看3樓代碼29到32行,為什么這里z坐標(biāo)為-1 和-2?因?yàn)槲覀冋{(diào)用了glOrtho(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0);也就是說(shuō)你的視野最近看到的距離為1,最遠(yuǎn)是5。由于你的視野是正對(duì)屏幕的,也就是朝z軸的負(fù)方向。因此這里必須把物體沿z軸移到你的視野范圍 內(nèi)才能看到物體。如果我們把物體頂點(diǎn)的z軸值改為大于-1或小于-5,那偶們就看不見該頂點(diǎn)了,呵呵。好。那么我們現(xiàn)在結(jié)合模型視圖變換 和投影變換。那么它們的調(diào)用順序是何如的呢?我們?cè)?樓知道,視圖的變換步驟是先經(jīng)過視圖模型變換,然后再經(jīng)過投影變換。因此對(duì)于一個(gè)

23、頂點(diǎn)v來(lái) 說(shuō),若視圖模型變換矩陣是M,而投影變換矩陣為P,那么變換后的頂點(diǎn)v' = v * (M * P)。我們不妨可以做個(gè)實(shí)驗(yàn)。為了能證明這個(gè)步 驟,我們將投影變換改為透視投影,即,將glOrtho改為glFrustum,觀察圖形。然后我們做以下修改:推薦精選復(fù)制代碼 1. - (void)prepareOpenGL2. 3.     glShadeModel(GL_SMOOTH);4.     5.     glClearColor(0.0, 0.0, 0.0,

24、0.0);6.     glViewport(0, 0, 320, 320);7.  8.     glMatrixMode(GL_PROJECTION);9.     glLoadIdentity();10.     /glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0);11.     12.     glMatr

25、ixMode(GL_MODELVIEW);13.     glLoadIdentity();14.     15.     glMultMatrixf(const GLfloat)16.         1.0f, 0.0f, 0.0f, 0.0f,17.         0.0f, 1.0f, 0.0f, 0.0f,

26、18.         0.0f, 0.0f, -1.5f, -1.0f,19.         0.0f, 0.0f, -2.5f, 0.0f20.     );21.     22.     glTranslatef(0.3f, 0.2f, 0.0f);    23. 

27、60;   glRotatef(-30.0f, 0.0f, 0.0f, 1.0f);24.     25.     glFrontFace(GL_CCW);26.     glEnable(GL_CULL_FACE | GL_DEPTH_TEST);27. 28.  29. - (void)drawRect:(NSRect)dirtyRect 30.     31.   

28、60; static struct32.     33.         GLubyte colours4;34.         GLfloat vertices3;35.         推薦精選36.     vertexInfoList = 37.  

29、        255, 0, 0, 255, -0.5f, 0.5f, -1.0f ,38.          0, 255, 0, 255, -0.5f, -0.5f, -1.0f ,39.          0, 0, 255, 255, 0.5f, 0.5f, -2.0f ,40.       

30、60;  255, 0, 255, 255, 0.5f, -0.5f, -2.0f 41.     42.     43.     / Drawing code here.44.     glClear(GL_COLOR_BUFFER_BIT);45.     46.     glInterleavedArrays(GL_C4UB_V3F, 0,

31、vertexInfoList);47.     48.     glCullFace(GL_BACK);49.     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);50.     51.     glFlush();52. 我 們會(huì)發(fā)現(xiàn)這個(gè)形狀與調(diào)用glFrustum的形狀完全一樣,看上去像個(gè)直角梯形。而如果我們將上面15到20行的代碼搬到第24行,那么我們將會(huì)看到

32、一個(gè)接近于等腰梯形的圖形,顯然與原來(lái)的不符,呵呵。而上述代碼中:  glMultMatrixf(const GLfloat) 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.5f, -1.0f, 0.0f, 0.0f, -2.5f, 0.0f ); 其實(shí)就等價(jià)于調(diào)用: glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0); 上面那個(gè)是與下面glFrustum調(diào)用相對(duì)應(yīng)的變換矩陣。好, 接下去我們準(zhǔn)備開始話3D圖形。上面忘記說(shuō)了,投影矩陣與模型視圖矩

33、陣是分開來(lái)的。也就是說(shuō)glMatrixMode(GL_PROJECTION);所指定指定的投影變換矩陣棧與 glMatrixMode(GL_MODELVIEW);所指定的模型視圖變換矩陣棧是相互獨(dú)立的。而投影變換矩陣變換的最終結(jié)果我們?cè)O(shè)為P,而 模型視圖變換矩陣的最終得出的變換矩陣我們?cè)O(shè)為M。所以上述公式中的P和M是這么得到的。我們?cè)诤笮蛘鹿?jié)中將會(huì)介紹對(duì)矩陣棧的操作。好。我們下面將談?wù)劽娴某?。這個(gè)對(duì)于裁剪背面以及光照都有用。我們知道一張紙有正反兩個(gè)面。在OpenGL中,一個(gè)平面可以想像為一張紙,也有 兩個(gè)面。如果你沒有指定要裁剪掉看不見的反面,那么反面也會(huì)被繪制。那么我們?nèi)绾未_定一個(gè)面是朝向

34、哪里呢?這取決于我們的初始設(shè)定以及繪制頂點(diǎn)的 順序。在默認(rèn)情況下,頂點(diǎn)以逆時(shí)針方向繪制出來(lái)的方向?yàn)檎妫槙r(shí)針方向繪制出來(lái)的是反面。我們也可以用右手拇指定律來(lái)確定面的朝向。函 數(shù)glFrontFace用于指定是順時(shí)針方向?yàn)檎孢€是逆時(shí)針方向?yàn)檎?。默認(rèn)情況下,逆時(shí)針方向?yàn)檎?。函?shù)原型如下:推薦精選 void glFrontFace( GLenum mode);mode只有兩個(gè)值,要么是GL_CW,指定繪制順序?yàn)轫槙r(shí)針 時(shí)表示正面;要么是GL_CCW,指定繪制順序?yàn)槟鏁r(shí)針方向時(shí)為正面。默認(rèn)為GL_CCW。下面我們將舉個(gè)繪制立方體的例子。1. - (void)prepareOpenGL

35、2. 3.     glShadeModel(GL_SMOOTH);4.     5.     glEnable(GL_CULL_FACE);6.     glEnable(GL_DEPTH_TEST);7.     glEnable(GL_NORMALIZE);8.     9.     glClearColor(0

36、.4, 0.4, 0.4, 1.0);10.     glViewport(0, 0, 320, 320);11.  12.     glMatrixMode(GL_PROJECTION);13.     glLoadIdentity();14.     glOrtho(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0);15.     推薦精選16.   

37、;  glMatrixMode(GL_MODELVIEW);17.     glLoadIdentity();18.     19.     glTranslatef(0.0f, 0.0f, -3.0f);20.     glRotatef(10.0f, 1.0f, 1.0f, 1.0f);21.     22.     glFrontF

38、ace(GL_CCW);23. 24.  25. - (void)drawRect:(NSRect)dirtyRect 26.     27.     static const struct28.     29.         GLubyte colours4;30.         GLfloat ver

39、tices3;31.         32.     vertexInfoList = 33.          255, 0, 0, 255, -0.5f, -0.5f, -0.5f ,    / v0: left-bottom-back34.          0, 255,

40、 0, 255, 0.5f, -0.5f, -0.5f ,     / v1: right-bottom-back35.          0, 0, 255, 255, 0.5f, 0.5f, -0.5f ,      / v2: right-top-back36.          255, 0, 255, 255, -0.5f, 0

41、.5f, -0.5f ,   / v3: left-top-back37.          255, 255, 0, 255, -0.5f, -0.5f, 0.5f ,   / v4: left-bottom-front38.          0, 255, 255, 255, 0.5f, -0.5f, 0.5f ,    / v5: right-bot

42、tom-front39.          20, 20, 20, 255, 0.5f, 0.5f, 0.5f ,      / v6: right-top-front40.          255, 255, 255, 255, -0.5f, 0.5f, 0.5f ,  / v7: left-top-front41.    

43、 42.  43.     static const GLubyte _attribute_(aligned(4) indices = 44.         0, 3, 1,    1, 3, 2,    / back face ·         0, 4, 3,  

44、;  3, 4, 7,    / left face ·         4, 5, 7,    7, 5, 6,    / front face ·         5, 1, 6,    6, 1, 2,  

45、0; / right face ·         7, 6, 3,    3, 6, 2,    / top face ·         0, 1, 4,    4, 1, 5,    / bottom face 推薦精選·  

46、;    ·      ·     glRotatef(-10.0f, 1.0f, 1.0f, 1.0f); ·   ·     / Drawing code here. ·     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ·      ·     glInterleavedArrays(GL_C4UB_V3F, 0, vertexInfoList); ·      ·     glCullFace(GL_BACK); 

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論