平時在工作中經(jīng)常遇到各種跟坐標(biāo)系相關(guān)的概念,比如Clip Space等洞渤,由于并非日夜相對阅嘶,因此也常常忘記其原本的含義,為了避免查閱資料的重復(fù)勞動载迄,此處將相關(guān)概念整合到一起讯柔,方便需要時能夠迅速檢索。
1. 空間坐標(biāo)系
我們知道护昧,在圖形學(xué)中魂迄,是存在著多套坐標(biāo)系的,比如世界坐標(biāo)系惋耙,相機坐標(biāo)系等捣炬,而之所以使用多套坐標(biāo)系,而不將它們完全統(tǒng)一成一套坐標(biāo)系绽榛,是因為同一套坐標(biāo)系在不同的應(yīng)用場景中可能會存在這樣那樣的理解與使用上的問題湿酸,當(dāng)然這也就為我們學(xué)習(xí)與工作中的使用與理解帶來了困難。
1.1 世界空間坐標(biāo)系
世界空間坐標(biāo)系灭美,簡稱世界坐標(biāo)系推溃,指的是將整個世界(比如地圖)包裹起來的一個四維坐標(biāo)系,這個坐標(biāo)系同時也稱為全局坐標(biāo)系(所有物件公有的一套坐標(biāo)系)或者絕對坐標(biāo)系(不隨視角或者其他因素而變化)届腐。
場景中的每個物件在世界坐標(biāo)系中都有一套對應(yīng)的坐標(biāo)或者更廣泛的說Transform(包含Position/Rotation/Scale等數(shù)據(jù))铁坎,這套Transform是相對于世界坐標(biāo)系約定的原點以及正向XYZ坐標(biāo)軸而給定的。
世界坐標(biāo)系比較簡單犁苏,也很容易理解厢呵,這里就只做下簡單介紹。
1.2 模型空間坐標(biāo)系
模型坐標(biāo)系是一套三維局部坐標(biāo)系傀顾,是出于編輯方便的考慮襟铭,以模型上某點(通常是中心點)為原點,約定三個正交方向為XYZ正方向的坐標(biāo)系短曾。
模型坐標(biāo)系通常用于建模軟件以及引擎編輯器的模型編輯等界面中寒砖,模型自身相關(guān)的頂點等數(shù)據(jù)通常是按照模型坐標(biāo)系進(jìn)行存儲的,在渲染使用的時候嫉拐,需要通過自身相對于世界坐標(biāo)系的Transform將之轉(zhuǎn)換到世界坐標(biāo)系中哩都。
1.3 相機空間坐標(biāo)系
相機坐標(biāo)系也是一套四維全局坐標(biāo)系,對應(yīng)的是以相機為原點婉徘,以相機LookAt方向為Z軸正方向的坐標(biāo)系漠嵌,這個坐標(biāo)系是出于獲取以觀察者(玩家或者相機)為參考原點的相對坐標(biāo)的需要而建立的咐汞,一個靜態(tài)模型在相機空間坐標(biāo)系中的位置信息會隨著相機的移動與旋轉(zhuǎn)而變化。
1.4 裁剪空間坐標(biāo)系
裁剪坐標(biāo)系(Clip Space)指的是相機坐標(biāo)系經(jīng)過投影矩陣轉(zhuǎn)換后得到的空間坐標(biāo)系儒鹿,之所以叫裁剪坐標(biāo)系化撕,是因為投影矩陣約定了視角的上下左右前后邊界(對應(yīng)的是相機的Frustum范圍),后面會將處于邊界之外的數(shù)據(jù)直接Clip到邊界上约炎。
通常植阴,Vertex Shader輸出的頂點坐標(biāo)就處于這個坐標(biāo)系中,后面硬件會自動根據(jù)裁剪坐標(biāo)剔除掉越界部分圾浅,假設(shè)某個點的坐標(biāo)為(x, y, z, w)掠手,那么XY方向上處于[-w, w]之外的內(nèi)容會被剔除,Z方向上在OpenGL中也是[-w, w]狸捕,而在DirectX中喷鸽,則是[0, w]。
1.5 標(biāo)準(zhǔn)設(shè)備坐標(biāo)系
與裁剪坐標(biāo)系相關(guān)的一個概念叫標(biāo)準(zhǔn)設(shè)備坐標(biāo)(Normalized Device Coordinates灸拍,簡稱NDC)魁衙,實際上這個坐標(biāo)跟我們說的裁剪坐標(biāo)系中的坐標(biāo)并不是同一個東西,所謂的NDC指的是與設(shè)備平臺無關(guān)的一套三維坐標(biāo)系(比如同一個物件株搔,無論設(shè)備使用什么樣的分辨率剖淀,在這個坐標(biāo)系中的數(shù)值都是相同的)。
標(biāo)準(zhǔn)設(shè)備坐標(biāo)系與裁剪坐標(biāo)系的關(guān)聯(lián)與區(qū)別在于纤房,NDC是裁剪坐標(biāo)系中的四維坐標(biāo)clip除以第四維齊次坐標(biāo)分量clip.w后得到的纵隔,而這個過程稱之為透視除法(perspective division),是在VS之后炮姨,硬件自動完成的捌刮,經(jīng)過透視除法后,就完成了坐標(biāo)從四維空間到三維空間的轉(zhuǎn)換舒岸。
在正交投影作用下绅作,因為clip.w通常是1,因此裁剪坐標(biāo)系的坐標(biāo)與NDC坐標(biāo)在數(shù)值上是相同的蛾派。
與前面的空間坐標(biāo)系不同俄认,NDC是有邊界的,以O(shè)penGL為例洪乍,其XYZ方向上的邊界為[-1, 1]眯杏,DirectX(包括Vulkan與Metal API)的NDC范圍有所不同,主要在Z軸方向上壳澳,其范圍為[0, 1]岂贩。
1.6 屏幕空間坐標(biāo)系
屏幕空間坐標(biāo)系是一個二維平面坐標(biāo)系,這個坐標(biāo)系的坐標(biāo)也是Fragment Shader巷波、Pixel Shader的輸入萎津。上一步我們得到NDC之后卸伞,坐標(biāo)范圍分布在[-1, 1](OpenGL為例),而之后則需要經(jīng)過Viewport Transform將NDC轉(zhuǎn)換到屏幕空間锉屈,得到與屏幕分辨率相一致的2D整數(shù)坐標(biāo)系(更準(zhǔn)確的說荤傲,坐標(biāo)范圍與Viewport分辨率一致)。
處于這個坐標(biāo)系中的坐標(biāo)部念,我們稱之為Framebuffer Coordinates或者Viewport Coordinates,對于DirectX氨菇、Vulkan以及Metal API而言儡炼,F(xiàn)ramebuffer Coordinates的原點(0, 0)在左上角(y down),而對于OpenGL API而言查蓉,其坐標(biāo)原點在左下角(y up)乌询。另外,貼圖坐標(biāo)系的指向也跟上述規(guī)則一樣豌研,即貼圖坐標(biāo)系與Framebuffer Coordinates具有相同的坐標(biāo)軸朝向妹田,這不難理解。
這里需要注意的是NDC的坐標(biāo)指向與這里的規(guī)則有所不同:對于Vulkan API而言鹃共,NDC的最小坐標(biāo)(-1, -1)在左上角(y down)鬼佣,而對于DirectX、Metal霜浴、OpenGL API而言晶衷,其最小坐標(biāo)點在左下角(y up)。
我們平常所說的BackFace Culling(CW/CCW)等阴孟,就是在這個階段完成的晌纫,之所以不放到NDC中,是因為除以w這個過程可能會導(dǎo)致三角形頂點繞行順序發(fā)生變化永丝;此外锹漱,對于Vulkan以及OpenGL的一些在viewport transform之前對Y進(jìn)行翻轉(zhuǎn)的擴展(比如VK_KHR_maintenance),可能會導(dǎo)致頂點繞行順序發(fā)生變化慕嚷,從而導(dǎo)致裁剪效果存在異常哥牍,這也是需要注意的。在完成這個Culling之后喝检,就會進(jìn)入光柵化邏輯砂心。
1.7 各坐標(biāo)系在管線上的位置與關(guān)系
模型渲染始于模型空間坐標(biāo)系,終于屏幕空間坐標(biāo)系蛇耀,而中間穿插著剩余的多套坐標(biāo)系之間的轉(zhuǎn)換辩诞,這些坐標(biāo)系之間的關(guān)系如下圖(參考文獻(xiàn)[1])所示:
1.8 貼圖坐標(biāo)系
當(dāng)我們需要對貼圖進(jìn)行采樣,或者進(jìn)行數(shù)據(jù)寫入時纺涤,就需要指定讀取以及寫入時的坐標(biāo)译暂,這個時候使用的這個坐標(biāo)叫做貼圖坐標(biāo)系抠忘。
貼圖坐標(biāo)系與Framebuffer Coordinates十分相似,也有著相同的坐標(biāo)原點外永,不同的是崎脉,貼圖坐標(biāo)系支持浮點數(shù),浮點數(shù)作用下可以實現(xiàn)對貼圖數(shù)據(jù)的雙線性采樣(或者volume texture的三線性采樣)伯顶。
對于貼圖坐標(biāo)系囚灼,我們還可以繼續(xù)劃分為貼圖上傳(數(shù)據(jù)存儲)時的坐標(biāo)系——這個會影響先傳輸頂部行數(shù)據(jù)還是先傳輸?shù)撞啃袛?shù)據(jù),以及貼圖采樣(讀燃礼谩)時的坐標(biāo)系——這個對應(yīng)的是shader采樣時以左上角為原點還是以左下角為原點灶体,當(dāng)這兩個坐標(biāo)系一致時,我們在shader中采樣得到的數(shù)據(jù)就是符合預(yù)期的掐暮,否則可能會導(dǎo)致錯誤蝎抽。
1.9 Window坐標(biāo)系
所有操作系統(tǒng)的窗口坐標(biāo)系,其原點都在左上角路克,因此對于OpenGL等以左下角為原點的API而言樟结,在最終提交Framebuffer時,就需要對其進(jìn)行上下翻轉(zhuǎn)(Flip Y)精算。
1.10 各坐標(biāo)系Y軸朝向[2]
API / Coordinates | NDC | Framebuffer | Texture | Window |
---|---|---|---|---|
DirectX | Up | Down | Down | Down |
OpenGL | Up | Up | Up | Down |
Vulkan | Down | Down | Down | Down |
Metal | Up | Down | Down | Down |