2D笛卡爾坐標(biāo)
在二維繪圖中,最為常用的坐標(biāo)系統(tǒng)是笛卡爾坐標(biāo)系統(tǒng). 笛卡爾坐標(biāo)由一個(gè)X和一個(gè)Y坐標(biāo)構(gòu)成.X表示水平方向位置,Y表示垂直方向的位置.

3D笛卡爾坐標(biāo)系
將2D笛卡爾坐標(biāo)系系統(tǒng)擴(kuò)展到三維空間中.從水平和垂直方向,增加了深度分量.用Z來表示,Z軸同時(shí)垂直于X,Y軸.可以用3個(gè)坐標(biāo)(X,Y,Z)來指定三維空間中的一個(gè)位置.

視口
窗口是以像素為單位度量. 在開始在窗口中繪制點(diǎn),線,形狀之前,必須告訴OpenGL 如何把指定坐標(biāo)映射為屏幕坐標(biāo).
坐標(biāo)系統(tǒng)必須從笛卡爾坐標(biāo)映射到物理屏幕像素坐標(biāo). 這個(gè)映射是通過一種叫做視口(viewPort)的設(shè)置來指定.
在我們代碼中,我們會(huì)通過glViewPort函數(shù)來實(shí)現(xiàn)視口的設(shè)計(jì). 視口就是窗口內(nèi)部用于繪制裁剪區(qū)域的客戶區(qū)域.


投影:從3D到2D
不管我們覺得自己的眼睛看到的三維立體圖像多么真實(shí).屏幕上像素實(shí)際上只有二維的. 是無法真實(shí)去呈現(xiàn)立體圖形.
那么OpenGL 是如何將笛卡爾坐標(biāo)系映射成可以在屏幕上顯示的二維坐標(biāo)的?
在這里需要用到投影.
我們需要 指定投影空間 -> 指定在窗口顯示的視景體(Viewing Volume) -> 指定如何對它進(jìn)行變換.
舉例子: 類似于立體圖像站在鏡子前.
投影分為2種.
- 第一種正投影(Orthographics Projection)或平行投影. 使用正投影時(shí),需要指定一個(gè)正方形/長方形的視景體. 在視景體以外的任何物體都不會(huì)被繪制. 并且使用正投影所以實(shí)際大小相同的物體在屏幕上都具有相同的大小.不管它們是否存在遠(yuǎn)近問題. 正投影比較適合平面圖形/2D圖形渲染時(shí)使用.
- 第二種透視投影(Perspective Projection).它在3D開發(fā)中更為常見. 同樣需要指定視景體的.而這個(gè)視景體并不是類似于正方體,看起來像平截體. 透視投影一般會(huì)使用于3D圖像渲染.因?yàn)樗鼤?huì)更加逼真.

左手坐標(biāo)系和右手坐標(biāo)系

