最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

游戲開發(fā)探究篇:平時玩的 3D 游戲中,各種空間變換到底是怎么回事?

2020-03-31 16:50 作者:C語言編程__Plus  | 我要投稿

每一個游戲可以呈現(xiàn)炫麗效果的背后,需要進(jìn)行一系列的復(fù)雜計算,同時也伴隨著各種各樣的頂點(diǎn)空間變換。渲染游戲的過程可以理解成是把一個個頂點(diǎn)經(jīng)過層層處理最終轉(zhuǎn)化到屏幕上的過程,本文就旨在說明,頂點(diǎn)是經(jīng)過了哪些坐標(biāo)空間后,最終被畫在了我們的屏幕上。

崩壞三.jpg


空間變換的原理

首先,我們來看一個簡單的問題:當(dāng)給定一個坐標(biāo)空間以及其中一點(diǎn)(a, b, c)時,我們是如何知道該點(diǎn)的位置的呢?

從坐標(biāo)空間的原點(diǎn)開始

向x軸方向移動a個單位

向y軸方向移動b個單位

向z軸方向移動c個單位

坐標(biāo)空間的變換就蘊(yùn)含在上面的4個步驟中?,F(xiàn)在,我們已知坐標(biāo)空間C的3個坐標(biāo)軸在坐標(biāo)空間P下的表示Xc, Yc, Zc,以及其原點(diǎn)位置Oc。當(dāng)給定坐標(biāo)空間C中的一點(diǎn)Ac= (a, b, c),我們同樣可以依照上面4個步驟來確定其在坐標(biāo)空間P下的位置Ap

從坐標(biāo)空間的原點(diǎn)開始,即 Oc

向x軸方向移動a個單位,即 Oc+ aXc

向y軸方向移動b個單位,即 Oc+ aXc+ bYc

向z軸方向移動c個單位,即 Oc+ aXc+ bYc+ cZc

對得到的表達(dá)式做如下變換,其中“|”符號表示按列展開


繼續(xù)對其中的加法表達(dá)式做變換,即擴(kuò)展到齊次坐標(biāo)空間做平移變換


現(xiàn)在,我們得到了坐標(biāo)空間C到坐標(biāo)空間P的變換矩陣Mc->p


可以看出Mc->p實際上是通過坐標(biāo)空間C在坐標(biāo)空間P中的原點(diǎn)和坐標(biāo)軸的矢量表示構(gòu)建出來的:把3個坐標(biāo)軸依次放入矩陣的前3列,把原點(diǎn)矢量放到最后一列,再用0和1填充最后一行即可。

我們可以利用反向思維,從這個變換矩陣中提取出坐標(biāo)空間C的原點(diǎn)和坐標(biāo)軸在坐標(biāo)空間P的表示。例如,當(dāng)我們已知從模型空間到世界空間的4×4變換矩陣,我們可以提取出它的第一列,再進(jìn)行歸一化(為了消除縮放的影響)來得到模型空間的x軸在世界空間下的單位矢量表示。同樣的方法可以提取y軸和z軸。

當(dāng)對方向矢量進(jìn)行坐標(biāo)空間變換時,由于矢量是沒有位置的,因此坐標(biāo)空間的原點(diǎn)變換是可以忽略的。那么對方向矢量的坐標(biāo)空間變換就可以使用3×3的矩陣來表示,即


在Shader中,我們常??吹浇厝∽儞Q矩陣的前3行前3列來對法線方向,光照方向進(jìn)行空間變化,這正是原因所在。

一旦求出來Mc->p,Mp->c就可以通過求逆矩陣的方式求出來,因為從坐標(biāo)空間C變換到坐標(biāo)空間P與從坐標(biāo)空間P變換到坐標(biāo)空間C是互逆的兩個過程。當(dāng)Mc->p是一個正交矩陣時,Mc->p的逆矩陣就等于它的轉(zhuǎn)置矩陣,即


此時,我們還可以通過Mc->p反推出坐標(biāo)空間P的坐標(biāo)軸在坐標(biāo)空間C中的表示Xp, Yp, Zp,這些坐標(biāo)軸對應(yīng)的就是Mc->p的每一行。

模型空間

模型空間,是和某個模型或者說是對象有關(guān)的,模型空間也被稱為對象空間或局部空間。

每個模型都有自己獨(dú)立的坐標(biāo)空間,當(dāng)它移動或旋轉(zhuǎn)的時候,模型空間也會跟著移動和旋轉(zhuǎn)。

Unity在模型空間中使用的是左手坐標(biāo)系,因此在模型空間中,+x軸,+y軸,+z軸分別對應(yīng)的是模型的右,上,前向。

模型空間的原點(diǎn)和坐標(biāo)軸通常是由美術(shù)人員在建模軟件里確定好的。當(dāng)導(dǎo)入到Unity中后,我們可以在頂點(diǎn)著色器中訪問到模型的頂點(diǎn)信息,其中就包含了每個頂點(diǎn)的坐標(biāo)。這些坐標(biāo)都是相對于模型空間中的原點(diǎn)(通常位于模型的重心)定義的。


世界空間

