為什麼透視投影矩陣中要用z的倒數進行插值。

2021-09-12 14:38:10 字數 1965 閱讀 1000

先說一些閒話,為什麼考慮到了這個問題。今天本來想看看這個shader怎麼做。

如上圖,就是圓球和立方體相交的地方會發亮這種shader該怎麼實現。然後看到了這個shader中有這麼乙個函式lineareyedepth,由於本人剛學shader不久,對圖形學也一直處於一知半解的狀態,所以不知道這個函式是什麼意思。先貼上搜到的結果:

lineareyedepth 負責把深度紋理的取樣結果轉換到視角空間下的深度值,也 就是我們上面得到的z(visw)。而 linear01depth 則會返回乙個範圍在[0, 1]的線性深度值,也就是我們上面得到的z(01),這兩個函式內部使用了內建的_zbufferparams變數來得到遠近裁剪平面的距離。

這個結果先不多講了,(感覺學習總是跑偏,在解決乙個問題時,會引出一大堆問題),在搜尋透視投影矩陣的推導過程中看見了這麼一句話:因為在光柵化之前,我們需要對z座標的倒數進行插值。不明白為什麼要這麼做,也推不出來透視投影矩陣。遂翻看unity shader 入門精要。一句話:推導部分詳見擴充套件閱讀。(令人頭大)於是乎去看mathematics for 3d game programming and computer grahpics,感覺這真是本好書啊。越看越感覺什麼opengl 什麼unity shader 統統都是浮雲,都是工具,這才是真理啊。

好了,進入正題,下面就說說為什麼要這麼做:

原諒我才學疏淺,寫文章從來不是我的強項,but,今天我就是想寫。可是又不知到怎麼寫,就這麼把看到的這節翻譯一下吧。

就不逐字翻譯了,直接看圖,大黑點代表相機,水平的線代表投影平面,斜著的線代表真實的物體,那水平線上的小黑點代表的是真實物體投影到平面上的點。你們發現什麼了沒?對了,就是當在投影平面上線性插值時,反推到真實物體上,深度值不是線性的(聽懂了沒?沒聽懂看下圖,下圖還看不懂就放棄看這篇吧,主要賴我表述能力太差)

看見了沒,d1,d2,d3,d4越來越小了,所以顯然不能去z值直接進行插值,so?那該怎麼取值嘞?

繼續看圖,假設就這麼建立了乙個座標系,(x1,z1)(x2,z2)是真實物體的兩端,兩端在投影面上的投影分別為(p1,-e) (p2,-e) 你們又發現什麼了沒?

紅色三角形和藍色三角形相似啊,而且我在直線上任意取乙個點都是相似的啊,好強啊。

接下來就充分發揮初中數學能力了。下面的推導就不用再解釋了吧,就根據相似三角形來就可以了

當然,我們還要進行線性插值,這裡還沒有插值的公式,莫怕,就差最後一點了。

這個也沒什麼好說的了,就是把(x1,z1) (x2,z2) (p1,-e) (p2,-e)代入就可以了。

perfect!告辭!

PHP中變數為什麼要用

c vb php中 可以利用值 數和字串 的位置 1 函式引數 2 運算子運算元 包括vb中的賦值語句 3 陣列下標 包括phpkey標 能產生值 數和字串 的位置 1 簡單變數 2 陣列元素 3 結構成員 4 函式 5 常量 一般字面常量 c和php中define常量 vb中const常變數 6 ...

Python中為什麼要用self?

參考文章 self的含義與基本用法 python中為什麼要使用self 注意到文章中的一句話,避免非限定呼叫造成的全域性變數。舉個例子來談談我對這句話的理解 class father def init self,name self.name name def selfdemo self print ...

c Linq 中為什麼非要用var

因為linq的query中的是不定型別,返回的是不定型別的指標,即不定型別的引用。在這種情況下,只能用var型別的變數儲存這個不定型別的指標。var 宣告的是 乙個變數物件,即乙個變數物件的引用 指標 我們一般以物件的引用 指標 來代表這個物件。下面這段 充分說明了var 物件是不定型別的引用。因為...