图形学基础笔记III:图形管线中的多边形裁剪算法、Sutherland-Hodgman、Guard Band Clipping
這個主要講的是viewport 里的。
從 frustum (根據(jù) fov 視場角 和 aspect ratio 縱橫比決定 lrbt,front、near 是由攝像機距離和世界大小決定的)到 viewport 之后,能夠看到的就只有投影后的 cuboid 在 viewport 里面的東西了。
問題是這個 clipping 是在 CPU 還是 GPU?實際有多個階段,從 culling,CPU clipping 到 GPU clipping 和GPU rasterization。
本文嘗試講解這個問題,不過實際顯卡和驅(qū)動變幻莫測,還需要更多參考資料。
但是有些麻煩的是因為只能處理三角形,如果裁剪了之后變成 polygon 了就要重新劃分三角形了。好在三角形切一刀只會變成三角形或者四邊形(quadrilateral)。
所以可以用下面的偽代碼對整個 cuboid 內(nèi)的 3D 三角形進行處理。
tiger book 也分析了裁剪實際放在 mvp 之前也可以,除以齊次坐標(biāo)后也可以,在mvp之后也可以,但是除法之后(世界坐標(biāo))對于眼睛附近的地方是不連續(xù)的,所以這方面的運動就很難,所以一般在 MVP 后的除法之前做,而超平面也不難表示。對于 mvp 之后的平面方程則是最簡單了(因為就是正立方體)。
首先是對直線的裁剪的硬件算法,即 cohen-sutherland 算法。對于多邊形的裁剪是基于直線的裁剪的 sutherland-hodgman。一般講解的是 2D 的情況,實際有 3D 的算法。
這部分算法可能是在 CPU 做的,也可能是在 GPU(看下面的 Guard band clipping 里面就明白了,對于不同的區(qū)域而言,有一些必須 CPU 就剪好,有一些可以讓 GPU 剪,最后都是看你驅(qū)動怎么實現(xiàn)的),而且最新的硬件算法你也不知道是什么,會經(jīng)過奇特的優(yōu)化,其中還涉及到插值的問題。
對于一半在 viewport 里面的三角形,其實最簡單的做法是 AABB 遍歷的時候只訪問 viewport 里面的像素就行了,感覺也沒什么,關(guān)鍵是你不能剪掉的啊,剪掉了那 vertex 的信息就沒了(OpenGL 規(guī)定是在 VS 后面進行 clipping),還要重建新的三角形和分割,那還 render 個寂寞。
對于 hardware clipping 來說,實際你還是要進行這部分的數(shù)據(jù)傳輸。如果不想數(shù)據(jù)傳輸就涉及在 CPU 端做 culling。optimization - At what phase in rendering does clipping occur? - Stack Overflow
當(dāng)然,上面說的最簡單的做法是 AABB 遍歷的時候只訪問 viewport 里面的像素就行。但是這樣實際是要求顯卡的實際能用的緩沖區(qū)是要大于 viewport 的。如果你的圖元連緩沖區(qū)都放不下,是不是就一定要做類似 sutherland-hodgman 然后按老虎書說的要看情況拆成兩個新的三角形,還要處理邊界值(根據(jù)被剪掉的頂點插值好屬性從而不會丟失)。
Nvidia 和 D3D 有一個叫 guard band clipping 的 culling + clipping 的層次算法,從 CPU 一路到 GPU 的,所以可能 GPU 就沒有實現(xiàn):
Guard Band Clipping in Direct3D (nvidia.cn)
Cohen-Sutherland
- 平面編碼:使用 tbrl 4位編碼,如果是在 viewport 的 tbrl 就為 1. 每個位置最多兩個 1.
- 在交點處把線段分為兩段。其中一段完全在窗口外,可棄之。然后對另一段重復(fù)上述處理。
- 如上圖,實際只需要對直線的端點(其實一直說直線說的是線段)求這個編碼,根據(jù)不同的情況,然后遞歸/迭代進行下去:
Sutherland-Hodgman 多邊形裁剪算法
- 關(guān)鍵在于怎么確定凸的凹的那些要不要封閉。
- 按某個順序逐邊裁剪:
- 多邊形邊的分類:把所有邊都按逆時針確定起點 S 和終點 P。每次裁剪的時候,viewport 邊界裁剪線要做延長,再劃分 in out 分區(qū)
- case1 是整條邊都在viewport 里面的(通過 Cohen-Sutherland 得知的),只保留終點。
- case2 是內(nèi)往外出,保留交點。(起點會由另一個閉合邊輸出),交點的求法可以用數(shù)值解。
- case3 邊在外面,不保留頂點。
- case4 外面進來,保留交點和終點。
- 一言:對于相交的,在 viewport 內(nèi)的終點,以及交點都要保留
- 后處理:由于這個算法輸出的是點,這里演示了一個凹多邊形,所以你怎么把連連起來呢?wiki 說 Note that if the subject polygon was concave at vertices outside the clipping polygon, the new polygon may have coincident (i.e., overlapping) edges – this is acceptable for rendering, but not for other applications such as computing shadows.
- 所以說必須要做一個后處理,實際你處理不了,只能加一些專家系統(tǒng)的解決一部分問題。不過既然三角形是凸的,所以實際可以不管他(然而我感覺用這個只處理三角形是不是有點浪費?)別的算法也是針對 polygon 的。可能說三角形還能優(yōu)化。不過注意的是,對于三角形切了之后變成四邊形的情況還要割呢。
- 交點插值:由于與切割線的交點已經(jīng)不是原來三角形的頂點了,所以 clipping 的過程要求一下新的頂點的重心坐標(biāo),把插值后的屬性放到新的頂點上取。
- 切分三角形:這個過程很簡單的,只要切完了之后看一下有多少個頂點,如果是 4 個就切一刀,把對應(yīng) vertex 的 attributes 都要復(fù)制一份。
- 原理:其實上邊這些操作指南一樣的東西,是可以用三角形來推導(dǎo)出來的。規(guī)定順時針方向和逆時針方向都行。就是依次遍歷三角形的三條邊,然后能夠依次把要保留(裁剪)的頂點不遺漏不多選地列舉出來。其實那幾條規(guī)則對三角形來說實在是想當(dāng)然的,可以窮舉所有情況,。
?
Homogeneous Clipping
- 算法論文:p245-blinn.pdf (fabiensanglard.net)
- 上面這個 Sutherland-Hodgman 算法一看好像只能用在 2D 上,有一定的局限。
- 但是我們可以考慮把裁剪線擴展為裁剪面,而交點還是交點,只不過變成了 3D 的直線(線段)與平面的交點。
- 前面提到虎書說到,我們可以在 MVP 之后,做除法之前進行 clipping。這就是齊次坐標(biāo)裁剪。復(fù)習(xí)一下為什么要在除法之前進行 clipping 呢,這是因為除法之后(世界坐標(biāo))對于眼睛附近的地方是不連續(xù)的(復(fù)習(xí) MVP 矩陣的推導(dǎo)),所以一般在除法之前做。(記住除法的那個 w 其實在運算過程為了化簡其他,用的就是 z 就行了,也就是因為這個 z 的除法引入了反比例函數(shù))。
- P 矩陣的問題就是這里,回想 games101 講 transformation II 的矩陣的推導(dǎo),由于 P 矩陣主要是我們基于 x 和 y 來推導(dǎo)的,z 的這個是湊出來的。所以這下問題就導(dǎo)致最后會出錯
- 但是實際還是大部分可以是正比關(guān)系的,只要 n + f 夠給力,但是反比例函數(shù)的特性,必然有一部分會被弄反。
- 實際瘋狂 google 找到齊次裁剪的關(guān)鍵字之后,也發(fā)現(xiàn)了有大佬的漂亮公式文章,這里也附上作為參考,我暫時就不研究具體公式(不過其實和上面 Sutherland-Hodgman 算法的差不多)。計算機圖形學(xué)補充2:齊次空間裁剪(Homogeneous Space Clipping) - 知乎 (zhihu.com)。需要注意齊次坐標(biāo)裁剪和 Sutherland-Hodgman 的關(guān)系就行。
?
實際顯卡驅(qū)動中的 culling & clipping
- Nvidia 的算法說明:Guard Band Clipping in Direct3D (nvidia.cn)
- 由于顯卡的幀緩沖是有限的,為了能夠支持更大的世界,實際顯卡的幀緩沖是支持比 viewport 的幀緩沖大小大得多的的,這個叫做guard band。但是他仍然是有限的,顯卡能夠處理的三角形也是必須在有限的空間里的(但是三角形的個數(shù)可以輕松上億甚至十幾億),一半 60 幀的引擎同屏渲染幾億三角形應(yīng)該不在話下。
- 所以實際 CPU 傳給 GPU 進行光柵化的三角形空間位置也不能超出視口太多然后還要渲染的,這樣的結(jié)果是顯卡自己處理不了這種三角形,因為他無法訪問這么大范圍的數(shù)據(jù)。
- 所以是兩階段裁剪算法:CPU 必須保證所有傳送的三角形都在 Guard band 里面。GPU 自己再裁一遍。
- 上圖,A 可以硬件丟棄,B 可以硬件裁剪。D 傳送的時候就被丟掉了(驅(qū)動做),或者 CPU 可以丟掉。C 就是一個很麻煩的三角形,關(guān)鍵是他還和 viewport 相交了。所以必須要進行軟件裁剪(CPU 進行)。
實際對于3D 來說,一些背面三角形沒有必要渲染,直接丟掉,這個叫做背向面剔除
?
總結(jié)
以上是生活随笔為你收集整理的图形学基础笔记III:图形管线中的多边形裁剪算法、Sutherland-Hodgman、Guard Band Clipping的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学计算机科学导论到底有什么用,计算机科学
- 下一篇: 云脑启智 开源赋能|2021新一代人工智