世界空間是一個特殊的坐標(biāo)系,因為它建立了我們所關(guān)心的最大空間,即整個游戲空間

在Unity中,世界空間同樣使用了左手坐標(biāo)系。它的x軸,y軸,z軸是固定不變的。

頂點(diǎn)變換的第一步,就是將頂點(diǎn)坐標(biāo)從模型空間轉(zhuǎn)換到世界空間中,這個變換通常叫做模型變換

在Unity中,我們可以通過Transform組件中的值得知模型做了哪些變換。這個值是根據(jù)Transform的父節(jié)點(diǎn)的模型坐標(biāo)空間中的原點(diǎn)定義的,如果這個Transform沒有任何父節(jié)點(diǎn),那么這個值就是相對于世界坐標(biāo)空間定義的。

要將模型空間中的一點(diǎn)轉(zhuǎn)換到其父空間中,需要獲取M子->父,這個矩陣可以通過模型的Transform值得到。Transform中包含了旋轉(zhuǎn),縮放和平移值,則M子->父=? MtranslationMrotateMscale。而從模型空間轉(zhuǎn)換到世界空間的變換矩陣M模型->世界可以通過子空間到父空間變換矩陣,父空間到爺爺空間變換矩陣,連乘,直到世界空間為止得到。

觀察空間

觀察空間也被稱為攝像機(jī)空間,可以認(rèn)為是模型空間的一個特例,即攝像機(jī)的模型空間。

在Unity中,觀察空間使用的是右手坐標(biāo)系,即+x軸指向右方,+y軸指向上方,+z軸指向攝像機(jī)后方

頂點(diǎn)變換的第二步就是將頂點(diǎn)坐標(biāo)從世界空間變換到觀察空間中。這個變換通常叫做觀察變換。

從觀察空間到世界空間的變換矩陣我們同樣可以通過Transform中的值得到,再對該矩陣求逆得到從世界空間到觀察空間的變換矩陣。我們還可以使用另一種方法,對Transform組件中的值直接取反(做逆向變換),然后得到從世界空間到觀察空間的變換矩陣。注意,由于觀察空間使用的是右手坐標(biāo)系,因此還需要對變換矩陣的z分量進(jìn)行取反操作。

裁剪空間.jpg


裁剪空間

頂點(diǎn)接下來要從觀察空間轉(zhuǎn)換到裁剪空間中,這個變換可以被稱為投影變換。這個用于變換的矩陣叫做裁剪矩陣或是投影矩陣

裁剪空間的目的是能夠方便地對渲染圖元進(jìn)行裁剪:完全位于這塊空間內(nèi)部的圖元將會被保留,完全位于這塊空間外部的圖元將會被剔除,與這塊空間邊界相交的圖元就會被裁剪。而這塊空間就是由視椎體來決定的。

視椎體有兩種類型,分別對應(yīng)兩種投影類型:透視投影(下圖左)和正交投影(下圖右)。透視投影模擬了人眼看世界的方式,而正交投影則完全保留了物體的距離和角度。


投影矩陣雖然叫做投影矩陣,但并沒有真正進(jìn)行投影,而是為投影做準(zhǔn)備。目的是對x,y,z分量進(jìn)行縮放,經(jīng)過投影矩陣的縮放后,我們可以直接使用w分量作為范圍值,只有x,y,z分量都位于這個范圍內(nèi)的頂點(diǎn)才認(rèn)為是在裁剪空間內(nèi)。并且w分量在真正的投影時也會用到。

透視投影和正交投影分別對應(yīng)了不同的投影矩陣。還需要注意的是投影矩陣會改變空間的旋向性:空間從右手坐標(biāo)系變換到了左手坐標(biāo)系

透視投影


其中FOV表示視椎體垂直方向的張開角度,而Near和Far分別控制了近裁剪平面和遠(yuǎn)裁剪平面距離攝像機(jī)的遠(yuǎn)近。這樣我們可以求出近裁剪平面的高度,如下所示。遠(yuǎn)裁剪平面類似。


而根據(jù)攝像機(jī)的橫縱比信息,我么就可以得到近裁剪平面的寬度


一個頂點(diǎn)和透視投影的投影矩陣相乘后得到的結(jié)果如下


視椎體的變化如下所示


此時我們就可以按如下不等式來判斷一個變換后的頂點(diǎn)是否位于視椎體內(nèi)


正交投影


其中Size表示視椎體豎直方向上高度的一半,而Near和Far同樣分別控制了近裁剪平面和遠(yuǎn)裁剪距離攝像機(jī)的遠(yuǎn)近。則近裁剪平面的高度如下所示。遠(yuǎn)裁剪平面類似。


近裁剪平面的高度同樣可以通過攝像機(jī)的縱橫比得到


一個頂點(diǎn)和正交投影的投影投影矩陣相乘后得到的結(jié)果如下


視椎體的變化如下所示


判斷一個變換后的頂點(diǎn)是否位于視椎體內(nèi)使用的不等式和透視投影中的一樣,這種通用性也是為什么要使用投影矩陣的原因之一。

屏幕空間

