畢業即失業,想學習點知識,看到了皮露露可不可的視頻和Unity | 流體模擬 - Navier Stokes - 為什么不開大的文章 - 知乎
看到大佬們做的效果見獵心喜,故而開始學習,在此記錄一下權做學習筆記。
(資料圖)
由于流體模擬方程對我來說研究之后除了增加了一點點數學常識并沒能對這個工程的理解有所幫助,所以這里大概是這怕文章中唯一一次提到這個公式了。
案例中流體的模擬是基于速度場的將整個圖片劃分網格通過速度場來對圖片的像素進行采樣,在Unity中創建一張2D貼圖,每一個像素都是一個關于顏色的四維向量,我們采取顏色向量的前兩個值作為速度向量來對每個像素的速度進行描述。這樣就可以通過片元著色器對速度場的變化進行模擬了。
按照常規思維在模擬的時候應該將當前像素的速度和時間相乘計算新的坐標并將當前點的速度寫入新坐標中,由于使用Unity的片元著色器對速度場進行模擬,片元著色器只能寫入當前像素的值,所以采用另一種方法同樣算出移動距離后從反方向的地方獲取像素的速度并將其寫入當前像素。
但是這樣做的話模擬精度似乎會有很嚴重的損失。在實驗中若不對速度場進行插值處理,速度場在邊界處似乎無法流動。
在C#腳本中聲明了兩組RenderTexture,并在start中進行初始化,貼圖vel用于儲存速度場,col則是對圖像進行流動模擬所用。div則儲存散度場。
由于模擬是基于GPU的體現在Unity則是使用片元著色器(像素著色器)。所以需要通過shader進行實現shader是在材質上進行工作所以需要為其創建“simMat”模擬材質來進行模擬。C#腳本若無特殊說明將運行在updata中,代碼將會每幀執行一次。
由于在Unity的學習中通常使用UPR管線所以在學習時也嘗試在UPR的工程中進行還原,個人代碼將會以注釋的形式進行標注
在C#腳本中將用于儲存速度場的貼圖vel0和平流速度系數傳入shader中進行計算則會運行shader中的相關pass并將運算結果存如vel1中,在最后交換vel1和vel0這樣在下一幀時將基于上一幀的結果進行運算
在shader中頂點著色器將uv為當前像素LRTB分別為上下左右相鄰的像素
dt是unity_的宏定義,tex2d()用于對貼圖進行采樣,通過對當前uv進行采樣獲得速度并將其乘以時間獲得距離,再通過距離即可找到應移動到此點的速度值。將其寫入當前像素
通過使用pass1進行速度擴散處理
此處為粘性擴散,意為將速度擴散至周圍的像素,因為前文提到的缺陷無此方法則速度場無法流動,此處采用了插值法對自己和周圍的像素采樣后取平均值,但是我未能理解為何為當前像素賦予與幀時間相關的權重,以至于在處理中當前像素將會是一個很小的權重(似乎與內能損耗相關?)
完成這部分速度場就可以進行流動,以下為我復刻的代碼。
標簽: