OpenGL透視投影下的模型視圖矩陣/投影矩陣/觀察者矩陣

一.首先我們先來(lái)看看這些矩陣在透視投影下的位置

位置

? ??????特別說(shuō)明:objectFrame是用來(lái)記錄物體發(fā)生旋轉(zhuǎn)/平移/縮放等的矩陣(暫且命名為模型矩陣吧),模型視圖矩陣(modelViewMatrix)在物體沒有發(fā)生變化的時(shí)候,它是由單元矩陣*觀察者矩陣*投影矩陣,當(dāng)物體發(fā)生變化,模型視圖矩陣就變成:先觀察 -> 物體變換 -> 投影,也就是說(shuō)單元矩陣*觀察者矩陣*objectFrame*投影矩陣

?????????世界上任何事物,當(dāng)觀察者出于的位置不同,事物所呈現(xiàn)在觀察者的眼中的畫面也是不一樣的,就比如當(dāng)一個(gè)帥哥/美女站在你面前,你是觀察者,你說(shuō)處于的位置不同,所看到的也不一樣,更加形象的說(shuō),世界上任何一種物體(包括人),都可以用一個(gè)正方體或者長(zhǎng)方體包裹起來(lái),那么從觀察者的角度,你最多也就只能看到三個(gè)面(總共6個(gè)),所以觀察者非常重要。絕大部分計(jì)算機(jī)的顯示器是二維的(a 2D surface)。在OpenGL中一個(gè)3D場(chǎng)景需要被投影到屏幕上成為一個(gè)2D圖像(image)。這稱為投影變換,需要用到投影矩陣(projection matrix)。首先,投影矩陣會(huì)把所有頂點(diǎn)坐標(biāo)從eye coordinates(觀察空間,eye space或view space)變換到裁剪坐標(biāo)(clip coordinated,屬于裁剪空間,clip space)。然后,這些裁剪坐標(biāo)被變換到標(biāo)準(zhǔn)化設(shè)備坐標(biāo)(normalized device coordinates, NDC,即坐標(biāo)范圍在-1到1之間),這一步是通過(guò)用用裁剪坐標(biāo)的wcwc分量除裁剪坐標(biāo)實(shí)現(xiàn)的。因此,我們要記住投影矩陣干了兩件事: 裁剪clipping(即frustum culling,視景體剔除)和生成NDC。

流程

? ??????得到了觀察者矩陣/投影矩陣/模型視圖矩陣后下一步我們就要涉及到一個(gè)新的感念------->壓棧 PushMatrix()&&出棧PopMatrix();此圖引用于:http://www.itdecent.cn/p/ce3b51b8f168,作者:凡幾多


壓/出棧流程圖


二.什么是矩陣/矩陣的作用

????????我們可以把矩陣?yán)斫鉃橹环N工具,它可以描述的內(nèi)容有很多,比如:

1.線性變換

2.線性方程(很多教材都是從這里開始寫矩陣的)

3.用于表示一些代數(shù)

4.排列數(shù)(permutation)

5.可達(dá)性(圖論)

6.以及很多應(yīng)用上,比如層次分析法中的比較矩陣、神經(jīng)網(wǎng)絡(luò)中數(shù)據(jù)傳遞的過(guò)程等等

????????這里我們主要講的是線性變換(如果你已經(jīng)忘了大學(xué)的線性代數(shù),可以在網(wǎng)上查一查資料復(fù)習(xí)一下,沒有學(xué)過(guò)線性代數(shù)的程序猿問(wèn)題不大,只是在這里坐一個(gè)簡(jiǎn)單的介紹,你只需要在代碼中知道調(diào)用矩陣函數(shù)的時(shí)候在做什么,怎么傳參數(shù)就行)

什么是線性變換?

????????對(duì)于一個(gè)變換 的A,它可以滿足可加性與齊次性

基本公式

然后矩陣可以很清晰地刻畫這種變換。為什么這么說(shuō)?

通過(guò)齊次性能夠發(fā)現(xiàn),對(duì)于一條線上的子空間所有向量經(jīng)過(guò)變換后的結(jié)果,只與該空間的單位向量差一個(gè)系數(shù)。這也就是說(shuō),如果想要真正具體地描述一個(gè)線性變換,只需要分別知道:每個(gè)維度上單位向量經(jīng)過(guò)線性變換后的結(jié)果。然后用由單位向量得到的“結(jié)果”來(lái)刻畫整個(gè)變化。

