AIに身体性を与えるためのマイクロワールドの構築3です。
マルチマテリアル処理と、オクルージョンカリングについて記載します。
まずは、パフォーマンスにどれだけ差が出るか、一番簡単で頭の悪い実装を行ってみたいと思います。
以前パーリンノイズで、キューブオブジェクトを配置していくデモを見ましたね。
simplestar-tech.hatenablog.com
こちらのコードを参考に六角柱オブジェクトを配置していくデモシーンを作ってみましょう。
ざっと 180 x 40 個の六角柱を表示したところ 20fps で SetPass call が 14100 回という値でした。
では、カリングなしで、とりあえず全部同じ GameObject となるように修正してみます。
つまり、巨大な頂点バッファとインデックスバッファとUV座標バッファを構築して、描画するという手段を取ってみます。
先ほどと同じように 180 x 40 個の六角柱を表示したところ 77fps で SetPass call が 19 回という値でした。
パフォーマンスモニターで Draw に要した時間は 0.53 ms でした。
つまり、描画速度は 94倍アップしました。
さて、試してみてわかったことに、残念ながら全頂点を一つのメッシュに格納できなかったため
180 x 4 個の六角柱ずつ、計10 個のオブジェクトで描画することにしました。
マテリアルが一色なのは、サブメッシュカウントを1にしているためです。
続いて、深度によって色分けされるように追加実装してみます。
できました。
サブメッシュ数を増やすことで、SetPass call が 67 回と増えてしまいましたが
パフォーマンスモニターで Draw に要した時間を調べたところ 0.64 ms と、そこまでパフォーマンスは落ちませんでした。
対象 Unity シーンは HexRandomMap です。
GitHub にアップしましたので、実装が気になる方はこちらを見てみてください。
マルチマテリアル処理まで、確認しました。
引き続きオクルージョンカリングについて記載していきますよ!
続く…
2017/10/15 続きです。
まずオクルージョン処理に入る前にいくつか障害があります。
どういう障害なのかもわからないので、一つ一つ具体的にしていく作業から始めます。
なんとなく気づいたこととして
指定した幅と高さが感覚と合わない問題がありました。
これを頑張って解決しました。
以下の絵は 8x8 を指定したときのメッシュ結合結果です。
これで感覚に沿うようになりました。
X軸に六角形が 8 つ並び、Z軸方向は密に配置されるように交互にオフセットが入るようになっています。
頂点数と三角形数は、特にカリングが入っていないのでこのような数字となっています。
続いて、ワールドを構成する情報をもとにビジュアライズしていないという問題があります。
こちらも頑張って解決しまして
次のように3次元配列にブロックのあるなしを指定することで
_mapData[0][0][0] = 1; _mapData[0][0][1] = 1; _mapData[0][0][2] = 0; _mapData[0][0][3] = 1; _mapData[1][0][0] = 1; _mapData[0][1][0] = 1;
3次元空間のブロックの積み重ねをメッシュ結合ともとに、ビジュアライズできるようにしました。
そして残るは、接合している表示されることのない三角形や、完全に埋もれてしまう頂点をメッシュから除去する仕組みが入っていない問題があります。
例えばこれ、8x8x8の結合メッシュですが
こんなに頂点数や三角形数はいらないはずなんです。
こちらを頑張って解決することにしました。
頑張ると、こんな感じで頂点数や三角形数が減りました。
これ以上減らすことは不可能なので、頑張るのはここまでにします。
試しに1000万ブロックを敷き詰めたマイクロワールドを描画してみました。
プロファイラーで確認したところ、81.8FPS の Wait for FPS が 91% の 11.79ms でした。
つまり、描画に要している時間は 0.92 ms ほどでした。
ブロック一つ一つにゲームオブジェクトを割り当てた最初の簡単なアプローチと比べて
大幅にパフォーマンスアップしました。
あとはコード整理ですが、ひとまず六角柱を敷き詰めたマイクロワールドの構築がイメージに近づいてきた
(マルチマテリアル処理と、オクルージョンカリングについて記載した)ので、次の記事に進みます。