當(dāng)完成了所有的裁剪工作后,就需要進(jìn)行真正的投影了,即把視椎體投影到屏幕空間中,這個過程可以被稱為屏幕映射。經(jīng)過這一步變換,我們會得到真正的像素位置,對應(yīng)的2D坐標(biāo),而不是虛擬的三維坐標(biāo)。這個過程可以理解成有兩步:

進(jìn)行標(biāo)準(zhǔn)齊次除法,也被稱為透視除法。就是把齊次坐標(biāo)系的x,y,z分量都除以w分量。在OpenGL中把這一步得到的坐標(biāo)叫做歸一化的設(shè)備坐標(biāo)(NDC)。經(jīng)過透視投影變換后的裁剪空間會變換到一個立方體內(nèi),而正交投影的裁剪空間本身就是一個立方體(它的w分量是1,齊次除法不會對它產(chǎn)生影響)。在Unity中這個立方體的x,y,z分量的范圍都是[-1, 1],和OpenGL保持一致。


經(jīng)過齊次除法后,透視投影和正交投影的視椎體都變換到一個相同的立方體內(nèi)。現(xiàn)在,我們可以根據(jù)變換后的x,y坐標(biāo)來映射輸出窗口對應(yīng)的像素坐標(biāo)。

在Unity中,屏幕空間左下角的像素是(0, 0),右上角的像素坐標(biāo)是(pixelWidth, pixelHeight)。齊次除法和屏幕映射的過程可以使用下面的公式來表示

screenx=clipx?pixelWidth2?clipw+pixelWidth2

screeny=clipy?pixelHeight2?clipw+pixelHeight2

在Unity中,從裁剪空間到屏幕空間的轉(zhuǎn)換是由底層幫我們完成的。我們的頂點(diǎn)著色器只需要把頂點(diǎn)轉(zhuǎn)換到裁剪空間即可(模型空間-世界空間-觀察空間-裁剪空間,對應(yīng)的矩陣通常會串聯(lián)成一個MVP矩陣)。

法線變換

最后,我們再來看一種特殊的變換:法線變換。在游戲中,模型的一個頂點(diǎn)往往會攜帶額外的信息,而頂點(diǎn)法線和切線就是其中的兩種信息,切線和法線是互相垂直的。

由于切線是由兩個頂點(diǎn)之間的差值計算得到的,因此我們可以直接使用變換頂點(diǎn)的矩陣MA->B來變換切線。但如果直接使用MA->B來變換法線,得到的新法線可能就不會和切線垂直了。例如下圖所示.


那么應(yīng)該使用哪個矩陣來變換法線呢?我們可以通過數(shù)學(xué)約束條件推出這個矩陣。由于頂點(diǎn)法線NA和切線TA垂直,則TANA= 0。給定變換矩陣MA->B,我們已知TB= MA->BTA。現(xiàn)在我們要找到一個矩陣G來變換法線NA,使得變換后的法線仍然與切線垂直,即


通過一些推導(dǎo)可得


由于TANA= 0,因此可得



這說明使用原變換矩陣的逆轉(zhuǎn)置矩陣來變換法線就可以得到正確的結(jié)果。

值得注意的是,如果矩陣MA->B是正交矩陣,則我們可以直接使用原變換矩陣作為法線的變換矩陣。如果變換只包含旋轉(zhuǎn)和統(tǒng)一縮放,我們可以利用統(tǒng)一縮放系數(shù)k來得到變換矩陣MA->B的逆轉(zhuǎn)置矩陣,這樣可以避免計算逆矩陣的過程。

視口空間

視口空間中的坐標(biāo)被稱為視口坐標(biāo),就是把屏幕歸一化,這樣屏幕左下角就是(0, 0),右上角就是(1, 1)。如果已知屏幕坐標(biāo)的話,我們只需要把x,y分量除以屏幕分辨率即可得到視口坐標(biāo)。如果已知裁剪空間中的坐標(biāo),可以通過以下公式得到視口坐標(biāo)

這樣看來,一款3D游戲的開發(fā)成型,背后的程序員們付出的努力可不少呢!

作者:博客園丨iwiniwin

出處:http://www.cnblogs.com/iwiniwin/

本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上原文出處鏈接和本聲明。

本篇文章就到這里啦!學(xué)習(xí)C/C++編程,了解程序員更多小知識歡迎關(guān)注UP~

游戲開發(fā)探究篇:平時玩的 3D 游戲中,各種空間變換到底是怎么回事?的評論 (共 條)

分享到微博請遵守國家法律
陇川县| 马山县| 满城县| 陵川县| 达尔| 八宿县| 大连市| 金秀| 托里县| 安丘市| 玉龙| 昭觉县| 南和县| 凤凰县| 长阳| 竹溪县| 乐陵市| 柳河县| 启东市| 民权县| 永丰县| 竹北市| 武冈市| 朝阳县| 武城县| 双流县| 青阳县| 繁峙县| 呼和浩特市| 河源市| 柯坪县| 洪洞县| 礼泉县| 邳州市| 洛川县| 河津市| 宁国市| 昆山市| 孝义市| 措勤县| 温州市|