Continue(s)

Twitter:@dn0t_ GitHub:@ogrew

【Unity】DMI vs DMI2

はじめに

(界隈には今さらな技術かもしれませんが…。)

あるメッシュを大量にレンダリングしたいとき、Unityではいくつか方法がありますがGPU Instancingはその中で強力な手段の1つです。

特に今回はUnityが用意している2つの描画用API Graphics.DrawMeshInstanced()(以下DMI) と Graphics.DrawMeshInstancedIndirect() (以下DMI2)の簡単な実装例とそれぞれのメリットデメリットをわかる範囲で整理します。

Graphics.DrawMeshInstanced(DMI)について

主な引数

引数 概要
mesh Mesh インスタンスさせたいメッシュ
submeshIndex int そのメッシュのサブセット
material Material 使用するマテリアル
matrices Matrix4x4[] 位置、回転、スケールを評価する行列
count int インスタンスさせたい数
properties MaterialPropertyBlock 同マテリアルだがインスタンスごとに変えたいパラメータ

簡単な使用例を見ていきます。

1000個のQuad Meshを生成します。

gist.github.com

gist.github.com

DMIの欠点としてComputeShaderの都合、インスタンスが最大で1023個までしか生成できないことがよく挙げられます。

しかし、これも1023個を1束としたバッチ処理で回避することができます。

ためしに10000個のQuad Meshを生成します。

gist.github.com

話は横道にそれますが、インスタンスそれぞれの影が出ないのはやはり違和感なので、そこだけSubShaderを追加したのも載せておきます。(影の描画描画周りは少しややこしいです。)

gist.github.com

上の実装からもわかるようにDMIは気軽にGPU Instancingさせることが可能な一方で、メッシュのマトリックス情報の更新はCPU側からGPUに毎フレーム送る必要があります。つまり大量のインスタンスをそれぞれ移動させたり回転させたりするのはかなり厳しいです。(バッチ処理するとなると尚更です。)

そこで出てくるのが次項の DMI2 です。

Graphics.DrawMeshInstancedIndirect(DMI2)について

主な引数

引数 概要
mesh Mesh インスタンスさせたいメッシュ
submeshIndex int そのメッシュのサブセット
material Material 使用するマテリアル
bounds Bounds 描画範囲
bufferWithArgs ComputeBuffer (後述)

最後のbufferWithArgsについてはメッシュを描画するのに必要な残りの情報をぶち込めるようになっています。公式でこれをまとめている部分が見当たらないのですがネットの先人らの知恵を参考にまとめたのが以下です。

引数 概要
0 コピーしたいメッシュ1つあたりの頂点数
1 何個コピーしたいのか
2 メッシュの開始インデックス
3 メッシュの頂点インデックス
4 生成し始めるインスタンスのインデックス

DMI2はGPU側にインスタンシングに必要な情報を持たせることができるのでDMIのようにCPUとのやりとりによる負荷はそこまでネックになりません。また1023個の制限もなくなります。

ここでも簡単な例を見て見ましょう。

40000個のQuad Meshを生成します。今度は最初から影付きです。

gist.github.com

gist.github.com

いい感じです。ちなみにカメラを適当に動かしても100FPSくらい出てます。

インターネットにはGPU InstancingとCumputeShaderの合わせ技でかっこいい演出を施す記事が多いのですが本来これらは別の技術です。1個前の例のようにDMI2を使ってGPU Instancingをさせるだけでも良いし、以前書いたこの記事のようにCompute ShaderだけでプリミティブはCPUでなんとかするでも良いわけです。

おわりに

今回はUnityに搭載されているGPUインスタンスAPIのDMIとDMI2についてまとめました。

とある案件でShaderGraphを使って100KオーダーのGPU Instancingをさせたいとなり調査をしていくと、DMIはできるけどDMI2では難しそうということがわかりました。そもそも僕自身がDMIは使ったことあるけどDMI2を使ったことない状態だったので一度機能について整理してみようというのが記事を書くきっかけでした。

一応このフォーラムをみるに、有志の方がカスタムノードを提供していて、それを使えばShaderGraphでもDMI2を実装できなくはないようです。個人的にはノードとコードを行き来しながら作業するのはなるべく少なくしたいという思いがあるのでせめて公式が専用ノードを出すまではコード書くのでいいかな、と思っています。

それからDMIとDMI2の中間的立ち位置にGraphics.DrawMeshInstancedProceduralというAPIがありますが、今回は時間の都合、触れませんでした。DMI2とそこまで違いはありません。

参考

ホビー数学07「ベッドルームで群論を」

まずはじめに、この本は群論の本ではない。無論、代数学の本でもない。

アメリカの科学雑誌のコラムニストが25年間書きつづけた数多の文章から選びぬかれたエッセイ選集である。

私が独りでやっているこのホビー数学の活動には、今までこれと言ってルールは設けてなかったが、それでも一応、学習の参考になるような小難しい専門書や動画コンテンツを中心に取り上げてきた。

したがって今回のようなエッセイ集は対象から外すべきかとも考えたのだが、第1章を読み終えるころにはその気持ちはすっかり切り替わっていた。

まずわかりやすい指標として伝えたいのは、このエッセイ集の巻末には参考文献が16頁に渡って箇条書されている。(専門用語や学者の名前も8頁にわたって索引にまとまっている。)

要するにガチなのだ。

著者のブライアン・ヘイズ氏は、もともと年少の頃から物理学者か海洋学者にあこがれるような好奇心旺盛な子供で、学生のときたまたま単位の問題で文系に進まざるを得なくなり、新卒?で新聞社を経て、そこから書評などを書くライターとして頭角を現し、そして科学専門誌でエッセイを掲載するようになったというユニークな経歴を持つ。

彼が執筆活動と並行して自然科学、中でも数学の分野で自学自習を進めていった結果、各界の学者からクオリティの高いコラムとして称賛されるようになった。(ときには的はずれな計算や論理展開もしてしまうが、有識者からのアドバイスに真摯に向き合う姿勢は尊敬に値する。)

全部で12のエッセイが掲載されているのだが、それぞれで扱う分野は異なる。

せっかくなので索引から本書で重要となるキーワードをいくつかピックアップすると、対称3進数、NP完全、遺伝暗号、カントール集合、巡回群、隠れた変数理論、等価演算子擬似乱数、分水界、(戦争の)マグニチュードファレイ数列、など。

この本が他のいわゆる理数系のうんちく本と一線を画すのは、ただただ興味深い歴史的事実や学際エピソードを紹介するだけでなく、著者自ら問題と向き合い、ときにアルゴリズムを考えたり、図書館へうん十年前の非専門誌を探しに行ったり、手計算した結果をグラフにしたりと、文章の隅々に「科学遊び」に熱中する著者の熱量を感じとることができる。

その貪欲さのおかげで遺伝暗号や分水嶺といった自分に余り馴染みないテーマの文章でも、ぐいぐいと最後まで読み切ることができた。

12の章ごとに逐一、感想をツイートをしていたのでそれを掲載する。

1.ベッドルームで群論

2.資源としての「無作為」

3.金を追って

4.遺伝暗号をひねり出す

5.死を招く仲違いに関する統計

6.大陸を分ける

7.歯車の歯について

8.一番簡単な難問

9.名前をつける

10.第三の基数

11.アイデンティティーの危機

12.長く使える時計