透視投影矩陣(所有都是右乘列向量)
投影矩陣簡單版(從某視頻里看到的):
f為投影焦距。
以下是unity的透視投影矩陣:
解釋一下各個變量,結合下圖理解:
Fov:是unity攝像機上的一個屬性,Field of View。表示攝像機的張開角度。
Far:unity攝像機上的一個屬性。表示近裁剪切面和攝像機的距離。
Near:unity攝像機上的一個屬性。表示遠裁剪切面和攝像機的距離。
Ascept:Ascept = nearClipPlaneWidth / nearClipPlaneHeight
而 nearClipPlaneHeight = 2 * Near * tan(Fov / 2) 這是指近裁剪平面的高度。
nearClipPlaneWidth 可通過camera.aspect來算(w/h)。其實就是直接去camera.aspect這個屬性。
以下是乘了一組向量以后的:
判斷一個頂點是否在裁剪空間內,就判斷x、y、z三個分量是否滿足以下不等式,一個不滿足就說明要被剔除。
-w <= x <= w
-w <= x <= w
-w <= x <= w
正交投影矩陣
解釋,同樣結合下圖:
Near和Far和上面的透視投影一樣,Size是攝像機上的一個屬性,所以farClipPlaneHeight = 2 * Size;
aspect還是通過camera.aspect獲取。
以下是和一組向量相乘后的結果:
判斷是否裁剪,和透視投影矩陣一樣。
屏幕空間
通過投影矩陣變換、裁剪操作,接下來就是投影到屏幕了。
經過透視投影變換后的裁剪控件,經過齊次除法后會變換到一個立方體內,就是用齊次坐標系的w分量去除以x、y、z分量(書上說的,我覺得應該是各個分量除以w,不然要是有一個分量是0的話不就炸了嘛。。。)。這樣可以使齊次坐標標准化,即w = 1。
然后通過公式算出屏幕的x、y坐標:
ScreenX = (x * pixelWidth) / (2 * w) + pixelWidth / 2
ScreenY = (x * pixelHeight) / (2 * w) + pixelHeight/ 2
z分量會被用於深度緩沖。
法線變換
首先,法線是垂直於切線的,變換后的切線可以使用原來頂點變換的變換矩陣得到。
但是,對於法線來說,用原來的頂點變換矩陣可能會使原來的法線不一定垂直於切線(比如說非統一縮放)。
假設已知切線Ta、法線Na他們相互垂直,因此,Ta · Na = 0;已知變換矩陣Mab,變換后的法線Tb = MabTa,求一個矩陣G變換法線Na,使變換后的法線任然與Tb垂直。
Tb·Nb = (MabTa) · (GNa) = 0
(MabTa) · (GNa) = (MabTa)T(GNa) = TaTMabTGNa = TaT(MabTG)Na = 0
因為Ta · Na = 0,所以如果MabTG = I,那么上面等式成立。所以G = (MabT)-1 = (Mab-1)T,G就是頂點變換矩陣的轉置的逆。
如果變換矩陣是正交矩陣,那么我們可以直接使用變換頂點的變換矩陣來得到變換后的法線。