21.3K Views
August 14, 23
スライド概要
2023年8月に新横浜インディゲームもくもく会でLTした資料です。
フリーランスのTAです。 主にもくもく会でのLT資料などをアップロードしたいと思います。
Unityで大量の草を生やせ! おかひろ
自己紹介 おかひろ Twitter:@okahiro_p フリーランスのTA 個人で東方二次創作ゲーム作っています
こういうやつをやります
草 1本6Trisの草を90本生やして1オブジェクトとする オブジェクトを10,000個並べる 90万本の草 先端が風で揺れるような表現をする VertexShaderで動かす
こんな感じで写す 約7400オブジェクト(66万本の草)が写るショット
最初に まずは愚直に10,000個オブジェクトを並べてみる ※左端1,000個選択
結果 ※Pixel6で計測 ・SetPassCall:23 ・DrawCalls:7.3k ・Tris:3.9M
重い! DrawCallが7.3kある DrawCall:CPUがGPUに出す描画命令。描画対象のオブジェクト数分発行される 10kでないのは、2.7kはカメラに写っていないためカリングされている Materialはすべて一緒なのでSetPassCallは多くない CPU GPU 描画命令 7300回
DrawMeshInstancedIndirect 同じMesh・Materialを大量に描画できる CPUからGPUへの描画命令を1回で行う CPU GPU 描画命令
結果 ※Pixel6で計測 ・SetPassCall:23 ・DrawCalls:23
早くなった・・・けど まだFPS30いっていない 更に改善 DrawMeshInstancedIndirectだと10,000オブジェクト分を指定しているが、実際はすべてカ メラに写るわけではないので、Cullingを行う ComputeShaderによる擬似視錐台カリング 最初の例ではUnityが勝手に視錐台カリングしてくれていたが、DrawMeshInstancedIndirectする場合は自前で Cullingが必要 遠くの草も1オブジェクトあたり90本の草を描画しなくても良さそう。 ComputeShaderでLODを行い、遠くの草は低ポリゴンのものに差し替える 更に、遠くの草は風で揺れなくても良い(どうせ見えない) VertexShaderの処理削減 中距離用の草(20本) 遠距離用の草(10本)
CullingとLOD CullingとLODなし CullingとLODあり ※LODをわかりやすくするため、遠距離:赤、中 距離:青の色をつけている
結果 ※Pixel6で計測 ・SetPassCall:23 ・DrawCalls:23
草の生やし方 実際のゲームでは、草原がきれいな正方形になることはほとんどないと思う 描画速度を担保しつつ、生え方も考慮したい
いろいろ方法がありそうだが・・・ 100×100pxの画像を用意し、ピクセルごとにrの値が0なら草を生やさない、1 なら草を生やす処理を実装してみた このあとCullingとLODのComputeShaderに値を回すのと、並列で処理しやすいので これもComputeShaderで実行
例 わかりにくくなるためCullingはオフ
例 わかりにくくなるためCullingはオフ
例 わかりにくくなるためCullingはオフ
参考資料 モバイル向け大量描画テクニック UnityURP-MobileDrawMeshInstancedIndirectExample https://github.com/ColinLeung-NiloCat/UnityURPMobileDrawMeshInstancedIndirectExample OpenWorldGrassDemo https://www.youtube.com/watch?v=mmxpPDVskg0 https://github.com/Gamu2059/OpenWorldGrassDemo Recipes for Shaders and Visual Effects https://resources.unity.com/ebooks/the-universal-render-pipeline-cookbook-unity2022-lts-edition?ungated=true
ご清聴ありがとうございました