日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

图形学基础笔记III:图形管线中的多边形裁剪算法、Sutherland-Hodgman、Guard Band Clipping

發(fā)布時間:2023/12/8 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图形学基础笔记III:图形管线中的多边形裁剪算法、Sutherland-Hodgman、Guard Band Clipping 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

這個主要講的是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ù)不同的情況,然后遞歸/迭代進行下去:
// Cohen–Sutherland clipping algorithm clips a line from// P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with// diagonal from (xmin, ymin) to (xmax, ymax).void CohenSutherlandLineClipAndDraw(double x0,double y0,double x1,double y1) {// compute outcodes for P0, P1, and whatever point lies outside the clip// rectangleOutCode outcode0 = ComputeOutCode(x0, y0);OutCode outcode1 = ComputeOutCode(x1, y1);bool accept = false;while (true) {if (!(outcode0 | outcode1)) {// bitwise OR is 0: both points inside window; trivially accept and exit// loopaccept = true, break;} else if (outcode0 & outcode1) {// bitwise AND is not 0: both points share an outside zone (LEFT, RIGHT,// TOP, or BOTTOM), so both must be outside window; exit loop (accept is// false)break;} else {// failed both tests, so calculate the line segment to clip// from an outside point to an intersection with clip edgedouble x, y;// At least one endpoint is outside the clip rectangle; pick it.OutCode outcodeOut = outcode1 > outcode0 ? outcode1 : outcode0;// Now find the intersection point;// use formulas:// slope = (y1 - y0) / (x1 - x0)// x = x0 + (1 / slope) * (ym - y0), where ym is ymin or ymax// y = y0 + slope * (xm - x0), where xm is xmin or xmax// No need to worry about divide-by-zero because, in each case, the// outcode bit being tested guarantees the denominator is non-zeroif (outcodeOut & TOP) // point is above the clip windowx = x0 + (x1 - x0) * (ymax - y0) / (y1 - y0), y = ymax;else if (outcodeOut & BOTTOM) // point is below the clip windowx = x0 + (x1 - x0) * (ymin - y0) / (y1 - y0), y = ymin;else if (outcodeOut & RIGHT) // point is to the right of clip windowy = y0 + (y1 - y0) * (xmax - x0) / (x1 - x0), x = xmax;else if (outcodeOut & LEFT) // point is to the left of clip windowy = y0 + (y1 - y0) * (xmin - x0) / (x1 - x0), x = xmin;// Now we move outside point to intersection point to clip// and get ready for next pass.if (outcodeOut == outcode0)x0 = x, y0 = y, outcode0 = ComputeOutCode(x0, y0);elsex1 = x, y1 = y, outcode1 = ComputeOutCode(x1, y1);}} }

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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。