注意OpenGL中坐標(biāo)系 OpenGL中的物體、世界、照相機(jī)坐標(biāo)系都屬于右手坐標(biāo)系,而規(guī)范化設(shè)備坐標(biāo)系使用左手坐標(biāo)系?;\統(tǒng)地說OpenGL使用右手坐標(biāo)系是不合適的
坐標(biāo)系
OpenGL 希望每次頂點(diǎn)著色后,我們的可見頂點(diǎn)都為標(biāo)準(zhǔn)化設(shè)備坐標(biāo)(Normalized Device Coordinate,NDC)。也就是說每個(gè)頂點(diǎn)的z,y,z都應(yīng)該在?1到1之間,超出這個(gè)范圍的頂點(diǎn)將是不可見的。
通常情況下我們會(huì)自己設(shè)定一個(gè)坐標(biāo)范圍,之后再在頂點(diǎn)著色器中將這些坐標(biāo)變換為轉(zhuǎn)化設(shè)備坐標(biāo)。然后這些標(biāo)化設(shè)備坐標(biāo)傳入光柵器(Rasterizer),將它們變換為屏幕上的二維坐標(biāo)和像素。
將坐標(biāo)變換為標(biāo)準(zhǔn)化設(shè)備坐標(biāo),接著再轉(zhuǎn)化為屏幕坐標(biāo)的過程通常是分步進(jìn)行的,也就是類似于流水線那樣子。在流水線中,物體的頂點(diǎn)在最終轉(zhuǎn)化為屏幕坐標(biāo)之前還會(huì)被變換到多個(gè)坐標(biāo)系統(tǒng)(Coordinate System)。將物體的坐標(biāo)變換到幾個(gè)過渡坐標(biāo)系(Intermediate Coordinate System)的優(yōu)點(diǎn)在于,在這些特定的坐標(biāo)系統(tǒng)中,一些操作或運(yùn)算更加方便和容易,這一點(diǎn)很快就會(huì)變得很明顯。對我們來說比較重要的總共有5個(gè)不同的坐標(biāo)系統(tǒng)
- 局部空間(Local Space,或者稱為物體空間(Object Space))
- 世界空間(World Space)
- 觀察空間(View Space,或者稱為視覺空間(Eye Space))
- 裁剪空間(Clip Space)
- 屏幕空間(Screen Space)
就是一個(gè)頂點(diǎn)在最終被轉(zhuǎn)化為片段之前需要經(jīng)歷的所有不同狀態(tài).為了將坐標(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ì)變成世界坐標(biāo)(world Coordinate),觀測坐標(biāo)(View Coordinate),裁剪坐標(biāo)(Clip Coordinate),并最后以屏幕坐標(biāo)(Screen Corrdinate)的形式結(jié)束
在3D圖形學(xué)中常用的坐標(biāo)系:
- 世界坐標(biāo)系
- 物體坐標(biāo)系
- 攝像機(jī)坐標(biāo)系
- 慣性坐標(biāo)系
世界坐標(biāo)系: 世界坐標(biāo)系是系統(tǒng)的絕對坐標(biāo)系,在沒有建立用戶坐標(biāo)系之前畫面上所有的點(diǎn)的坐標(biāo)都可以在該坐標(biāo)系的原點(diǎn)來確定各自的位置.世界坐標(biāo)系始終是固定不變的
物體坐標(biāo)系: 每個(gè)物體都有他們獨(dú)立的坐標(biāo)系.當(dāng)物理移動(dòng)或者改變方向時(shí).該物體相關(guān)聯(lián)的坐標(biāo)系將隨之移動(dòng)或改變方向。
物體坐標(biāo)系是以物體本身而言,比如,我先向你發(fā)指令,“向前走一步”,是向您的物體坐標(biāo)體系指令。我并不知道你會(huì)往哪個(gè)絕對的方向移動(dòng)。比如說,當(dāng)你開車時(shí),有人會(huì)說向左轉(zhuǎn),有人說向東。但是,向左轉(zhuǎn)是物體坐標(biāo)系的概念,而向東則是世界坐標(biāo)系中的。
在某種情況下,我們可以理解物體坐標(biāo)系為模型坐標(biāo)系。因?yàn)槟P晚旤c(diǎn)的坐標(biāo)都是在模型坐標(biāo)系中描述的。
攝像機(jī)(照相機(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平面里。

慣性坐標(biāo)系: 指的是世界坐標(biāo)系到物體坐標(biāo)系的"半途". 慣性坐標(biāo)系的原點(diǎn)和物體坐標(biāo)原點(diǎn)重合,但慣性坐標(biāo)系的軸平行于世界坐標(biāo)系的軸.
為什么要引入慣性坐標(biāo)系?因?yàn)槲矬w坐標(biāo)系轉(zhuǎn)換到慣性坐標(biāo)系只需要旋轉(zhuǎn),從慣性坐標(biāo)系轉(zhuǎn)換到世界坐標(biāo)系只需要平移.

坐標(biāo)變換的全局圖
OpenGL最終的渲染設(shè)備是2D的,我們需要將3D表示的場景轉(zhuǎn)換為最終的2D形式,前面使用模型變換和視變換將物體坐標(biāo)轉(zhuǎn)換到照相機(jī)坐標(biāo)系后,需要進(jìn)行投影變換,將坐標(biāo)從相機(jī)—>裁剪坐標(biāo)系,經(jīng)過透視除法后,變換到規(guī)范化設(shè)備坐標(biāo)系(NDC),最后進(jìn)行視口變換后,3D坐標(biāo)才變換到屏幕上的2D坐標(biāo),這個(gè)過程如下圖所示

在上面的圖中,注意,OpenGL只定義了裁剪坐標(biāo)系、規(guī)范化設(shè)備坐標(biāo)系和屏幕坐標(biāo)系,而局部坐標(biāo)系(模型坐標(biāo)系)、世界坐標(biāo)系和照相機(jī)坐標(biāo)系都是為了方便用戶設(shè)計(jì)而自定義的坐標(biāo)系,它們的關(guān)系如下圖所示

圖中左邊的過程包括模型變換、視變換,投影變換,這些變換可以由用戶根據(jù)需要自行指定,這些內(nèi)容在頂點(diǎn)著色器中完成
圖中右邊的兩個(gè)步驟,包括透視除法、視口變換,這兩個(gè)步驟是OpenGL自動(dòng)執(zhí)行的,在頂點(diǎn)著色器處理后的階段完成
將坐標(biāo)系統(tǒng)組合在一起

OpenGL 然后對裁剪坐標(biāo)執(zhí)行透視除法從而將它們變換到標(biāo)準(zhǔn)化設(shè)備坐標(biāo)。OpenGL 會(huì)使用glViewPort內(nèi)部的參數(shù)來將標(biāo)準(zhǔn)化設(shè)備坐標(biāo)映射到屏幕坐標(biāo),每個(gè)坐標(biāo)都關(guān)聯(lián)了一個(gè)屏幕上的點(diǎn)。這個(gè)過程稱為視口變換。