概述
電腦顯示器是2D平面,一個3D物體通過OpenGL渲染投影到2D顯示器平面形成圖像,GL_PROJECTION是OpenGL用于投影轉換的矩陣。首先,轉換3D物體的頂點數(shù)據從相機空間到裁剪空間,然后,通過除以W(齊次坐標)從裁剪空間再轉換到標準設備空間(NDC)。
因此,我們需要意識到裁剪計算和NDC轉換都是整合到了GL_PROJECTION矩陣里了。接下來的內容將探討怎么構建投影矩陣,使用6個代表邊界值的參數(shù)分別是:left,right,bottom,top,near , far(下面簡寫為l、r、b、t、n、f)。有一點注意一下,裁剪計算是在轉換成NDC坐標之前發(fā)生的,即在除以(齊次坐標)之前。通過裁剪坐標
,
,
和
(這里的c下標表示裁剪空間)做對比,如果裁剪坐標小于
或大于
將被裁減掉(
),然后OpenGL會重新構建網格邊緣。

透視投影
在透視投影里,一個3D點在一個平頭視錐體里面(相機空間)是要被映射到一個正方體(NDC空間)里的,x坐標的區(qū)間從[l,r]映射到[-1,1],y坐標的區(qū)間從[b,t]映射到[-1,1],z坐標的區(qū)間從[-n,-f]映射到[-1,1]。

注意一點,相機空間是使用右手坐標系統(tǒng),但是NDC坐標空間使用左手坐標系統(tǒng),這就是相機在原點沿著-Z方向看,但是在NDC空間是反過來的。因為glFrustum()僅僅接收正的near和far值,在構造GL_PROJECTION矩陣時我們需要給他們變成負值。
在OpenGL里,一個3D點在相機空間是被投影到near平面(projection plane 即下圖的-n平面)。下面的圖片展示一個點(


從上往下看視錐體,相機空間的x坐標點
同理,從側邊看視錐體可得:
注意到,


因此,我們可以設置裁剪空間的w坐標等于

下一步,我們通過線性關系映射(p下標表示投影空間未有裁剪的)和
(p下標表示投影空間未有裁剪的)到NDC坐標空間的
(n下標表示NDC空間)和
(n下標表示NDC空間),即:[l,r] => [-1,1] [b,t] => [-1,1]




然后使用上面的


注意到,我們故意把等式構造成除以
從上面的等式總結,我們可以找到GL_PROJECTION矩陣第一行和第二行的構造方法

現(xiàn)在GL_PROJECTION矩陣只剩下第三行沒構造好,構造

在相機空間,

為了求出系數(shù)A和B,根據上面等式得出

由等式(1)推出:

把B等式代入等式(2):

把A等式代入等式(1):

得到A和B的等式可導出


當視錐體是個對稱視錐體時,r = -l , t = -b 所以可以簡化矩陣公式:

最后,再審視一下上面等式(3)表達的

正交投影
構造正交投影矩陣 GL_PROJECT比構造透視投影矩陣簡單多了,只需要在相機空間里線性的映射到NDC空間。我們只需要縮放長方體變成正方體,然后移到原點位置,讓我們看看GL_PROJECTION的各元素之間的線性關系吧。







因為正交投影矩陣是不需要用w計算z值的(z值也是線性關系直接求出來,透視投影需要用w來間接計算

當視錐體是對稱長方體,即r = -l、t = -b,有:

坐標轉換:模型坐標 -> 世界坐標 -> 相機坐標 -> 裁剪坐標 -> NDC坐標
原文鏈接