比如說(shuō):在3維空間中,很容易想到就只有三個(gè)坐標(biāo)軸,

單元矩陣

比如說(shuō),你想把x軸投射到y(tǒng)軸,y軸投射到z軸,z軸投射到x軸(長(zhǎng)度不變)這一變換。那么就需要,讓x軸出現(xiàn)在y'軸的位置,y軸出現(xiàn)在z'軸的位置,z軸出現(xiàn)在x'軸的位置。即一個(gè)排列組合?

變換過(guò)程

就成為這樣的矩陣,將左邊三個(gè)向量都橫過(guò)來(lái),然后第一個(gè)向量擺在第一行,第二個(gè)向量擺在第二行,第三個(gè)向量擺在第三行。

矩陣就是描述這一過(guò)程的重要手段

三.OpenGL變換數(shù)據(jù)概覽

OpenGL變換數(shù)據(jù)概覽

變換 應(yīng)用

1.視圖 制定觀察者或照相機(jī)的位置?

2.模型 在場(chǎng)景中移動(dòng)物體?

3.模型視圖 描述視圖和模型變換的二元性?

4.投影 改變視窗體 的大小或重新設(shè)置它的形狀?

5.視口 這是一種偽變換,只是對(duì)窗口上的最終輸出進(jìn)行縮放

視覺坐標(biāo)

????????笛卡爾坐標(biāo)系:從觀察者的角度來(lái)看,x軸和y軸的正方向分別指向右方和上方。z軸的正方向從原點(diǎn)指向使用者,而z軸的負(fù)方向則從觀察者指向屏幕內(nèi)部。 當(dāng)我們利用OpenGL進(jìn)行3D繪制時(shí),就會(huì)使用笛卡爾坐標(biāo)系。如果不進(jìn)行任何變換,那么使用的坐標(biāo)系將與剛剛描述的視覺坐標(biāo)系相同。


視覺觀察坐標(biāo)

視圖變換

????????視圖變換允許我們把觀察點(diǎn)放在所希望的任何位置,并允許在任何方向上觀察場(chǎng)景。確定視圖變換就像在場(chǎng)景中放置照相機(jī)并讓它指向某個(gè)方向。

模型變換

????????模型變換用于操縱模型和其中的特定對(duì)象。這些變換將對(duì)象移動(dòng)到需要的位置,然后再對(duì)它們進(jìn)行旋轉(zhuǎn)和縮放。

投影變換

????????投影變換將在模型視圖變換之后應(yīng)用到頂點(diǎn)上,它將指定一個(gè)完成的場(chǎng)景(所有模型變換都已完成)是如何投影到屏幕上的最終圖像。

????????正投影:所有多邊形都是精確地按照指定的相對(duì)大小來(lái)在屏幕上繪制的。

????????透視投影:透視投影的特點(diǎn)是透視縮短,這種特性使得遠(yuǎn)處的物體看起來(lái)比進(jìn)出同樣大小的物體更小一些。

視口變換

????????當(dāng)所有變換完成后,就得到了一個(gè)場(chǎng)景的二維投影,它將被映射到屏幕上某處的窗口上。這種到物理創(chuàng)口標(biāo)的映射是我們最后要做的變換,稱為視口變換。

模型視圖矩陣

????????模型視圖矩陣是一個(gè)4X4矩陣,它表示一個(gè)變換后的坐標(biāo)系,我們可以用來(lái)放置對(duì)象和確定對(duì)象的方向。一個(gè)包含單個(gè)頂點(diǎn)數(shù)據(jù)的矩陣乘以模型視圖矩陣后得到新的視覺坐標(biāo)。OpenGL并不是將一個(gè)4X4矩陣表示為一個(gè)浮點(diǎn)值的二維數(shù)組,而是將它表示為一個(gè)由16個(gè)浮點(diǎn)值組成的單個(gè)數(shù)組。

矩陣

