Unity 大規模魚群的渲染

2021-09-20 18:45:24 字數 3921 閱讀 7616

看了gdc關於abzu的演講,感覺很受啟發,決定在unity中實現其中講到的魚群的渲染。

首先是乙個基礎的shader,這裡我寫了乙個支援主貼圖和法線貼圖的只有漫反射的shader 大概就是這樣:

shader "fishtest/fishshader"

[noscaleoffset]_normalmap("normalmap",2d)="bump"{} }

subshader

pass

;

sampler2d _maintex;

float4 _maintex_st;

sampler2d _normalmap;

v2f o;

o.pos=unityobjecttoclippos(v.vertex);

o.uv=transform_tex(v.texcoord,_maintex);

tangent_space_rotation;

o.lightdir=mul(rotation,objspacelightdir(v.vertex));

return o;

}fixed4 frag(v2f i):sv_target

endcg

} }}

因為我們做的是頂點動畫,所以實際上只需要偏移頂點,無需多餘的修改,所以我們建立乙個單獨的方法來完成頂點動畫。

float4 vertexani(float3 vertex)
然後在頂點函式中將頂點動畫應用至頂點

v.vertex=vertexani(v.vertex);
現在我們的魚長這樣

因為我們的計算堵在模型的頂點空間中,所以注意一下魚的頂點空間座標,如果你的模型的頂點空間不一致,要做相應的更改,這裡我們的x軸為魚身長度。

接下來就是在vertexani實現頂點動畫了,演講中魚游動的動畫有四個部分組成

這一步很簡單,就是z軸的左右偏移。我們sin和時間變數實現,

首先設定相關的屬性,

properties

將上面這些值新增至pass中後修改vertexani

float4 vertexani(float3 vertex)
噹噹!現在我們的魚學會了左右橫跳。 

這個部分也簡單,主要就是需要生成旋轉矩陣,我們先寫乙個生成旋轉矩陣的方法,把它放在cginclude塊裡

cginclude

float3x3 angleaxis3x3(float angle, float3 axis)

endcg

新增對應的著色器屬性。

properties

然後再次修改vertexani,要記得先旋轉再位移,這樣才能確保旋轉是繞魚的中心旋轉。

float4 vertexani(float3 vertex)
ok,現在我們的魚學會了搖頭

魚類作為柔韌性槓槓的生物,我們的魚當然不可以這麼僵硬。下面兩步就是讓魚變得更加柔軟

著色器屬性,這裡的相位就是正弦函式中的那個相位,因為我想不到好的詞描述這個值,值越大,它的波動越頻繁

properties

float4 vertexani(float3 vertex)
效果如下,看起來有點沙雕。

不知道怎麼解釋這種移動,直接看後面的圖吧

綜合前四部分的動畫你會得到這樣乙個效果

說不出的詭異感,我們的魚頭應該要比魚身硬,所以我們要用蒙版撤銷掉魚頭的旋轉動畫,我們依距x值來獲取蒙版值,為了方便設定,我們新增乙個選項來顯示蒙版值。所以新增下列的著色器屬性

properties

獲取蒙版值的方法如下,過渡值可暗實際情況調整,因為我這個模型有點大,所以值設為50。

float getmask(float vertexx)
接下來就是按照蒙版值在旋轉和不旋轉的頂點之間插值。

float4 vertexani(float3 vertex)
為了方便設定蒙版我們設定乙個debug模式以觀察蒙版。

因為我們只在編輯室才需要這個顯示蒙版的著色器變體,所以將關鍵字設為著色器特性。

#pragma shader_feature _debug_check_mask
接著我們要將mask值傳給片元函式

struct v2f;
然後修改頂點和片元函式

...#ifdef _debug_check_mask

o.maskcol=getmask(v.vertex.x);

#endif

...}fixed4 frag(v2f i):sv_target

這樣我們就可以檢視蒙版了 

綜上,最終的動畫如下

因為我們的魚群使用同乙個網格,所以我們可以使用例項化技術,大量的魚的例項共用同乙個網格,這裡我們不考慮陰影和多光源的例項化,所以實現方式很簡單。

#pragma multi_compile_instancing
首先新增乙個多重編譯指令,unity會檢查你的shader是否支援例項化,如果是,那麼材質面板會出現這樣乙個toggle。

接下來就是讓shader支援例項化

先是輸出結構,新增乙個巨集

struct v2f;
然後是頂點函式

v2f o;

unity_setup_instance_id(v);

...}

好了,接著我生成了2000條魚,並開啟例項化。

ps:雖然的確的確減了draw call,但是我開啟和關閉例項化都是70多幀,不知道為什麼- -|||

todo ...演講最後有人問演講者有關於魚群游動的行為,演講者提到每條魚都會根據周圍的魚進行判斷。emmm,先挖個坑吧

大規模地形渲染

地形在計算機圖形學中是一種比較特殊的物體 通常地形被設計為規則的網格 網格上每個頂點都根據不同的高度在網格的法線量方向進行位移 地形的高度被儲存為乙個名為高度圖的檔案中 當地形的網格結構越密集 地形的外觀就顯得越平滑 但同時也增加了需要被渲染的頂點和三角形數量 怎麼才能在保證地形的外觀平滑的前提下儘...

利用GPU實現大規模動畫角色的渲染

我想很多開發遊戲的小夥伴都希望自己的場景內能渲染越多物體越好,甚至是能同時渲染成千上萬個有自己動作的遊戲角色就更好了。但不幸的是,渲染和管理大量的遊戲物件是以犧牲cpu和gpu效能為代價的,因為有太多draw call的問題,如果遊戲物件有動畫的話還會涉及到cpu的蒙皮開銷,最後我們必須找到其他的解...

軟體的大規模生產

很多人都幻想軟體可以工廠化,流水線化生產,但是這一天卻從來沒有到來。軟體和工廠模式的不同在於軟體是研發出來,而工廠是研發出來後,持續生產。工廠中的生產階段是重點,而軟體的生產階段只需要複製複製,可以忽略不計。所謂的流水線指的是工廠的生產階段,所以軟體很難出現所謂的流水線。那麼軟體是不是無法擴大規模,...