OpenGL中frustum投影矩陣的推導
OpenGL中,有一個函式叫frustum,字面的意思是截錐體,也就是一個去掉頭部的錐體,如下圖所示,
看了一下《計算機圖形學》(英文名Computer Graphics with OpenGL)的透視投影推導過程,比較全面,各種情況都有描述。不過最近又參考了網上的一些資料,發現這裡【1】的推導過程比較單純直接。我們看一下,
注意到上面這個圖,觀察者的位置相對於(0,0,0)這個點是在右邊的,也就目光是沿Z軸方向(所以距離 眼睛越近,顯得越大嘛),OpenGL的camera也就是(0,0,0)點,沿-Z方向。
把xe對映到xp,ye對映到yp是這樣的,
式(1)
通過Mprojection矩陣,把eye座標投影到NDC空間(Normalized
注意下上面的ndc和clip座標系之間,只差了一個係數 wclip,他們都是3維齊次座標【2】。下面這個方程中,c就是clip,變換矩陣的第4行設定為(0, 0, -1, 0),為什麼呢?因為這一行實際上只處理係數wc,看前面我們知道xp與yp分別和(-Ze)成反比,所以這裡我們也期望,wc和(-ze)成反比,且最後能歸一化wc/(-ze)=1。
接下來的一步,就是完成xp,yp到xn,yn的歸一化對映:[l, r] ⇒ [-1, 1] and [b, t] ⇒ [-1, 1],首先來看對映[l, r] ⇒ [-1, 1],如下圖
這是一個非常簡單的線性對映,寫成方程式就是,
其中就是xp=0時在xn軸上的截距,根據對映,當xp=r時,xn=1,代入到該式中,就可以得到,
然後變換一下格式,
現在把代回最上面那個式子,就得到了,
式(2)
同樣的道理,可以得到
式(3)
把式(2),式(3)代回到式(1),就得到這樣一個結果,
這兩個結果,結合我們前面得到的wc=-ze,整個矩陣就可以等價地寫成下面的形式,
現在只有矩陣的第3行是未知的,我們這樣處理,
因為在eye的空間,we=1(w是一個和透視距離有關的量,0表示無窮遠點,參考【2】),所以,
,和上面的道理類似,對映 (ze, zn)滿足範圍為近點=(-n, -1),遠點= (-f, 1),
求解該線性方程組,得到,
這樣,得到
式(4)
最後得到的矩陣就可以寫成
這個矩陣,也正是我們frustum函式變換所採用的矩陣。
這裡也順便提一下Z-finghting。根據式(4),Zn和Ze的關係為
因此,當[-n, -f]的距離比較大的時候,因為有理數取值都有誤差,在遠點就容易形成z-finghting,也就是當兩個實體在遠點有交接時,因為誤差產生的距離抖動,無法準確得到交接線從而產生類似下圖的結果,
本文結束。
參考