Unity 手把手教你實現(xiàn)有向距離場(SDF)圖像生成工具(3)【猴子都能學(xué)會】
????通過上面一篇文章對于unity的并行操作作了一定的講解,而本篇主要是去實現(xiàn)Dead Reckoning算法,說簡單點就是用確定的去推算不確定的當然這樣的結(jié)果可能不是正確的,所以我們這里需要正向與反向去遍歷貼圖消除錯誤。

????好了再次打開我們上次寫好的腳本,并擴充一下我們儲存邊界條件的結(jié)構(gòu)體
其中inTarget代表白色像素,X代表離該像素最近的邊界像素的X的坐標,Y同理,distance代表了和最近像素之間的距離值,我們用下面一張圖進行詳細的講解,每個方塊代表一個像素,而白色部分代表我們的目標區(qū)域,也就是inTarget,之前我們判斷一個像素是否在邊界就是看這個像素的上下左右有沒有黑色像素就行。

?現(xiàn)在我們將邊界像素的X給該像素的位置的X值,Y給該像素的Y值,對于unity的圖像坐標,左下角的像素為坐標原點,向右為X正方向,向上為Y正方向。

????在上一篇文章我們其實就已經(jīng)找到了邊界像素,也就是下圖的紅色部分

那么現(xiàn)在我們需要把所有紅色區(qū)域的像素的distance設(shè)置為0,他們的坐標為自身坐標,intarget為1,而所有白色區(qū)域的坐標設(shè)置為無限大(給個很大的值就可以了),距離也同樣是無限大,intarget為1,對于黑色區(qū)域也就是不需要我們考慮的區(qū)域他們的intarget給0,X和Y給無限大,因為本次我們只考慮目標區(qū)域以內(nèi)的像素,距離也給無限大處理的邊界屬性應(yīng)該和下圖相同

????好了,再讓我們回到CoputeShader,將ComputeShader的結(jié)構(gòu)體擴充
????值得注意在ComputeShader中的結(jié)構(gòu)體必須和C#中對應(yīng),變量所在位置也要完全一致。
????現(xiàn)在我們按照剛才講的將數(shù)據(jù)填充進去。
????到這里我們僅僅完成了Dead Reckoning算法所需要的準備工作,該算法由于需要用過去的值去推算現(xiàn)在的值,所以有個缺陷是不能做并行,只能在CPU中串行遍歷兩次。
????我們再聲明一個函數(shù)來處理來處理這個結(jié)構(gòu)體的數(shù)組 , 這里我們需要引用傳值,將結(jié)構(gòu)體數(shù)組的地址傳過來。
????那么現(xiàn)在我們?nèi)绾斡嬎隳?,首先是遍歷元素的順序,我們左下角是向右是X軸正方向,向上是Y軸正方向,所以我們正向遍歷應(yīng)該是從左到右從下到上來遍歷像素
????現(xiàn)在我們將更新它的最近邊界點坐標和與最近邊界點的距離,在正向遍歷時如下圖,我們需要檢測一個像素的相鄰像素,也就是說正向我們需要檢測左 , 左下 , 下 , 右下的像素,反向需要檢測 右 , 右上 , 上 , 左上的像素。

????在我們正向遍歷的時候,對于一個正在檢測的像素我們?nèi)z測它相鄰像素儲存的距離值,如果 該像素的距離值 > 相鄰像素的距離 + (該像素與相鄰像素的距離) , 圖中黃色數(shù)字代表“該像素與相鄰像素的距離”,那么我們就把相鄰像素的最近邊界點賦值給該像素,并計算出該像素到最近邊界點的距離

????該算法具體實現(xiàn)如下
由于我們需要把距離儲存在圖像中所以距離值必須是0-1,這里我們用一個數(shù)值來儲存最大距離值
????先寫一個計算距離的函數(shù)
這個命名當時沒注意到,
然后我們在這里調(diào)用這個方法,并將數(shù)值傳給GPU計算
????讓我們再來到ComputeShader這里就非常簡單了,改一下我們上次寫好的Kernel就可以了
然后我們就能用工具生成一張這樣的距離場圖像

這里簡單寫個shader對距離做個線性插值就可以實現(xiàn)圖形變換了