作ったもの
Unity、VRChat向けのメッシュ軽量化ライブラリを作りました。
MITライセンスで公開しており、VPMでインストールすることが
できます。(非VRChatのUnityでも利用可能です)
使い方
Meshia.MeshSimplificationではシンプルなステートレスAPIを採用しているので、簡単に使い始められます。
using Meshia.MeshSimplification;
Mesh simplifiedMesh = new();
// 非同期API
await MeshSimplifier.SimplifyAsync(originalMesh, target, options, simplifiedMesh);
// 同期API
MeshSimplifier.Simplify(originalMesh, target, options, simplifiedMesh);
VRChat向けの使用法や、詳細な使い方はドキュメントを参照してください。
既出では?
Unity向けの無料のメッシュ軽量化ライブラリとしてはUnity公式のフォークもあるUnityMeshSimplifierや、それをVRChat向けに使いやすくしたものが既にあります。
有料で有名なものとしてはMantis LOD Editorなどもあります。
Meshia.MeshSimplificationではこれと比較して
- 高速な動作
- マルチスレッド対応
- 非同期API
が含まれています。
高速な動作、マルチスレッド対応
Meshia.MeshSimplificationではほぼ全ての処理がJobSystem上で行われており、Burstも適用されているので高速かつメインスレッド以外もしっかり活用して処理をしてくれます。
これは、Unity 2020.1で追加されたAdvanced Mesh APIによって可能になりました。
Unityの対応バージョンが古く、従来のAPIを使用しているUnityMeshSimplifierやMantis LOD Editorではメインスレッドからしかメッシュのデータにアクセスできないので、メインスレッドのみでの動作となっています。
非同期API
Meshia.MeshSimplificationではJobSystemを使用しているため、処理はワーカースレッドで行われ、非同期で結果を受け取ることができます。
誰でも簡単に利用できるよう、ステートレスAPIではJobSystem特有のJobHandleなどではなく、Taskとして非同期処理を行えるようになっています。
Mantis LOD Editorでもリアルタイムでの段階的なプレビューに対応していますが、あくまでもメインスレッドを使用してフレーム間をまたいで段階的に処理をするものとなっています。
実装詳細
処理の並列化
Meshia.MeshSimplificationでは頂点バッファーからの読み込み、インデックスバッファーの取得、初期の削減候補の生成などの処理を全て別のJobで行うことで可能な限りマルチコアを活用するようになっています。
ただ、一番時間がかかる実際に頂点を削減していく処理はアルゴリズムの都合上1スレッドしか使えないのが問題点です。
Advanced Mesh API
Meshia.MeshSimplificationで利用しているUnityのAdvanced Mesh APIは頂点データの読み書きに生の頂点バッファーを用います。
みなさんは頂点の座標やノーマル、頂点カラー、UVといった頂点毎データ、VertexAttributeがどのように管理されているか知っていますでしょうか?
VertexAttributeは
- 32bit浮動小数点数
- 16bit浮動小数点数
- 8bit固定小数点数(0から1)
- 8bit固定小数点数(-1から1)
- 16bit固定小数点数(0から1)
- 16bit固定小数点数(-1から1)
- 8bit符号なし整数
- 8bit符号あり整数
- 16bit符号なし整数
- 16bit符号あり整数
- 32bit符号なし整数
- 32bit符号あり整数
のいずれかの数値を1~4の要素数持つことで一つの頂点のUVや頂点カラーなどの情報を表現しています。
例えば
- 座標
- 32bit浮動小数点数*3
- ノーマル
- 32bit浮動小数点数*3
- タンジェント
- 32bit浮動小数点数*3
- 頂点カラー
- 8bit固定小数点数(0から1)*3
- UV
- 16bit浮動小数点数*2
といった具合です。
これらのVertexAttributeが任意数のバッファーに任意のレイアウトにインターリーブされて格納されているのが生の頂点バッファーです。
シンプルな例として
複数のバッファーがあるパターンとして
などがありえます。しんどいですね。
Meshia.MeshSimplificationでは基本的にどんなフォーマットでも32bit浮動小数点数*4のフォーマットに変換してから処理をする方針を取っています。
Advanced Mesh APIではBlendShapeにアクセスできない
Advanced Mesh APIでは何故かBlendShapeにだけはアクセスできないので、Meshia.MeshSimplificationではBlendShapeの情報だけはメインスレッド上で一旦コピーしてから処理をしています。
あとがき
Meshia.MeshSimplificationを支援していただける方は、GitHub Sponsorsでの支援や、BOOTHでの支援版の購入をお願いします!
また、IssueやPRなどもお待ちしております!
