OpenGL投影矩陣


  • 概述
  • 透視投影
  • 正交投影

概述

計算機顯示器是一個2D平面。OpenGL渲染的3D場景必須以2D圖像方式投影到計算機屏幕上。GL_PROJECTION矩陣用於該投影變換。首先,它將所有定點數據從觀察坐標轉換到裁減坐標。接着,這些裁減坐標通過除以w分量的方式轉換到歸一化設備坐標(NDC)。

因此,我們需要記住一點:裁減變換(視錐剔除)與NDC變換都保存在GL_PROJECTION矩陣中。下述章節描述如何從6個限定參數(左、右、下、上、近平面、遠平面)構建投影矩陣。

注意,視錐剔除(裁減)在裁減坐標上執行,並且在除以wc之前。裁減坐標xc、yc、zc會與wc做比較檢測。如果任一坐標小於-wc或大於wc,則該頂點將會拋棄。

image

接着,OpenGL重新構建那些裁減掉的多邊形的邊。

視錐體裁減 
被視錐裁減的三角形

透視投影

  OpenGL透視視錐體與NDC
OpenGL透視視錐體與NDC

在透視投影中,截棱錐體(觀察坐標)中的3D點會被映射到立方體(NDC)中。x坐標的范圍從[l,f]到[-1,1],y坐標的范圍從[b,t]到[-1,1],z坐標的范圍從[n,f]到[-1,1]。

注意,觀察坐標為右手坐標系,NDC使用左右坐標系。也就是說,位於原點的照相機在觀察坐標中看向-Z軸,而在NDC中看向+Z軸。因為glFrustum()只接收正的近平面與遠平面距離值,我們需要在構建GL_PROJECTION矩陣時對他們取反。

OpenGL中,觀察空間中的3D點被投影到近平面(投影平面)上。下圖展示觀察空間中的點(xe,ye,ze)如何投影到近平面上的點(xp,yp,zp)。

  視錐體的俯視圖
視錐體的俯視圖
  視錐體的側視圖
視錐體的側視圖

 

從視錐體的俯視圖看出,使用相似三角形比率計算方式將觀察空間的x坐標xe被映射到xp

從視錐體的側視圖看出,yp也使用相同的方式計算出:

注意,xp與yp二者都依賴於ze,它們與-ze成反比例。也就是說,它們都被-ze除。這是構建GL_PROJECTION矩陣的第一點提示。在觀察坐標通過與GL_PROJECTION矩陣相乘變換之后,裁減坐標依舊是其次坐標。它最終通過除以裁減坐標的w分量才變成歸一化設備坐標(NDC)。(更詳細描述參考OpenGL變換。)

,

因此,我們可以將裁減坐標的w分量設置為-ze。這樣,GL_PROJECTION矩陣的第四行變為(0,0,-1,0)。

接着,我們通過線性關系將xp與yp映射到NDC中的xn與yn:[l,r]=>[-1,1],[b,t]=>[-1,1]。

映射xp到xn
映射xp到xn

 

映射yp到yn
映射yp到yn

然后,我們用上面的方程式替換xp與yp

   

注意,我們為透視除法(xc/wc, yc/wc)將每個等式相被-ze整除。前面我們已經將wc設置為-ze,大括號中的項為裁減坐標中xc與yc

從這個等式,我們可以發現GL_PROJECTION矩陣的第一與第二行。

現在,我們僅僅解決GL_PROJECTION矩陣的3行。由於觀察空間中的ze總是投影到近平面上的-n點,zn的計算方法與其他坐標的計算方法有稍許不同。不過我們需要唯一的z值來進行裁剪與深度測試。此外,我們也會進行逆投影(逆變換)操作。因為,我們知道z並不依賴於x與y的值,我們借助w分量找尋zn與ze之間的關系。因此,我們可以像這樣指定GL_PROJECTION矩陣的第三行:

在觀察空間,we等於1。因此,等式變為:

為了計算系數A與B,我們使用(ze,zn)關系式(-n,-1)與(-f,1),且將它們帶入到上述等式。

為了求解A與B,重寫等式(1):

將等式(1')帶入等式(2),然后求解A:

將A帶入等式(1)中,求出B:

我們解出A與B。因此ze與zn的關系變為:

最后,我們解出GL_PROJECTION矩陣的所有元素。完整的投影矩陣為:

OpenGL透視投影矩陣
   OpenGL透視投影矩陣

該投影矩陣為通用截面體。如果視錐體為對稱的,即r=-l且t=-b,則矩陣可簡化為:

在開始后面講述之前,請回顧ze與zn之間的關系:等式(3)。你會注意到它是一個有理數方程且ze與zn並非線性關系。也就是說近平面具有非常高的精度,而遠平面的精度很低。如果[-n,-f]的范圍變得很大,會引起深度精度問題(深度沖突):遠平面附近ze的小變化不會影響zn值。為了最小化深度緩存精度問題,n與f的距離應該盡可能小。

深度緩存精度比較
深度緩存精度比較

正交投影

正交椎體與歸一化設備坐標(NDC)
正交椎體與歸一化設備坐標(NDC)

構造正交投影的GL_PROJECTION矩陣比透視投影模式簡單很多。

觀察空間的xe、ye與ze分量都線性映射到NDC。我們只需將長方體縮放為正方體,然后移動它到原點。讓我們使用線性關系推導出GL_PROJECTION中的所有元素。

映射Xe到Xn
映射xe到xn

 

映射Ye到Yn
映射ye到yn

 

映射Ze到Zn
映射ze到zn

因為對於正交投影並不需要w分量,GL_PROJECTION矩陣的第4行依舊為(0,0,0,1)。因此,正交投影完整的GL_PROJECTION矩陣為:

OpenGL正交投影矩陣
OpenGL正交投影矩陣

如果視錐體是對稱的(r=-l且t=-b),它可以進一步簡化。

 

英文原文:http://www.songho.ca/opengl/gl_projectionmatrix.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM