Unity 手把手教你實現(xiàn)有向距離場(SDF)圖像生成工具(2)【猴子都能學(xué)會】
Unity 手把手教你實現(xiàn)有向距離場(SDF)圖像生成工具(1)【猴子都能學(xué)會】 - 嗶哩嗶哩 (bilibili.com)
?????在上一篇文章中我們完成了工具窗口的繪制, 現(xiàn)在就開始實現(xiàn)基本功能。
? ??????首先我們需要判斷貼圖是否為空
????然后聲明一個私有變量用來儲存我們保存圖像的路徑
????接下來實現(xiàn)一個窗口來保存貼圖

????這里直接調(diào)用unity的API就行了,再判斷一下路徑是否為空
現(xiàn)在我們點擊按鈕就會出現(xiàn)一個保存窗口了,但點了保存后依然什么也沒有發(fā)生。
????現(xiàn)在我們再聲明一個私有的ComputeShader,并把我們剛剛創(chuàng)建的ComputeShader給上去
????這里通過路徑去加載我們的ComputeShader,所以注意這里路徑是你ComputeShader所在的位置不要寫錯了
????現(xiàn)在我們再聲明兩個int類型的變量用來保存圖像的寬度和高度。
然后我們把圖像的寬度和高度賦值給sourcWidth和sourceHeight
?????好了接下來我們再來寫一個函數(shù),該函數(shù)將讀取貼圖的邊界條件,所以我們需要向該函數(shù)傳入一張Texture2D。
????首先我們需要判斷一下傳入的圖片是否為可讀,使用該工具必須把傳入的圖像設(shè)置為可讀才行,并且不能壓縮,壓縮會嚴(yán)重影響生成的SDF精度。
????還記得我們最開始創(chuàng)建了一個ComputeShader嗎?我們至此還沒有對它進(jìn)行任何修改,現(xiàn)在讓我們來打開它,你會看到如下代碼,這就是unity為我們生成的ComputeShader的模板
????這里unity給我們寫了注釋,每個Kernel會和下面的功能相對應(yīng),我們可以在一個ComputeShader中寫多個Kernel,他這里有個RWTexture2D<float4> Result; 這里的RW代表了RandomWrite(無序?qū)懭耄┑囊馑?,我們接下來會利用ComputeShader,并行讀取圖像數(shù)據(jù),所以數(shù)據(jù)的填充并沒有先后順序,如果我們只想讀取圖像,那么可以直接用Texture2D<float4>就可以了,[numthreads(8,8,1)]這個是我們多線程中非常重要的存在,它劃分了我們的線程,[numthreads(x,y,z)]而其中x y z,并不是我們想寫多少寫多少想給多大給多大,我們需要滿足x * y * z <= 1024; 而我們在ComputeShader中定義的線程和我們在C#中定義的線程組的乘積需要滿足我們的線程總數(shù)。
????我在上面對于ComputeShader做了一下簡單介紹,當(dāng)然還要明白,我們輸入輸出的不僅僅是貼圖還能是結(jié)構(gòu)體,所以接下來我們會利用ComputeShader將圖像的邊界條件存儲在一個結(jié)構(gòu)體里面輸出出來。
????接下來讓我們看看如何輸入一張圖像,輸出一個結(jié)構(gòu)體。
????我們現(xiàn)在在ComputeShader中聲明一個結(jié)構(gòu)體,里面只有一個int 類型叫edge。
????再聲明一個_Width,該變量由C#傳入代表圖像寬度,再需要一個傳出的結(jié)構(gòu)體RWStructuredBuffer<EdgePixel> Result;
????讓我們回到C#,我們聲明一個結(jié)構(gòu)體與ComputeShader的結(jié)構(gòu)體對應(yīng),兩者除了名字必須完全一致。
????接下來我們創(chuàng)建一個ComputeBuffer去實現(xiàn)GPU與CPU的數(shù)據(jù)交換
????我們基于上面對edgeBuffer賦值,并將數(shù)據(jù)傳入ComputeShader參與計算
????現(xiàn)在再回到ComputeShader,這里我們需要把二值圖的邊界找出來
????現(xiàn)在我們返回C#中,我們需要再來一次并行計算將結(jié)構(gòu)體的數(shù)組轉(zhuǎn)換為一張圖像
首先我們先聲明一張RenderTexture來儲存圖像
????現(xiàn)在我們回到ComputeShader寫另一個kernel來生成圖像,這里非常簡單,唯一注意的是現(xiàn)在我們的圖像變成了輸出的對象,需要用RWTexture2D<float4>
????現(xiàn)在我們再到C#中來執(zhí)行這個Kernel生成圖像
????現(xiàn)在圖像被保存在rt0中了,現(xiàn)在我們需要輸出一張png格式圖片,所以我們先聲明一個Texture2D作為目標(biāo)圖像
現(xiàn)在我們ComputeSDF()中去調(diào)用我們之前寫的兩個方法
? ? 以上我們再來執(zhí)行工具看看是不是能得到如下圖像,如果可以說明之前的代碼就成功了,距離的計算會在下一篇文章中講解