? ??????重點(diǎn)重點(diǎn)重點(diǎn)(重要的事情說(shuō)三遍):前三縱列分別對(duì)應(yīng)x軸,y軸,z軸上的方向。 如果有一個(gè)包含一個(gè)不同坐標(biāo)系的位置和方向的4X4矩陣,然后用一個(gè)表示原來(lái)坐標(biāo)系的向量(表示為一個(gè)列矩陣或向量)乘以這個(gè)矩陣,得到的結(jié)果是一個(gè)轉(zhuǎn)換到新坐標(biāo)系下的新向量。這就意味著,空間中任意位置和任何想要的方向都可以由一個(gè)4X4矩陣唯一確定,并且如果用一個(gè)對(duì)象的所有向量乘以這個(gè)矩陣,那么我們就將整個(gè)對(duì)象變換到了空間中的給定位置和方向。

單元矩陣(Identity)

????????單元矩陣中除了對(duì)角線上的一組元素之外,其他元素均為0。將一個(gè)向量乘以一個(gè)單位矩陣,就相當(dāng)于用這個(gè)向量乘以1,不會(huì)發(fā)生任何改變。

四.上代碼

1.設(shè)置觀察者矩陣


????????在函數(shù)SetupRC中,我們可以看到這樣一行代碼:cameraFrame.MoveForward(-15.0f);在上面我已經(jīng)講到了視覺坐標(biāo),這行代碼的意思就是觀察者向后移15,注意注意注意:此時(shí)我們得到的只是觀察者的坐標(biāo)位置,想用矩陣來(lái)表示這個(gè)位置,我們把這個(gè)點(diǎn)乘以單元矩陣就得到了我們的觀察者矩陣,具體代碼是://調(diào)用頂部載入單元矩陣modelViewMatrix.LoadIdentity();它就自動(dòng)將觀察者位置用矩陣表示出來(lái),當(dāng)然你也可以不調(diào)用,因?yàn)樵谏厦娴膲?b>棧/出棧的流程圖里可以看出有一個(gè)矩陣1,這個(gè)矩陣1就是單元矩陣,默認(rèn)存在單元矩陣,個(gè)人理解是在壓棧的時(shí)候把傳人的點(diǎn)的坐標(biāo)變成矩陣(理解不對(duì)的,請(qǐng)大神批評(píng)教育)

2設(shè)置投影矩陣

在函數(shù)void ChangeSize(int w, int h)里面,

步驟說(shuō)明:創(chuàng)建矩陣,加載矩陣

參數(shù):35----->你可以理解為眼睛張開的角度

?float(w) / float(h)---->(縱橫比)

1.0f ----->近平面離觀察者的位置

500.f---->遠(yuǎn)平面的位置

? ??????注意:近平面和遠(yuǎn)平面的參數(shù)可以修改,但是你想完整的在2D空間展示圖形,這個(gè)之間形成的立方體要足夠當(dāng)?shù)孟挛矬w,不然超出的部分將被裁減

3.設(shè)置模型矩陣(模型矩陣objectFrame,不是模型視圖矩陣,個(gè)人理解,如有錯(cuò)誤請(qǐng)批評(píng)教育)

? ? ?重新強(qiáng)調(diào)一下:objectFrame是用來(lái)記錄物體發(fā)生旋轉(zhuǎn)/平移/縮放等的矩陣(暫且命名為模型矩陣吧),模型視圖矩陣(modelViewMatrix)在物體沒有發(fā)生變化的時(shí)候,是一個(gè)單元矩陣,當(dāng)物體發(fā)生變化,模型視圖矩陣就變成:先觀察 -> 物體變換 -> 投影,也就是說(shuō)單元矩陣*觀察者矩陣*objectFrame*投影矩陣

所以我們用GLFrame? ? ? ? ? ? objectFrame記錄物體的點(diǎn),然后乘以單元矩陣,最后就得到了模型矩陣,在

我們會(huì)看到關(guān)于模型視圖矩陣:

特別的是在最后,你會(huì)看到

這里就是為了還原模型視圖矩陣,其本質(zhì)就是把模型視圖矩陣設(shè)置為單元矩陣,防止影響其他視圖

記錄(objectFrame)物體的點(diǎn)在物體坐標(biāo)的的位置,


通過(guò)乘以單元矩陣

就得到了模型矩陣,最后在壓棧的過(guò)程中,將觀察者矩陣,模型矩陣,投影矩陣相乘,得到模型視圖矩陣,最后通過(guò)變換管道,提交給shaderManager

提交


最后:附上代碼https://pan.baidu.com/s/1OeSWGPGBlOgFrPZeGMS_bw提取碼:ae9x

最后編輯于
?著作權(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ù)。

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