7. Playgroundでは?
XY
UV
モデル : XY バッファ / UV バッファ
インスタンス化 + 2D Matrixをかける(状態キャッシュ)
CO X U X U X U
インスタンス : Color + XYUV Buffer
L
YV YV YV
描画時にバッチバッファにまとめる
XUXUXUXUXUXUXUXUXU
… YV YV YV YV YV YV YV YV YV …
CO CO CO CO CO CO
…
…
L
L
L
L
L
L
同じステートで実行
10. 気になる、Unityはどうしている?
普段の場合、Unityの仕様を見ると、
? Batching of static model done by Unity Pro.
? Batching of dynamic model done by Unity. (=Playgroundと同じ動
作)
? Culling done by Unity
普通に3Dモデルで2Dを描画する作業なら、バッチ機能がやってくれ
るはず。
しかし2Dライブラリの場合、ライブラリ次第です。
例えば、ex2DライブラリはC#で自前でバッチする。
状態を変更し、描画を実行するの繰り返しで1画面分の画像を作る。もちろん、この図は理論的な話であって、わかりやすくするため、わざとたくさんな変更を見せかけた。実際に内部のステートがそんなに激しく(はげしく)変わっていない。でも、よく変わるのは同じ物を描画するではなくて、毎回違う物を描画するため、Vertex情報のバッファーが基本的に変わる。ShaderのパラメターShader自身利用されるTextureその他はZ Testがよく変更されます。(1分) - 3 mn total
細かい説明をしませんが、基本的に3Dエンジンなら、こんな作業をする。まずCPU側で- カメラの空間にモデルが入るかどうか確認する、例えばBounding box/ellipseを使って確認コストを出来るだけ安くする。さらにOcclusion Libraryを使う高級エンジンもある。描画するシーンのいろんな順でソートする。GPUが無駄をしないため。そして、CPUの先処理によって、GPUの時間?負担が少なくします。Textureの切り替え数を減らす:まとめて描画する。 Z Bufferで近くにあったオブジェクトを先に描画させる事によって、裏にあるピクセルを出来るだけZ バッファでrejectされる。その他のわざもたくさんあるので言うだけ : LOD モデルやシェダー, Imposter, mipmapなど)じゃ、2Dゲームの場合ではどうなりますか?(1分30秒) - 4mn30 total
2Dの場合、まず不透明なオブジェクトがほとんどない。背景のみ。そのあと、画像をかさねて描画するだけです。すべての画像が透明のため、Pixel Shaderの実行回数を減らすのは難しい。また、3Dに比べたら頂点の数は1/10になってもおかしくないので、Vertex shaderのコストやCPUでBatchするコストが問題にならないです。そして、ステートがほぼ変更がないため、ステート変更が基本的にTextureの切り替えと頂点データ。(1分) - 5mn30 total
ですので、出来るだけ、同じTextureに素材あつまれば(Atlasと言います)さらにステートの変更を少なくが出来る、そうすると、実行回数自身を減らす事が可能になります。同じステートであれば、まとめて一気に描画する。しかし、このため、CPU側で以前にあったVertex Shaderの一部の仕事をCPU側に持っていく事が必要です。OpenGLESの仕様では、頂点のバッファーの順で描画する事になっていますので、CPUで作ったリストの順でそのままGPUが描画します。1分 – 6mn30 total
3Dエンジンと同じくモデルを持つ。(座標、UV, Color)しかし、色の情報はモデルに必要ない、インスタンスのみ。Cullingが基本的にしない。ポリゴンがそんなに多くないため、OpenGLESにスキップさせた方が早い。(ただし、場所によって更新しないコードが存在。)インスタンスが座標情報を画面空間でCPUで計算し、インスタンスで保存。描画時にコピーし、まとめて描画。もちろん、インスタンス内の更新やバッチ用のバッファの更新が最適化にされており。出来るだけ無駄なコピーや更新処理を実行しないように設計されています。メリット:ユーザがtextureの順と描画順をあわせる事を気をつけたら、自動的に最適なGPUコールになります。Demerit : はじめからCPUに負担をかける事。2分 : total 8 mn