OpenGL坐標(biāo)系與幾何變換流程

OpenGL中為了將坐標(biāo)從一個(gè)坐標(biāo)系變換到另一個(gè)坐標(biāo)系,我們需要用到幾個(gè)變換矩陣,最重要的幾個(gè)分別是模型(Model)、觀察(View)、投影(Projection)三個(gè)矩陣。我們的頂點(diǎn)坐標(biāo)起始于局部空間(Local Space),在這里它稱為局部坐標(biāo)(Local Coordinate),它在之后會(huì)變?yōu)槭澜缱鴺?biāo)(World Coordinate),觀察坐標(biāo)(View Coordinate),裁剪坐標(biāo)(Clip Coordinate),并最后以屏幕坐標(biāo)(Screen Coordinate)的形式結(jié)束。下面的這張圖展示了整個(gè)流程以及各個(gè)變換過程做了什么:
  1. 局部坐標(biāo)是對(duì)象相對(duì)于局部原點(diǎn)的坐標(biāo),也是物體起始的坐標(biāo)。
  2. 下一步是將局部坐標(biāo)變換為世界空間坐標(biāo),世界空間坐標(biāo)是處于一個(gè)更大的空間范圍的。這些坐標(biāo)相對(duì)于世界的全局原點(diǎn),它們會(huì)和其它物體一起相對(duì)于世界的原點(diǎn)進(jìn)行擺放。
  3. 接下來我們將世界坐標(biāo)變換為觀察空間坐標(biāo),使得每個(gè)坐標(biāo)都是從攝像機(jī)或者說觀察者的角度進(jìn)行觀察的。
  4. 坐標(biāo)到達(dá)觀察空間之后,我們需要將其投影到裁剪坐標(biāo)。裁剪坐標(biāo)會(huì)被處理至-1.0到1.0的范圍內(nèi),并判斷哪些頂點(diǎn)將會(huì)出現(xiàn)在屏幕上。
  5. 最后,我們將裁剪坐標(biāo)變換為屏幕坐標(biāo),我們將使用一個(gè)叫做視口變換(Viewport Transform)的過程。視口變換將位于-1.0到1.0范圍的坐標(biāo)變換到由glViewport函數(shù)所定義的坐標(biāo)范圍內(nèi)。最后變換出來的坐標(biāo)將會(huì)送到光柵器,將其轉(zhuǎn)化為片段。

我們之所以將頂點(diǎn)變換到各個(gè)不同的空間的原因是有些操作在特定的坐標(biāo)系統(tǒng)中才有意義且更方便。例如,當(dāng)需要對(duì)物體進(jìn)行修改的時(shí)候,在局部空間中來操作會(huì)更說得通;如果要對(duì)一個(gè)物體做出一個(gè)相對(duì)于其它物體位置的操作時(shí),在世界坐標(biāo)系中來做這個(gè)才更說得通,等等。如果我們?cè)敢?,我們也可以定義一個(gè)直接從局部空間變換到裁剪空間的變換矩陣,但那樣會(huì)失去很多靈活性。

接下來我們將要更仔細(xì)地討論各個(gè)坐標(biāo)系統(tǒng):

  • 物體坐標(biāo)系
    這是物體在被應(yīng)用任何變換之前的初始位置和方向所在的坐標(biāo)系,也就是當(dāng)前繪圖坐標(biāo)系。該坐標(biāo)系不是固定的,每個(gè)物體都有他們獨(dú)立的坐標(biāo)系,且僅對(duì)該對(duì)象適用。在默認(rèn)情況下,該坐標(biāo)系與世界坐標(biāo)系重合。當(dāng)物體移動(dòng)或者改變方向時(shí)(通過glTranslatef(),glScalef(), glRotatef()這幾個(gè)函數(shù)進(jìn)行變換),改物體相關(guān)聯(lián)的坐標(biāo)系將隨之移動(dòng)或改變方向。
  • 世界坐標(biāo)系

    世界坐標(biāo)系是系統(tǒng)的絕對(duì)坐標(biāo)系,在沒有建立用戶坐標(biāo)系之前畫面上所有的點(diǎn)的坐標(biāo)都可以在該坐標(biāo)系的原點(diǎn)來確定各自的位置,世界坐標(biāo)系始終是固定不變的。世界坐標(biāo)系是右手坐標(biāo)系:使用右手定則X是你的拇指方向,Y是你的食指方向,Z是你的中指方向。如圖:
  • 攝像機(jī)坐標(biāo)系(照相機(jī)坐標(biāo)系)
    在坐標(biāo)系的范疇里,攝像機(jī)坐標(biāo)系和照相機(jī)坐標(biāo)系都是一樣的意義。照相機(jī)坐標(biāo)系是和觀察者密切相關(guān)的坐標(biāo)系。照相機(jī)坐標(biāo)系和屏幕坐標(biāo)系相似,差別在于照相機(jī)坐標(biāo)系處理3D空間中,而屏幕坐標(biāo)系在2D平面里。默認(rèn)情況下,眼坐標(biāo)系與世界坐標(biāo)系也是重合的。
  • 裁剪坐標(biāo)系
    眼坐標(biāo)到裁剪坐標(biāo)是通過投影完成的。眼坐標(biāo)通過乘以GL_PROJECTION矩陣(投影矩陣)變成了裁剪坐標(biāo)。
  • 歸一化設(shè)備坐標(biāo)系(NDC)
    既然要規(guī)范化,那么就得先有一個(gè)規(guī)范。每種投影,都有一個(gè)剪裁空間,稱之為觀察體,對(duì)正交投影來說是一個(gè)立方體,對(duì)透視投影來說是一個(gè)棱臺(tái)。如果一個(gè)觀察體是一個(gè)x、y、z坐標(biāo)范圍都是 [-1, 1] 的立方體,則稱之為規(guī)范化立方體,這個(gè)就是所謂的規(guī)范。那么,將原來的觀察體,映射到規(guī)范化立方體的過程,就是規(guī)范化。
  • 屏幕坐標(biāo)系
    通常將屏幕上的設(shè)備坐標(biāo)稱為屏幕坐標(biāo)。設(shè)備坐標(biāo)又稱為物理坐標(biāo),是指輸出設(shè)備上的坐標(biāo)。設(shè)備坐標(biāo)用對(duì)象距離窗口左上角的水平距離和垂直距離來指定對(duì)象的位置,是以像素為單位來表示的,設(shè)備坐標(biāo)的 X 軸向右為正,Y 軸向下為正,坐標(biāo)原點(diǎn)位于窗口的左上角。
    從NDC坐標(biāo)到屏幕坐標(biāo)基本上是一個(gè)線性映射關(guān)系。通過對(duì)NDC坐標(biāo)進(jìn)行視口變換得到。這時(shí)候就要用到函數(shù)glViewport(),該函數(shù)用來定義渲染區(qū)域的矩形,也就是最終圖像映射到的區(qū)域。

OpenGL最終的渲染設(shè)備是2D的,我們需要將3D表示的場(chǎng)景轉(zhuǎn)換為最終的2D形式,這個(gè)過程如下圖所示!


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容