posts - 189,comments - 115,trackbacks - 0

            翻譯openGL的FAQ--可視和轉(zhuǎn)換 

          觀察和轉(zhuǎn)換
          ----------------------------------------------------------------------------------
          01.相機(jī)如何在OpenGL中工作?
          02.我怎樣才可以移動(dòng)我的視點(diǎn), 或者是相機(jī),在我的場(chǎng)景中?
          03.我的相機(jī)該去哪, 模型視點(diǎn)矩陣還是投射矩陣?
          04.我該怎么執(zhí)行一個(gè)縮放操作?
          05.給出當(dāng)前模型視點(diǎn)矩陣,我怎么才可以確定相機(jī)的物體空間位置?
          06.我怎樣才可以使照相機(jī)在我的場(chǎng)景中圍繞一個(gè)點(diǎn)轉(zhuǎn)?
          07.如何自動(dòng)計(jì)算一個(gè)觀察點(diǎn)可以顯示全部的場(chǎng)景?(我知道邊界球體和向上分量(bounding sphere                            
             and up vector ). )
          08.gluLookAt是如何工作的?
          09.我怎樣才可以得到一個(gè)在場(chǎng)景正中間的點(diǎn)?
          10.我把我的gluLookAt調(diào)用放在我的投影矩陣中,現(xiàn)在霧, 光線, 紋理貼圖都不能正確工作了, 究竟     
             發(fā)生什么了?
          11.我怎樣才可以建造一個(gè)立體的視覺?
          12.我不能使轉(zhuǎn)換正常的工作,哪里才可以知道更多的關(guān)于矩陣的東西?
          13.OpenGL的矩陣是縱排列,還是橫排列的?
          14.OpenGL的坐標(biāo)單位是什么?
          15.坐標(biāo)是如何轉(zhuǎn)換的?坐標(biāo)空間有什么不同?
          16.我怎么樣才可以轉(zhuǎn)換我場(chǎng)景中的唯一一個(gè)物體或者給每個(gè)物體都有單獨(dú)的變換?
          17.如何才可以在3D渲染圖上繪制2D圖?
          18.我如何才可以饒過OpenGL的矩陣轉(zhuǎn)換, 而直接把2D坐標(biāo)光柵化?
          19.使用絕對(duì)坐標(biāo)和相對(duì)坐標(biāo)的優(yōu)缺點(diǎn)在哪呢?
          20.我怎樣才可以畫一個(gè)場(chǎng)景中的不同視圖?
          21.我怎么樣才可以使我的物體圍繞一個(gè)固定的坐標(biāo)系統(tǒng)轉(zhuǎn)換, 而不是本地的坐標(biāo)系統(tǒng)?
          22.相對(duì)于使用gluPerspective, 使用glFrustum的優(yōu)缺點(diǎn)?
          23.我怎樣才可以調(diào)用glFrustum來匹配調(diào)用gluPerspective?
          24.我怎樣才可以畫一個(gè)全屏幕的矩形?
          25.對(duì)于一個(gè)給定的物體空間坐標(biāo), 我如何確定相應(yīng)的屏幕坐標(biāo)?
          26.怎么樣才可以找到一個(gè)屏幕上點(diǎn)的物體空間坐標(biāo)?
          27.怎樣才可以找到一個(gè)被模型視點(diǎn)矩陣轉(zhuǎn)換過的頂點(diǎn)坐標(biāo)? 
          28.怎樣計(jì)算觀察者到給定點(diǎn)的物體空間距離?
          29.在窗口被重定義大小后, 我怎么樣才可以保持我的比例系數(shù)?
          30.我怎么樣才可以使OpenGL使用左手坐標(biāo)系?
          31.怎樣轉(zhuǎn)換一個(gè)物體是它可以指向或者緊跟著另一個(gè)場(chǎng)景中的物體或點(diǎn)
          32.我如何才可以使用傾角, 仰角,斜角來轉(zhuǎn)換一個(gè)物體?
          33.我怎樣才可以渲染一個(gè)鏡面?
          34.我怎樣才可以做我自己的透視縮放?

          ==================================================================================

          1.OpenGL的照相機(jī)是如何工作的?

          OpenGL是非常注意的,這里是沒有照相機(jī)的.更確切的說是, 這個(gè)站相機(jī)總是位于眼空間坐標(biāo)處( 0.0, 0.0, 0.0, 0.0 ).為了給出移動(dòng)相機(jī)的效果,你必須反向的移動(dòng)你的場(chǎng)景,把轉(zhuǎn)換矩陣放入模型視點(diǎn)矩陣來實(shí)現(xiàn).這就是通常被引用的視點(diǎn)轉(zhuǎn)換.

          在實(shí)際練習(xí)中, 這是一個(gè)和相機(jī)轉(zhuǎn)換相等的等式, 但更有效率,因?yàn)楦嗟哪P娃D(zhuǎn)換 和相機(jī)轉(zhuǎn)換被連接到了一個(gè)單獨(dú)的矩陣中去.因此,但相機(jī)且只有相機(jī)在模型視點(diǎn)當(dāng)中時(shí),這些操作是必須被執(zhí)行的.比如,當(dāng)安置一個(gè)光源在世界坐標(biāo)系的時(shí)候, 當(dāng)視點(diǎn)轉(zhuǎn)換且只有視點(diǎn)轉(zhuǎn)換被應(yīng)用于模型視點(diǎn)矩陣的時(shí)候, 它是必須被重安置的.
          ---------------------------------------------------------------------------------
          2.我如何才可以移動(dòng)我的眼睛, 或者相機(jī)在我的場(chǎng)景中?

          OpenGL并沒有使用相機(jī)模型來提供一個(gè)接口完成這項(xiàng)工作.然后, GLU的庫(kù)提供了一個(gè)gluLookAt函數(shù), 它可以確定一個(gè)眼睛的位置, 一個(gè)可以看, 有向上向量,在物體空間中的坐標(biāo).這個(gè)函數(shù)可以根據(jù)它的參數(shù),計(jì)算出它的相機(jī)的反向轉(zhuǎn)換然后在乘以系統(tǒng)的當(dāng)前矩陣.
          ----------------------------------------------------------------------------------
          3.我的照相機(jī)該去哪兒, 模型視點(diǎn)矩陣還是投影矩陣?

          這GL_PROJECTION矩陣只能夠包含投影變換,它轉(zhuǎn)換眼坐標(biāo)到裁減坐標(biāo).

          這GL_MODELVIEW矩陣, 正如它名字所暗示的那樣,包含了模型和視點(diǎn)轉(zhuǎn)換, 它將會(huì)轉(zhuǎn)換物體的空間坐標(biāo)到眼坐標(biāo).請(qǐng)記住把相機(jī)轉(zhuǎn)換代碼放入GL_MODELVIEW矩陣中去, 不要放入GL_PROJECTION 去.

          考慮投影矩陣就好像在描述照相機(jī)的特性一樣, 例如field of view, focal length, fish eye lens, etc.考慮模型視點(diǎn)矩陣, 就好像你和照相機(jī)的位置, 以及你的朝向.

          在 gamedev FAQ有更多的描述兩個(gè)矩陣的信息.

          讀 Steve Bakers's 文章關(guān)于濫用投影.這篇文章是被高度評(píng)價(jià)和推薦的.它幫助了很多的OpenGL的新程序員們.
          ----------------------------------------------------------------------------------
          4. 我如何執(zhí)行一個(gè)縮放操作?

          一個(gè)簡(jiǎn)單的來縮放的方法就是使用統(tǒng)一的模型視點(diǎn)矩陣.然后, 這通常容易導(dǎo)致假如模型被放的太大的話, 會(huì)被zNear和zFar所裁減.

          一個(gè)更好的方法就是通常對(duì)投影的視景體進(jìn)行寬和高的限制.

          例如,你的程序通常會(huì)根據(jù)用戶的輸入, 來提供一個(gè)縮放的參數(shù),可能是一個(gè)浮點(diǎn)數(shù).當(dāng)設(shè)置了一個(gè)1.0的值后,將會(huì)沒有縮放操作執(zhí)行. 更大的值會(huì)有更大的縮放,和更多的關(guān)于視景體的限制, 而更小的值將會(huì)導(dǎo)致相反的情況.制造這種效果的代碼有可能像這樣:

          static float zoomFactor; /* 全局變量, 假如你需要,可以通過用戶輸入來改變,初始值為1.0*/

          /* 一段函數(shù)來設(shè)置投影矩陣.  可能的調(diào)用會(huì)來自一段典型的程序的重定義穿口大小的句柄. 將會(huì)              
             給出重畫大小的寬和高的整數(shù)值. 使用正確的畫面比例系數(shù)和縮放因子建造一個(gè)投影矩陣 */
          void setProjectMatrix( int width, int height )
          {
          glMatrixMode( GL_PROJECTION );
          glLoadIdentity();
          gluPerspective( 50.0*zoomFactor, (float)width/(float)height, zNear, zFar );
          /* zNear 和 zFar 將會(huì)由你來填入*/

          為了代替gluPerspective, 你的程序有可能使用glFrustum().這里有點(diǎn)小技巧,因?yàn)檫@個(gè)左, 右, 底,頂部參數(shù), 還有近平面參數(shù), 也會(huì)影響到可視域. 假設(shè)你想保持一個(gè)固定的zNear面的距離(非常合理的假設(shè)),glFrustum的代碼可能會(huì)看起來如下:

          glFrustum( left *zoomFactor, right *zoomFactor,
              bottom *zoomFactor, top *zoomFactor,
              zNear, zFar );
          glOrtho()也是類似的.
          ----------------------------------------------------------------------------------
          5.給出了當(dāng)前的模型視點(diǎn)矩陣, 我如何確定相機(jī)的物體空間位置?

          這個(gè)"相機(jī)"或者視點(diǎn)在眼坐標(biāo)中是在( 0.0, 0.0, 0.0 ).當(dāng)你把它轉(zhuǎn)換成( 0, 0, 0, 1)并與模型視點(diǎn)矩陣的逆矩陣相乘時(shí), 得出來的向量就是相機(jī)的物體空間坐標(biāo).

          OpenGL并沒有方法(使用glGet* 相關(guān)的函數(shù))來得到模型視點(diǎn)矩陣的逆矩陣.你需要使用自己的代碼來計(jì)算它.
          ----------------------------------------------------------------------------------
          6.我怎樣才可以使我場(chǎng)景中的照相機(jī)圍繞一個(gè)頂點(diǎn)在轉(zhuǎn)動(dòng)?

          你可以在同樣的場(chǎng)景中通過平移/轉(zhuǎn)動(dòng) 場(chǎng)景/物體來模擬軌道           .例如, 圍繞一個(gè)在Y軸上的物體, 而且不間斷的望向原點(diǎn), 有可能會(huì)這樣寫:

          gluLookAt( camera[0], camera[1], camera[2], /* 相機(jī)位置 */
              0, 0, 0, /* 相機(jī)朝向原點(diǎn) */
              0, 1, 0 ); /* 正Y軸方向 */ 
          glRotatef( orbitDegree, 0.0f,1.0f, 0.0f ); /* 圍繞 Y 軸 */
          /* ... 旋轉(zhuǎn)角度, 也可以來自于鼠標(biāo)的運(yùn)動(dòng) */

          glCallList( SCENE ); /* 繪制場(chǎng)景 */
          假如你堅(jiān)持使用物理的移動(dòng)這個(gè)相機(jī)的位置, 那么在把它放進(jìn)你的模型視點(diǎn)轉(zhuǎn)換中之前,你必須得轉(zhuǎn)換當(dāng)前相機(jī)位置的向量.

          在任意一種事件中,我都建議你研究下gluLookAt(如果你已經(jīng)沒有是用它了);
          ----------------------------------------------------------------------------------
          7.我如何才可以自動(dòng)計(jì)算一個(gè)點(diǎn),使它可以顯示我場(chǎng)景中的全部模型(我知道球體范圍和向上向量)?

          接下來的是來自Dave Shreiner 設(shè)置的一個(gè)可視系統(tǒng).

          首先,計(jì)算所有在你的場(chǎng)景中的物體的球體范圍. 這些將會(huì)提供給你兩點(diǎn)信息: 球體的中心位置 (讓 (cx, cy, cz) 來記錄這點(diǎn))和它的直徑.

          接下來,選擇一個(gè)zNear剪裁面距離的值.大部分的建議都是選擇一個(gè)大于,但接近一的數(shù),  所以,讓我們把它設(shè)為:

          zNear = 1.0;
          zFar  = zNear + diam;

          按下面這種方式,組織你的矩陣調(diào)用(對(duì)一個(gè)正射投影矩陣)

          GLdouble left = c.x - diam;
          GLdouble right = c.x + diam;
          GLdouble bottom = c.y - diam;
          GLdouble top = c.y + diam;

          glMatrixMode( GL_PROJECTION );
          glLoadIdentity();
          glOrtho( left, right, bottom, top, zNear, zFar );
          glMatrixMode( GL_MODELVIEW );
          glLoadIdentity();

          這種方法會(huì)設(shè)置你的物體在窗口的正中心, 伸展邊界以符合.(i.e.,這個(gè)是假設(shè)你窗口的比例系數(shù)為1.0).假如你的窗口是非正方形的, 將會(huì)按上面的方式計(jì)算左, 右, 上, 下, 在調(diào)用glOrtho以前放入下面的邏輯代碼段中.

          GLdouble aspect = (GLdouble) windowWidth / windowHeight;

          if ( aspect < 1.0 ) { /* 窗口的高比寬長(zhǎng) */
          bottom /= aspect;
          top /= aspect;
          } else {
          left *= aspect;
          right *= aspect;
          }

          上面的的代碼將會(huì)把你的 場(chǎng)景中的物體放在相對(duì)正確的位置. 假如你想試著去操作它( i.e.旋轉(zhuǎn),etc), 你需要增加一個(gè)可視轉(zhuǎn)換.

          一個(gè)典型的可視轉(zhuǎn)換將會(huì)和模型視點(diǎn)矩陣想混和, 而且看起來,應(yīng)該是這樣:

          gluLookAt( 0.0, 0.0, 2.0 * diam, c.x, c.y, c.z, 0.0, 1.0, 0.0 );
          ----------------------------------------------------------------------------------
          8.為什么gluLookAt()不能工作?

          這個(gè)通常是被不正確的轉(zhuǎn)換所導(dǎo)致的.

          假設(shè)你使用投影矩陣堆棧中的gluPerspective的zNear, zFar來作為第三, 第四個(gè)參數(shù),你就必須設(shè)置模型視點(diǎn)矩陣堆棧上的gluLookAt(), 并傳遞相應(yīng)的參數(shù),使你的物體, 可以落在zNear和zFar之間.

          當(dāng)你正試圖去了解可視轉(zhuǎn)換的時(shí)候,最好的方法就是寫一些代碼來做試驗(yàn).讓我們想一下,你正在看一個(gè)位于原點(diǎn)的一單位的球體.你可能想按下面的方式來設(shè)置你的轉(zhuǎn)換:

          glMatrixMode( GL_PROJECTION );
          glLoadIdentity();
          gluPerspective( 50.0, 1.0, 3.0, 7.0 );
          glMatrixMode( GL_MODELVIEW );
          glLoadIdentity();
          gluLookAt( 0.0, 0.0, 5.0,
              0.0, 0.0, 0.0, 
              0.0, 1.0, 0.0 );

          非常重要的一點(diǎn)就是,知道投影和模型視點(diǎn)矩陣是如何一起工作的.

          在這個(gè)例子中, 這個(gè)投影轉(zhuǎn)換,設(shè)立了一個(gè)50度的可視角度的觀察域, 和一個(gè)窗口的為1的比例系數(shù). 這個(gè)zNear的剪裁面是視點(diǎn)的前三個(gè)單位,這個(gè)zFar的剪裁面的是視點(diǎn)前的7個(gè)單位.它們分配了一個(gè)在Z軸長(zhǎng)度為4的視景體,對(duì)于一個(gè)單位的球體是絕對(duì)足夠的.

          這個(gè)模型視點(diǎn)轉(zhuǎn)換設(shè)置了眼坐標(biāo)為(0.0, 0.0, 5.0), 而所觀看的點(diǎn)是原點(diǎn),也就是我們單位圓的正中心.請(qǐng)注意這個(gè)眼坐標(biāo)的位置離觀察點(diǎn)的位置有5個(gè)單位的距離. 這點(diǎn)是相當(dāng)重要的,因?yàn)檠劬η懊娴?個(gè)單位的距離是在投影轉(zhuǎn)換所定義的視景體的正中間.假如這個(gè)gluLookAt()把眼睛設(shè)置在( 0.0, 0.0, 1.0 )它只會(huì)離原點(diǎn)一個(gè)單位的距離.它將會(huì)沒有足夠的長(zhǎng)度去包含物體在視景體中, 物體將會(huì)被zNear所剪裁.

          相同地,假如你把眼坐標(biāo)設(shè)置在( 0.0, 0.0, 10.0 ), 10個(gè)單位的離觀察點(diǎn)的距離,將會(huì)導(dǎo)致這個(gè)球體和視點(diǎn)有10個(gè)單位的距離, 并且被zFar剪裁面在7單位距離處, 被剪裁.

          假如這些東西, 困擾著你,讀OpenGL紅皮書,或者OpenGL詳解(specification)中有關(guān)于轉(zhuǎn)換的內(nèi)容.在你理解了物體空間坐標(biāo), 眼坐標(biāo)空間,和剪裁面坐標(biāo)空間, 這些上面的知識(shí), 將會(huì)變的非常的容易, 清晰. 最好, 在經(jīng)常寫些小的測(cè)試程序來實(shí)踐一下. 假如你在你的主程序中依然有相當(dāng)?shù)睦щy來使用正確的變換矩陣,那么寫些更簡(jiǎn)單幾何體的測(cè)試程序是非常有意義的.
          --------------------------------------------------------------------------------
          9.我如何去設(shè)置一個(gè)精確的點(diǎn)在場(chǎng)景的中間顯示?

          gluLookAt是非常容易做到這個(gè)的.簡(jiǎn)單的設(shè)置你的點(diǎn)的X, Y, 和Z值作為你的gluLookAt的第三, 第四, 第5個(gè)參數(shù).
          ---------------------------------------------------------------------------------
          10.我把我的gluLookAt調(diào)用放入我的投影矩陣中, 現(xiàn)在霧,光線,和紋理映射都不能正常工作了, 這  
             是為什么?

          這個(gè)通常是因?yàn)榘艳D(zhuǎn)換放在錯(cuò)誤的矩陣中所導(dǎo)致的, 看下問題三對(duì)這個(gè)問題的解釋. 然后也有可能, 是因?yàn)樘厥獾墓庹諉栴}, 所導(dǎo)致的,因?yàn)橛绣e(cuò)誤的矩陣被放入模型視點(diǎn)矩陣中,然后定義了光照的位置. 當(dāng)一個(gè)光源點(diǎn)被定位在眼空間坐標(biāo)中,i.e.和眼睛相關(guān),它將會(huì)被重新定位到一個(gè)單位矩陣在模型視點(diǎn)矩陣堆棧中的時(shí)候.當(dāng)可視矩陣被放入模型視點(diǎn)堆棧中時(shí), 原先世界坐標(biāo)系中的光源位置講會(huì)被重定位. 當(dāng)一個(gè)光源的位置是和一個(gè)轉(zhuǎn)換的物體相關(guān)的時(shí)候, 當(dāng)物體的模型矩陣和在模型視點(diǎn)矩陣堆棧中的可視矩陣想乘時(shí),這個(gè)光源也會(huì)被重新定位,請(qǐng)記住在任何的光源被渲染前, 它都有可能被重新定位.假如光源在結(jié)構(gòu)中相對(duì)于眼睛在移動(dòng), 那么每個(gè)結(jié)構(gòu)都必須使用合適的矩陣來進(jìn)行重定位.
          ----------------------------------------------------------------------------------
          11.我如何可以建造一個(gè)立體視圖?

          立體視圖就是通過展現(xiàn)觀察者觀察到的左眼和右眼所看見的畫面來形成的.這些圖像必須正確的匹配到顯示器上,一符合觀察者實(shí)際所看到的, 更多的習(xí)慣是使用多于一副的3D圖像. 附加一點(diǎn)就是這種方法會(huì)和被使用的顯示器技術(shù)有相當(dāng)緊密的聯(lián)系. 一些圖形系統(tǒng)和顯示設(shè)備, 會(huì)在硬件上支持立體視圖和支持像左緩存和右緩存, 另外就是在系統(tǒng)上支持雙緩存的前緩存和后緩存. 另外的系統(tǒng)就會(huì)在顯示屏幕顯示兩個(gè)視口來支持立體視圖, 并詳細(xì)定義顯卡的模式來發(fā)送這些圖像到顯示屏幕.另外與此相關(guān)的就是觀察者通常帶著一個(gè)特殊的眼鏡,它會(huì)自動(dòng)對(duì)圖像進(jìn)行揀選來以此來符合每個(gè)眼睛所看到的.然而即使沒有這些圖像特性, 一個(gè)開發(fā)者仍然可以使用顏色過濾在一些基于紅或藍(lán)色過濾器的選擇圖像的地方來實(shí)現(xiàn)立體視圖,例如畫左眼和右眼的圖像到到紅,藍(lán)幀緩中來實(shí)現(xiàn)這點(diǎn). 或者更加簡(jiǎn)單的就是有多個(gè)系統(tǒng)或是圖形顯卡(或者一塊顯卡)來產(chǎn)生兩個(gè)完全分離的視頻信號(hào), 來分別畫一個(gè)左眼的和右眼的圖像.這個(gè)視頻將會(huì)被發(fā)送到正確的眼睛中,使用一個(gè)display employing polarizing filters 或者一個(gè) head mounted display 或者一些別的用戶自己的顯示設(shè)備, 執(zhí)行一些原理相同的操作.

          從一個(gè)OpenGL透視投影中, 立體渲染的設(shè)備將會(huì)使用合適的操作來渲染到左眼和右眼(作圖像掩碼, 分離上下文 或是不同視口)并且匹配到與OpenGL投影相關(guān)的觀察者的左眼和右眼的幾何圖像到顯示器上. 這個(gè)最后的OpenGL設(shè)備要求是這個(gè)在"虛擬"世界中的眼睛位置必須得來自模型視點(diǎn)矩陣中的分離的瞳孔位置, 這種分離會(huì)在眼空間坐標(biāo)產(chǎn)生一個(gè)轉(zhuǎn)換 但不會(huì)在別的相同的方法中被計(jì)算.

          Paul Bourke 整理了很多關(guān)于立體OpenGL立體視圖的資料:

          · 3D Stereo Rendering Using OpenGL
          · Calculating Stereo Pairs
          · Creating Anaglyphs using OpenGL
          ----------------------------------------------------------------------------------
          12.我不能使轉(zhuǎn)換正常的工作. 我可以從哪里得到更多的關(guān)于矩陣的知識(shí)?

          一個(gè)系統(tǒng)的關(guān)于基礎(chǔ)的矩陣數(shù)學(xué)和線性代數(shù)的知識(shí)已經(jīng)超出這份FAQ的范圍. 相關(guān)的概念已經(jīng)在美國(guó)的高校數(shù)學(xué)課上解釋過了。

          假如你知道這些基本概念, 但還是有點(diǎn)糊涂(一個(gè)共同的問題就是經(jīng)驗(yàn)), 讀下Steve Baker's 
          review of matrix concepts  和他的 article on Euler angles.

          執(zhí)行基本向量, 矩陣, 四元數(shù)的操作的delphi代碼 可以在這里找到.
          ----------------------------------------------------------------------------------
          13.OpenGL的矩陣是行排列的, 還是縱排列的?

          出于編程的原因, OpenGL的矩陣是一個(gè)在內(nèi)存中依次相連的16元素的數(shù)組,轉(zhuǎn)換部分占據(jù)了16元素的矩陣中的第13, 14, 15, 16位置.

          縱隊(duì)排列相對(duì)橫隊(duì)排列純粹就是一種符號(hào)協(xié)定. 注意自右的和縱排列矩陣相乘將會(huì)產(chǎn)生和自左的和行排列矩陣相乘產(chǎn)生同樣的結(jié)果. 在 OpenGL詳解和OpenGL參考手冊(cè)都使用了縱排列矩陣. 你可以使用任意一種, 只要你清楚的聲明了。

          不辛地,使用在spec和藍(lán)皮書中的縱排列格式會(huì)在OpenGL社區(qū)中導(dǎo)致無止境的困擾.縱排列的格式會(huì)導(dǎo)致一個(gè)程序員不期望的矩陣在內(nèi)存中的排列格式.

          更多的關(guān)于這方面的內(nèi)容, 請(qǐng)點(diǎn)擊:這兒.
          ----------------------------------------------------------------------------------
          14.OpenGL的坐標(biāo)單位是什么?

          最簡(jiǎn)短的回答就是. 只要你希望, 它可以使用任何你所希望的單位.

          根據(jù)你幾何數(shù)據(jù)庫(kù)中的內(nèi)容, 對(duì)于你的程序可能非常方便的處理OpenGL的坐標(biāo)單位,比如一個(gè)毫米,或者一光年, 或者這其中的任何距離(或大或小).

          OpenGL也允許你自己定義你的幾何體使用不同值的坐標(biāo)系統(tǒng).例如, 你可能會(huì)發(fā)現(xiàn)在對(duì)飛機(jī)模型控制的時(shí)候使用厘米, 而對(duì)機(jī)身使用米, 而對(duì)所飛行的空間使用千米.OpenGL的模型視點(diǎn)矩陣可以縮放不同的坐標(biāo)系統(tǒng)來形成同樣的眼坐標(biāo)系統(tǒng).

          程序有義務(wù)來確定投影和模型視點(diǎn)矩陣的構(gòu)造所提供的圖像和觀察者保持一個(gè)合適的距離, 和合適的可視域, 以及能夠保持zNear和zFar剪裁面在一個(gè)合適的范圍內(nèi).一個(gè)在微米程度縮放的顯示分子的程序,  例如, 就不能把觀察者放在一個(gè)10英尺距離, 60度觀察域的地方.
          ----------------------------------------------------------------------------------
          15.坐標(biāo)是如何轉(zhuǎn)換的?坐標(biāo)空間有什么不同?

          物體坐標(biāo)被模型視點(diǎn)矩陣所轉(zhuǎn)換來產(chǎn)生眼坐標(biāo).

          眼坐標(biāo)被投影矩陣所轉(zhuǎn)換來產(chǎn)生裁減坐標(biāo).

          裁減坐標(biāo) X, Y, Z將會(huì)被裁減坐標(biāo)W所除來產(chǎn)生設(shè)備規(guī)范化坐標(biāo).

          設(shè)備規(guī)范化坐標(biāo)會(huì)被視口參數(shù)所縮放和轉(zhuǎn)移來產(chǎn)生窗口坐標(biāo).

          物體坐標(biāo)也就是當(dāng)你提交給OpenGL glVertex*()或著是 glVertexPointer()的時(shí)候的原始坐標(biāo).它將會(huì)顯示你的物體或者別的你想渲染的幾何體的坐標(biāo).

          許多的程序設(shè)計(jì)者使用世界坐標(biāo)系統(tǒng). 物體通常在同一個(gè)坐標(biāo)系統(tǒng)中被模型化, 縮放, 平移, 旋轉(zhuǎn)都會(huì)在你的建造的世界中轉(zhuǎn)換. 世界坐標(biāo)系統(tǒng)是通過存儲(chǔ)在模型視點(diǎn)矩陣中的模型轉(zhuǎn)換而形成的物體坐標(biāo)轉(zhuǎn)換而來. 然而,OpenGL并沒有世界坐標(biāo)系統(tǒng)的概念. 世界坐標(biāo)系統(tǒng)純粹就是一個(gè)程序架構(gòu).

          眼坐標(biāo)是通過被模型視點(diǎn)矩陣轉(zhuǎn)換的物體坐標(biāo)而來. 這個(gè)模型視點(diǎn)矩陣中包含了模型轉(zhuǎn)換和視點(diǎn)轉(zhuǎn)換, 它定義了觀察者位于原點(diǎn),而且朝向Z的負(fù)半軸.

          裁減坐標(biāo)是由眼坐標(biāo)通過投影轉(zhuǎn)換而來.裁減坐標(biāo)空間范圍是從 -Wc 到 Wc 在所有的三個(gè)軸方向上, Wc 是裁減坐標(biāo)W的值. OpenGL會(huì)裁減所有位于范圍之外的東西.

          裁減坐標(biāo)上所執(zhí)行的透視除法會(huì)產(chǎn)生標(biāo)準(zhǔn)設(shè)備規(guī)范化坐標(biāo), 在三個(gè)軸的范圍是從 -1 到 1.

          窗口坐標(biāo)是來通過視口來縮放,平移設(shè)備規(guī)范化坐標(biāo)轉(zhuǎn)換而來. glViewport()和glDepthRange()的參數(shù)控制這些轉(zhuǎn)換.使用視口, 你可以映射設(shè)備規(guī)范化坐標(biāo)的立方體到你的窗口的任何位置 和深度緩存中.

          更多的信息, 請(qǐng)看 OpenGL specification , 圖解2.6
          ----------------------------------------------------------------------------------
          16. 我如何轉(zhuǎn)換我場(chǎng)景中的唯一物體或者是給我場(chǎng)景中的每一個(gè)物體都有單獨(dú)轉(zhuǎn)換?

          OpenGL提供了矩陣堆棧來實(shí)現(xiàn)這個(gè)功能. 這樣的話, 就是使用模型視點(diǎn)矩陣堆棧.

          一個(gè)典型的OpenGL程序第一次設(shè)置這個(gè)矩陣模式是使用 glMatrixMode( GL_MODELVIEW )并且加載一個(gè)可視轉(zhuǎn)換, 例如一個(gè)到gluLookAt().更多的信息可利用的在 gluLookAt.

          然后這個(gè)代碼渲染每個(gè)場(chǎng)景中的物體使用他們自己的轉(zhuǎn)換通過包裝這個(gè)調(diào)用glPushMatrix()和glPopMatrix().例如:

          glPushMatrix();
          glRotatef( 90.0, 1.0, 0.0, 0.0 );
          gluCylinder( quad, 1, 1, 2, 36, 12 );
          glPopMatrix();

          上面的代碼渲染一個(gè)圓柱體圍繞X軸旋轉(zhuǎn)90度. 這個(gè)模型視點(diǎn)矩陣將會(huì)被重新存儲(chǔ)為先前的值在glPopMatrix()調(diào)用后. 相似的調(diào)用序列可以渲染場(chǎng)景中的并發(fā)物體.

          17.我如何在我的3D渲染上, 繪制我的2D控制器?

          基本的策略是對(duì)于要描繪的控制點(diǎn)設(shè)置一個(gè)2D投影.你既可以在你的3D渲染上做這些, 也可以在覆蓋面上來完成這個(gè). 假如你選擇在3D渲染上繪制這些, 那么在每幀結(jié)束的時(shí)候, 都要重畫這些控制點(diǎn)(在交換緩存前, 立即重畫). 假如你選擇畫在覆蓋面上, 你只需要在跟新的時(shí)候重畫.

          為了設(shè)置一個(gè)2D投影, 你需要改變這個(gè)投影矩陣. 正常地,這是非常容易設(shè)置一個(gè)世界坐標(biāo)的單元, 來對(duì)應(yīng)于一個(gè)屏幕的像素, 像這樣:

          glMatrixMode( GL_PROJECTION );
          glLoadIdentity();
          gluOrtho2D( 0, windowWidth, 0, windowHeight );

          gluOrtho2D()設(shè)置一個(gè)-1.0到1.0的Z軸的范圍, 所以你可以使用glVertex2*()函數(shù)中的一種來確保你的幾何圖元不會(huì)被zNear和zFar剪裁面所剪裁.

          正常地, 當(dāng)繪制2D控制點(diǎn)的時(shí)候, 都把模型視點(diǎn)矩陣設(shè)置會(huì)單位矩陣.所以你會(huì)發(fā)現(xiàn)非常容易做些別的( 例如, 你可以使用交叉存取的平移矩陣來重復(fù)的畫控制點(diǎn)).

          假如需要精確的像素操作, 你可以把一個(gè)小型的平移放入模型視點(diǎn)矩陣, 如下所示:

          glMatrixMode( GL_PROJECTION );
          glLoadIdentity();
          glTranslatef( 0.375, 0.375, 0.0 );

          假如你在一個(gè)3D 深度緩存的圖像上進(jìn)行繪制, 當(dāng)你繪制你的2D幾何圖元你需要關(guān)閉深度測(cè)試(depth test). 你可以通過調(diào)用glDisable( GL_DEPTH_TEST ) 或者是glDepthFunc( GL_ALWASY ).根據(jù)你的程序, 你可能在開始2D繪制的時(shí)候簡(jiǎn)單的清除了深度緩存. 最終, 繪制2D幾何圖元在你最你的Z軸深度上, 也不失為一個(gè)解決方法。

          在2D投影矩陣按如上所示的建立后,你就可以渲染正確的OpenGL圖元到屏幕上, 詳細(xì)的定義他們的X, Y像素的地址( 使用OpenGL 中心的屏幕坐標(biāo), (0, 0)在左下角).
          ---------------------------------------------------------------------------------
          18.我如何越過OpenGL矩陣變換而直接讓2D坐標(biāo)光柵化?

          這并不是OpenGL矩陣轉(zhuǎn)換中的一種開關(guān)模式. 然而, 假如你使用了glLoadIdentity()調(diào)用設(shè)置了設(shè)置了兩個(gè)單位矩陣, 典型的OpenGL執(zhí)行有足夠的智力,來知道這是一個(gè)單位矩陣轉(zhuǎn)換是不用操作的并因此來行動(dòng).

          更多的有關(guān)純粹把OpenGL當(dāng)做一個(gè)光柵化的API的信息, 請(qǐng)參考:OpenGL Game Developer's FAQ.
          ----------------------------------------------------------------------------------
          19.使用絕對(duì)坐標(biāo),或者是相對(duì)坐標(biāo)的好處, 和壞處?

          一些OpenGL可能需要在單一的場(chǎng)景中使用更多的坐標(biāo)來渲染同樣的物體.OpenGL有兩中方法做這個(gè):

           1.使用"絕對(duì)坐標(biāo)".支持每個(gè)物體的多份拷貝, 每個(gè)都有他們自己唯一的頂點(diǎn)集合.你不需要去改變   
             模型視點(diǎn)矩陣在需要的位置對(duì)物體進(jìn)行渲染.
           2.使用"相對(duì)坐標(biāo)".會(huì)保存物體的唯一一 份拷貝, 通過壓入模型視點(diǎn)矩陣堆棧, 設(shè)置需要的轉(zhuǎn)換,   
             發(fā)送幾何數(shù)據(jù), 并彈出堆棧來對(duì)他們進(jìn)行多次的渲染. 對(duì)每個(gè)物體重復(fù)這些步驟.

          一般來說, 經(jīng)常的改變狀態(tài), 例如模型視點(diǎn)矩陣, 會(huì)對(duì)你的效率有負(fù)面的影響. 假如你沒有對(duì)每個(gè)單獨(dú)的圖元都在模型視點(diǎn)轉(zhuǎn)換使用大量的轉(zhuǎn)換, 那OpenGL是可以快速的處理你的幾何數(shù)據(jù)的.

          然而,你有時(shí)候可能需要權(quán)衡對(duì)圖像進(jìn)行多分的拷貝來放棄對(duì)內(nèi)存的節(jié)省. 讓我們假設(shè)你定義了一個(gè)高擬真度的門把手,使用了大約200, 300個(gè)三角形, 而你對(duì)一個(gè)房子的建模將會(huì)使用50個(gè)門把手,它們都使用了相同的門把手.  這個(gè)更加好的是使用單獨(dú)門把手的顯示列表, 然后定義多個(gè)單獨(dú)的矩陣轉(zhuǎn)換, 而不是在內(nèi)存使用大約10-15K的空間來定義絕對(duì)坐標(biāo).

          當(dāng)有更多的計(jì)算主題時(shí), 那么不得不在CPU時(shí)間和存儲(chǔ)空間之間進(jìn)行選擇. 而你也不得不對(duì)此進(jìn)行更多的嘗試.
          ----------------------------------------------------------------------------------
          20.我如何在我的場(chǎng)景中繪制更多的視圖?

          你可以通過使用glViewport()調(diào)用在同樣的窗口繪制兩個(gè)視圖. 設(shè)置glViewport()對(duì)準(zhǔn)那個(gè)你想作為第一個(gè)視圖的地區(qū), 設(shè)置你的場(chǎng)景觀察, 和渲染. 然后設(shè)置glViewport()對(duì)準(zhǔn)那個(gè)你想作為第二個(gè)視圖的地區(qū), 再一次設(shè)置你的場(chǎng)景觀察, 和渲染.

          你可能需要注意有些操作并不會(huì)為glViewport()所注意, 例如glSwapBuffers()和glClear(). glSwapBuffers()總是交換當(dāng)前的整個(gè)窗口. 然而, 你可以通過使用剪取矩形來限制你的glClear()專門只對(duì)一個(gè)矩形窗口.

          你的程序有可能只允許在不同的窗口中使用不同的視圖. 假如這樣, 你需要在兩個(gè)渲染器中執(zhí)行一個(gè)針對(duì)當(dāng)前的操作. 假如兩個(gè)窗口共享一個(gè)上下文環(huán)境, 你需要向上面描述的那樣改變場(chǎng)景的視圖. 假如你的程序?qū)γ總€(gè)窗口使用分離的上下文, 那么這些操作是沒有必要的.
          ----------------------------------------------------------------------------------
          21.我如何使我的物體圍繞一個(gè)固定的坐標(biāo)系統(tǒng), 而不是物體的本地坐標(biāo)系統(tǒng)?

          假如你使一個(gè)物體, 圍繞Y軸旋轉(zhuǎn), 你就會(huì)發(fā)現(xiàn)X軸, 和Y軸在圍繞這個(gè)物體旋轉(zhuǎn).一個(gè)后續(xù)的旋轉(zhuǎn)圍繞這些軸進(jìn)行新的轉(zhuǎn)換軸旋轉(zhuǎn), 而不使用原始的軸. 在一個(gè)固定坐標(biāo)軸系統(tǒng)中, 而不是物體本地坐標(biāo)系統(tǒng)中, 執(zhí)行轉(zhuǎn)換是非常另人滿意的.

          這個(gè) OpenGL Game Developer's FAQ 包含了使用四元數(shù)來存儲(chǔ)轉(zhuǎn)換的信息, 在解決這類問題時(shí), 這些資料有可能很有用.

          導(dǎo)致這個(gè)問題的主要原因是OpenGL矩陣操作是在矩陣堆棧上的自右乘法, 因此導(dǎo)致了出現(xiàn)在物體空間的轉(zhuǎn)換.為了影響屏幕空間轉(zhuǎn)換, 你需要使用自左乘法. OpenGL并沒有提供模式的開關(guān)來對(duì)應(yīng)矩陣相乘的順序, 所以你需要手動(dòng)自左乘法.一個(gè)程序可能在每幀后通過取回當(dāng)前矩陣來對(duì)此進(jìn)行實(shí)現(xiàn). 這個(gè)程序乘以新的轉(zhuǎn)換來對(duì)應(yīng)于單位矩陣上的下一幀, 并乘以使用glMultiMatrix()的矩陣上的堆積的當(dāng)前轉(zhuǎn)換(來自上一幀).

          你需要注意的就是每次得到一幀的模型視點(diǎn)矩陣都可能對(duì)你的程序執(zhí)行效率有負(fù)面的影響. 然而你可以對(duì)這些操作進(jìn)行測(cè)試, 因?yàn)檫@個(gè)執(zhí)行效率是對(duì)應(yīng)于不同的執(zhí)行而不同的 .
          ----------------------------------------------------------------------------------
          22.使用glFrustum相對(duì)于gluPerspective的好處, 于壞處?為什么我們

          glFrustum()和gluPerspective()都會(huì)產(chǎn)生透視投影矩陣, 它們把眼坐標(biāo)轉(zhuǎn)換到剪裁坐標(biāo)而來.這個(gè)主要的不同在于glFrustum更多的是產(chǎn)生和允許離軸(off-axis)的矩陣, 而gluperspective可以產(chǎn)生對(duì)稱的on-axis的矩陣. 確實(shí), 你可以使用glFrustum來頂替gluPerspective. 然而,除了這個(gè)層次的調(diào)用本身是glu接口本身的一部分外,  使用glFrustum所產(chǎn)生的矩陣對(duì)于gluPerspective來說, 本身也沒有什么特殊的性能優(yōu)勢(shì).

          自從glFrustum相對(duì)于gluPerspective更加的常規(guī), 你就可以在萬一不能使用gluPerspective的時(shí)候, 使用它. 一些例子包括在 projection shadeows, 平鋪渲染, 和立體視圖中.

          平鋪渲染 使用在多非軸線矩陣來渲染場(chǎng)景中的不同地方. 這個(gè)結(jié)果是集合了一個(gè)大型的圖象數(shù)據(jù)數(shù)組來產(chǎn)生最終的圖象 這個(gè)是非常必要的當(dāng)這個(gè)最終渲染的期望的維數(shù)超過了OpenGL所能執(zhí)行的最大視口維數(shù).

          在立體視圖中, 同樣的場(chǎng)景的兩個(gè)渲染圖將會(huì)被作為有輕微的改變的可視觀察位置. 當(dāng)這個(gè)觀察軸在眼睛的右邊, 每個(gè)視圖都必須使用輕微的off-axis矩陣到任一邊, 來達(dá)到正確的可視結(jié)果.
          ---------------------------------------------------------------------------------
          23.我如何執(zhí)行一個(gè)到glFrustum的調(diào)用來匹配我對(duì)gluPerspective()?

          這個(gè)你的glFrustum()調(diào)用的可視的角度(fov)是:

           fov * 0.5 = arctan( (top - bottom) * 0.5 / near )

          當(dāng) bottom == -top 對(duì)于由gluPerspective所產(chǎn)生的對(duì)稱投影, 然后:

           top = (tan( fov * 0.5)) * near;
           bottom = -top 

          注意: 上面公式中的fov的單位必須使用弧度,來配合在C語言的數(shù)學(xué)庫(kù). 假如你想使用角度計(jì)算FOV(例如調(diào)用gluPerspective), 需要這樣進(jìn)行計(jì)算:

            top = tan( fov * 3.1415926 / 360 )

          左邊和右邊的參數(shù),只需要簡(jiǎn)單的使用 top, bottom, aspect來計(jì)算:

           left = aspect * bottom
           right = aspect * topp

          OpenGL Reference Manual 顯示了使用雙函數(shù)所產(chǎn)生的矩陣.
          ----------------------------------------------------------------------------------
          24. 我如何畫一個(gè)全屏幕的四邊形?

          這個(gè)問題通常的意思是, " 我如何畫一個(gè)可以填充我全部視口的四邊形?" 有很多方法可以做到.

          最直接的方法就是先設(shè)置你所希望的顏色, 設(shè)置投影和模型視點(diǎn)矩陣為單位矩陣, 并調(diào)用glRectf()來畫一個(gè)和GL_QUADS相等的圖元. 你的矩形或者四面體的Z軸深度應(yīng)該在-1.0到1.0之間,  -1.0映射到zNear剪裁面, 1.0映射到zFar剪裁面.

          這里有個(gè)例子, 這兒有個(gè)如何畫一個(gè)全屏幕的四面體在zNear剪裁面上:

          glMatrixMode( GL_MODELVIEW  );
          glPushMatrix();
          glLoadIdentity();
          glMatrixMode( GL_PROJECTION );
          glPushMatrix();
          glLoadIdentity();
          glBegin( GL_QUADS );
          glVertex3i( -1, -1, -1 );
          glVertex3i(  1, -1, -1 );
          glVertex3i(  1,  1, -1 );
          glVertex3i( -1,  1, -1 );
          glEnd();
          glPopMatrix();
          glMatrixMode( GL_MODELVIEW );
          glPopMatrix();

          你的程序, 有可能是需要相應(yīng)的矩形有個(gè)最大的Z軸值, 那樣的話, 你只需要修改Z軸用1來代替-1.

          當(dāng)繪制一個(gè)全屏幕的矩形時(shí), 你可能屏蔽掉一些緩沖區(qū)來讓只有特殊的緩沖區(qū)可被影響. 例如, 你可能屏蔽掉顏色緩沖區(qū)并設(shè)置深度函數(shù)為 GL_ALWAYS, 所以就只有深度緩沖區(qū)被繪制.你也可以設(shè)置 碼區(qū)(mask)來允許模板緩存被設(shè)置或者更多的別的復(fù)合緩存.
          ----------------------------------------------------------------------------------
          25.我如何找到一個(gè)給定物體的空間坐標(biāo)所對(duì)應(yīng)的屏幕坐標(biāo)?

          假如你只打算得到少數(shù)的幾個(gè)點(diǎn), 你可以使用GLU庫(kù)中中的gluProject()函數(shù). 假如要大堆的坐標(biāo), 使用系統(tǒng)的回掉機(jī)制可以更有效率.

          為了使用gluProject(),你必須提供模型視點(diǎn)矩陣, 投影矩陣, 視口, 和輸入的物體空間坐標(biāo).屏幕空間的坐標(biāo)將會(huì)被以 X, Y, Z的形式返回, 其中Z會(huì)被歸一化(normalize).
          ----------------------------------------------------------------------------------
          26.我如何可以找到屏幕上一個(gè)像素所在的物體空間坐標(biāo)?

          這個(gè)GLU庫(kù)提供了gluUnProject()函數(shù)來實(shí)現(xiàn)這個(gè)操作.

          你需要讀取深度緩存來獲得屏幕上的坐標(biāo)的Z軸值在 X, Y處, 這段代碼可以如下.

          GLdouble z;
          glReadPixels( x, y, 1, 1, GL_DEPTH_COMPONENT, GL_DOUBLE, &z );

          注意 X和Y是相對(duì)于屏幕左下角的(0, 0)位置.

          你需要提供屏幕空間的X, Y和Z值作為 gluUnProject的輸入,另外還有當(dāng)前像素正在被渲染的模型視點(diǎn)矩陣, 投影矩陣, 和視口.
          ----------------------------------------------------------------------------------
          27.我如何可以找到被模型視點(diǎn)矩陣轉(zhuǎn)換過的像素坐標(biāo)?

          這個(gè)通常被用于得到頂點(diǎn)的眼坐標(biāo)空間的值(i.e,物體的空間頂點(diǎn)被模型視點(diǎn)所轉(zhuǎn)換).你可以通過得到當(dāng)前的模型視點(diǎn)矩陣并執(zhí)行向量和矩陣的乘法來得到.
          ----------------------------------------------------------------------------------28.我如何計(jì)算觀察者到給定點(diǎn)的物體空間距離?

          轉(zhuǎn)換這點(diǎn)到眼坐標(biāo)空間,通過乘以模型視點(diǎn)矩陣. 然后簡(jiǎn)單的計(jì)算它到原點(diǎn)的距離.(假如這個(gè)不能正常的工作, 你可能是把視點(diǎn)轉(zhuǎn)換放入了投影矩陣堆棧中了.)

          來得到當(dāng)前的模型視點(diǎn)矩陣:

           GLfloat m[16];
           glGetFloatv( GL_MODELVIEW_MATRIX, m );

          對(duì)于使用任何的OpenGL調(diào)用, 你都可以使用glGet*()函數(shù)來得當(dāng)前的窗口的上下文.
          ----------------------------------------------------------------------------------
          29.在一個(gè)窗口被重新定義大小后, 我如何保持我的比例系數(shù)?

          這個(gè)是基于你是如何設(shè)置你的投影矩陣. 對(duì)于任何一種情況, 你都需要知道你的窗口的維數(shù)(寬和高). 如何得到這些是基于你使用的平臺(tái). 在GLUT, 例如, 這個(gè)維數(shù)是作為參數(shù)傳遞給 reshape回調(diào)函數(shù).

          接下來的是假設(shè)你的視口都使用和你的窗口同樣的尺寸. 假如你沒有, 使用窗口高度和寬度來代替視口的高度和寬度.

          假如你使用gluPerspective來設(shè)置你的投影矩陣, 第二個(gè)參數(shù)是控制這個(gè)比例系數(shù). 當(dāng)你的程序捕捉到了一個(gè)新的大小, 你需要修改的投影矩陣如下:

           glMatrixMode( GL_PROJECTION );
           glLoadIdentity();
           gluPerspective( fov, (float) width/(float) height, zNear, zFar );

          假如你使用glFrustum, 這個(gè)比例系數(shù)是將會(huì)是使用視景體的寬度和高度. 你可是使用下面的重設(shè)窗口大小代碼來支持1:1的比例系數(shù):

           float cx, halfWidth = windowWidth * 0.5f;
           float aspect = (float)windowWidth/(float)windowHeight;

           glMatrixMode( GL_PROJECTION );
           glLoadIdentity();
           /* cx is the eye space center of the zNear plane in X */
           glFrustum( cx - halfWidth*aspect, cx + halfWidth*aspect, bottom, top, zNear, zFar);

          glOrtho()和gluOrho2D() 的調(diào)用視和glFrustum()非常相似的.
          ----------------------------------------------------------------------------------
          30. 我可以讓OpenGL使用一個(gè)左手系空間?

          OpenGL 并沒有這樣一個(gè)模式開關(guān)來轉(zhuǎn)換左右手的坐標(biāo). 然而,你可以非常容易的通過乘以以個(gè)負(fù)的Z軸縮放到模型視點(diǎn)矩陣來得到左手坐標(biāo)系統(tǒng). 例如:

           glMatrixMode( GL_PROJECTION );
           glLoadIdentity();
           glScalef( 1.0, 1.0, -1.0 );
           /* 像平常那樣乘以視點(diǎn)轉(zhuǎn)換 */
           /* 像平常那樣乘以模型轉(zhuǎn)換 */
          ----------------------------------------------------------------------------------
          31.我如何轉(zhuǎn)換一個(gè)物體使它指向或者跟隨場(chǎng)景中的一個(gè)物體,或點(diǎn)?

          你需要構(gòu)造一個(gè)矩陣 , 它可以轉(zhuǎn)換你的物體的本地坐標(biāo)系統(tǒng)到一個(gè)你所希望面對(duì)的方向的坐標(biāo)系統(tǒng). 看 example code , 是如何建造這類矩陣的.

          假如你僅僅指是想渲染一個(gè)物體, 使它可以面對(duì)觀察者, 你可以考慮通過在眼坐標(biāo)空間中把模型視點(diǎn)矩陣設(shè)置成單位矩陣來實(shí)現(xiàn). 
          ----------------------------------------------------------------------------------
          32.我如何轉(zhuǎn)變我的物體使用一個(gè)給定的傾角, 仰角, 和斜角?

          轉(zhuǎn)換矩陣的左上角的3X3部分, 是由自右轉(zhuǎn)換坐標(biāo)空間的 X, Y, Z所構(gòu)成.


          ----------------------------------------------------------------------------------
          33.我該如何渲染處鏡面效果?

          把你的場(chǎng)景渲染兩次, 其中一次, 作為你的鏡面的反光. 還有一次,作為來自正常的視圖(非反射的). Example Code 示范了這種技術(shù).

          對(duì)于一個(gè)軸對(duì)齊的鏡面, 例如一個(gè)在YZ平面上的鏡面. 這個(gè)反射場(chǎng)景可以使用簡(jiǎn)單的縮放和平移. 使用 -1.0來乘以鏡面的法向量, 并進(jìn)行縮放. 并平移兩倍的鏡面距離.使用適當(dāng)?shù)霓D(zhuǎn)換來渲染這些場(chǎng)景會(huì)產(chǎn)生場(chǎng)景在鏡面中的反射.使用矩陣堆棧來保存上一次的可視轉(zhuǎn)換的值.

          下一步, 使用glClear( GL_DEPTH_BUFFER_BIT )來清空深度緩存.然后渲染鏡面.對(duì)于一個(gè)完美反射的鏡面, 只需要簡(jiǎn)單的渲染深度緩存. 真正的鏡面通常是不完美反射的, 他們很容易被一些別的光線所擾亂。為了建造這種效果, 使用混合技術(shù)來渲染一個(gè)鏡面使用0.05的alpha值. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_ALPHA)對(duì)于這個(gè)目的來說, 是個(gè)很好的混合函數(shù).

          最終, 渲染這些非反射場(chǎng)景. 當(dāng)這個(gè)完全的反射場(chǎng)景存在于顏色緩存中, 而不是部分的場(chǎng)景在鏡面中.你可能需要改變反射場(chǎng)景中的全部像素來覆蓋這個(gè)區(qū)域,這樣它們會(huì)變的不可見.
          --------------------------------------------------------------------------------
          34.我如何做我自己的透視縮放?

          OpenGL會(huì)用模型視點(diǎn)矩陣乘以你的坐標(biāo)系, 然后通過投影矩陣來得到剪裁坐標(biāo)系統(tǒng). 然后會(huì)執(zhí)行透視除法來獲得規(guī)范化設(shè)備坐標(biāo)系.在透視除法階段會(huì)建立一個(gè)透視渲染, 使一個(gè)在遠(yuǎn)處的幾何體會(huì)比在近處的小.透視除法階段通過用裁減坐標(biāo)X, Y, Z的值來除以W來完成的. 例如:

           Xndc = Xcc/Wcc;
           Yndc = Ycc/Wcc;
           Zndc = Zcc/Wcc;

          為了執(zhí)行你自己的透視糾正, 你需要獲得裁減坐標(biāo)W的值.回掉(feedback)緩存提供了同樣的坐標(biāo)系統(tǒng)對(duì)于XYZ設(shè)備坐標(biāo)和W剪裁坐標(biāo).你可以使用 glGetFloatv(GL_CURRENT_RASTER_POSITION, ... ), 而且W值會(huì)再一次在裁減坐標(biāo)系統(tǒng)中, XYZ在設(shè)備坐標(biāo)系統(tǒng)中。


          posted on 2010-08-24 13:54 MEYE 閱讀(348) 評(píng)論(0)  編輯  收藏 所屬分類: Android3D
          主站蜘蛛池模板: 尼勒克县| 丹江口市| 沙洋县| 吉木乃县| 轮台县| 高要市| 嘉黎县| 阳东县| 英超| 澄迈县| 金平| 建昌县| 开鲁县| 云霄县| 京山县| 旬邑县| 三穗县| 两当县| 洱源县| 襄城县| 大田县| 昔阳县| 岗巴县| 分宜县| 吉隆县| 大余县| 措美县| 新巴尔虎左旗| 布拖县| 辽宁省| 榆树市| 阿坝县| 屏东县| 龙岩市| 中山市| 仁寿县| 桃园县| 朔州市| 定兴县| 和平区| 疏勒县|