【UE4】 第14講 Triangle的光柵化
(版權宣告,禁止轉載)
為了避免困惑,讓我們簡化定義“光柵化”:判斷一個畫素是否在三角形的內部
在這篇文章,不會討論渲染管線的其它部分,比如深度,模版,混合的實現細節
對於當前的目的,所有的光柵化只是針對三角形,D3D的視口座標系
每個三角形有三條邊,每一條邊上面的點定義為一個方程 Bx+Cy = A,通過方程的符號判斷其它點相對邊的位置是在三角形內側還是三角形外側
三角形內部的畫素符號為負,外部的畫素符號為正
Larrabee採用了一種完全不同的方式,更易於進行向量化。這種方式一次計算16個塊來判斷哪一個和三角形有重合區域,如果有重合,再進入那個塊的內部進行下一級的16個子塊的判斷,直到找到三角形的所有內部畫素。下面我們舉例說明這個方式的執行過程,在任何時候【最大光柵化目標】是【渲染目標】的一部分,稱為一個【Tile】,比如我們定義一個Tile是64x64畫素的
Step1: 一次判斷16個塊(每一個塊是16x16畫素的)和三角形的重合關係
發現只有一個塊和三角形重合,就是標註了黃色邊框的那個塊
Step2:繼續進入那個黃色邊框的塊,細分為16個子塊(每個塊是4x4畫素的),
並且判斷和三角形有重合的子塊,如果有重合標註為黃色邊框
發現有五個子塊有重合
Step3:繼續進入4x4畫素子塊的下一級進行判斷,每個子塊是一個畫素
如果在三角形內,做個綠色的標記
五個子塊全部檢測完畢,得到三角形內的全部畫素
上面的例子是三角形在一個Tile內部的情況,對於三角形重合多個Tile的情況,
光柵化一般分為兩步:
第一步 判斷和三角形重合的Tile,並將三角形存入Tile的容器內
第二步 在每個得到的Tile內部進行光柵化
淺藍色的區域是一個256x256的【渲染目標】,被分成了4個128x128的【Tile】
一個Tile的【無價值排除角】指的是代入邊方程後的值最小的那個角,
用來判斷不包含三角形的Tile
(【無價值排除角】就是【Trivial reject corner】,下圖白色圓點)
值得注意的是【無價值排除角】的位置根據邊的斜率會有不同
相對於【無價值排除角】,還有
【無價值接受角】- 指的是代入邊方程後的值最大的那個角,
用來判斷三角形完全覆蓋的Tile
如下圖 Tile3 就是無價值完全接受的Tile
【Tile內部光柵化】
對於前面那個64x64畫素的Tile,分成了16個16x16畫素的塊,這16個塊的計算是同時進行的
先計算的是【無價值排除角】,得到的值的符號直接可以判斷哪個塊是完全在三角形外部的
箭頭代表16步對於【無價值排除角】的計算,每一步就是做一次相加,
可以用一個向量指令做16次相加,再用一個向量指令做一次比較
每個塊要做個座標系變換,右下角的座標是(0,0),這樣每個塊在計算時,
所有點的座標也是相同的, 每個塊的Bx+Cy得到邊上的初始值是不同的,
每個白色點座標代入Bx+Cy之後,判斷跟初始值的大小關係確定在邊的哪一側
用同樣的方式判斷【無價值接受角】
對於一個給定的邊,為了簡化問題,假定A=1 (A=Bx+Cy)
把【無價值接受角】的座標代入邊方程加上A(A=Bx+Cy)得到的值,存入一個向量
把得到的向量和0作比較確定符號得到位掩碼(Bit mask),得到的值用來判斷【無價值接受角】
按照同樣的方式,計算另外兩個邊,得到對應的另外兩個位掩碼(Bit mask)向量
然後把三個向量依次進行按位與,根據最終符號得到【無價值接受角】對應的塊
把【無價值接受角】對應的塊,存入光柵化輸出佇列
16x16畫素塊的判斷完成之後,對於那些部分割槽域在三角形內部的塊,
繼續細分為16個4x4畫素塊進行計算和判斷,
不同於16x16畫素塊的是計算【無價值接受角】的座標是畫素的中心位置
Larrabee光柵化方式的一個很好的特性是
MSAA只是對於每一個部分在三角形內的畫素需要一個額外的向量進行比較
上面講解了Larrabee光柵化演算法的主要內容以及每一步的實現細節,
下面給出完整的流程
<1>通過每個Tile和三角形的包圍盒比較出是否有重合部分
<2>細分為4x4個塊,進行【無價值排除角】和【無價值接受角】判斷
<3>對於部分在三角形內塊,繼續細分為4x4個塊,
進行【無價值】判斷,最終的到在三角形內的畫素