OpenGL 投影矩陣

OpenGL Projection Matrix
OpenGL投影矩陣

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

概述

計(jì)算機(jī)顯示器是一個(gè)2D平面。OpenGL渲染的3D場(chǎng)景必須以2D圖像方式投影到計(jì)算機(jī)屏幕上。GL_PROJECTION矩陣用于該投影變換。首先,它將所有定點(diǎn)數(shù)據(jù)從觀察坐標(biāo)轉(zhuǎn)換到裁減坐標(biāo)。接著,這些裁減坐標(biāo)通過除以w分量的方式轉(zhuǎn)換到歸一化設(shè)備坐標(biāo)(NDC)。

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

注意,視錐剔除(裁減)在裁減坐標(biāo)上執(zhí)行,并且在除以wc之前。裁減坐標(biāo)xc、yc、zc會(huì)與wc做比較檢測(cè)。如果任一坐標(biāo)小于-wc或大于wc,則該頂點(diǎn)將會(huì)拋棄。

接著,OpenGL重新構(gòu)建那些裁減掉的多邊形的邊。

被視錐裁減的三角形

透視投影

OpenGL透視視錐體與NDC

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

注意,觀察坐標(biāo)為右手坐標(biāo)系,NDC使用左手坐標(biāo)系。也就是說,位于原點(diǎn)的照相機(jī)在觀察坐標(biāo)中看向-Z軸,而在NDC中看向+Z軸。因?yàn)間lFrustum()只接收正的近平面與遠(yuǎn)平面距離值,我們需要在構(gòu)建GL_PROJECTION矩陣時(shí)對(duì)他們?nèi)》础?/p>

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

視錐體的俯視圖
視錐體的側(cè)視圖

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

從視錐體的側(cè)視圖看出,yp也使用相同的方式計(jì)算出:

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

因此,我們可以將裁減坐標(biāo)的w分量設(shè)置為-ze。這樣,GL_PROJECTION矩陣的第四行變?yōu)?0,0,-1,0)。

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

映射xp到xn
映射yp到y(tǒng)n

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


注意,我們?yōu)橥敢暢ǎ▁c/wc, yc/wc)將每個(gè)等式相被-ze整除。前面我們已經(jīng)將wc設(shè)置為-ze,大括號(hào)中的項(xiàng)為裁減坐標(biāo)中xc與yc

從這個(gè)等式,我們可以發(fā)現(xiàn)GL_PROJECTION矩陣的第一與第二行。


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

在觀察空間,we等于1。因此,等式變?yōu)椋?/p>

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

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

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

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

我們解出A與B。因此ze與zn的關(guān)系變?yōu)椋?/p>

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

OpenGL透視投影矩陣

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

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

深度緩存精度比較

正交投影


正交椎體與歸一化設(shè)備坐標(biāo)(NDC)

構(gòu)造正交投影的GL_PROJECTION矩陣比透視投影模式簡(jiǎn)單很多。

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

映射Xe到Xn
映射Ye到Y(jié)n
映射Ze到Zn

因?yàn)閷?duì)于正交投影并不需要w分量,GL_PROJECTION矩陣的第4行依舊為(0,0,0,1)。因此,正交投影完整的GL_PROJECTION矩陣為:

OpenGL正交投影矩陣

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


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

?著作權(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)容