第7回テックヒルズ
PLAYGROUND内の描画仕組み
ロマン ピコア
現代のモバイル用描画パイプライン

固定機能
プログラム可能
状態の変更のコスト
実行回数や負担を減らすための一般方法
まったく描画しないために処理
カメラの空間に無い物を描画しない。(カリング)

ピクセル毎の負担を減らす又ステート変更を減
らす
透明ではないオブジェクトを「近く遠く」にソート

透明であるオブジェクトを...
モバイル、2Dの場合


Shader数が少ない、変わらないゲームも多い。




透明ではない物はほとんどありません:背景のみ。






画像とαブレンド・足し算ブレンドはほとんど。

Z Bufferのトリックは無意味。

...
次のボトルネック:切り替えより回数減らそう
描画回数を減らすため、ステートが同じなら、バッチを実現。
4回実行(頂点情報だけが違う)
一回で描画

複数の描画命令を同じステートなら、同じ頂点リストにまとめて、実行数を減らす。
変わりにCPUがV...
Playgroundでは?
XY

UV

モデル : XY バッファ / UV バッファ

インスタンス化 + 2D Matrixをかける(状態キャッシュ)
CO X U X U X U
インスタンス : Color + XYUV Buffe...
速度を保つためにはキャッシュ&フラグ
①変わった時にフラグのみを変更
②変更された所だけのMatrixを再計算(フラグがあるため、
最適化ができて、無駄な計算せずにすむ)

Index
XY UV

2Dモデル
2Dインスタンス
シーングラフの...
気になる、Cocos 2Dはどうしている?

見た限り、バッチは可能ですが、純粋にプログラマーの責任
気になる、Unityはどうしている?
普段の場合、Unityの仕様を見ると、
 Batching of static model done by Unity Pro.
 Batching of dynamic model done by U...
Upcoming SlideShare
Loading in …5
×

Playground内の描画仕組み

3,084 views

Published on

Slide describing the playgroung 2D game engine rendering system.

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,084
On SlideShare
0
From Embeds
0
Number of Embeds
179
Actions
Shares
0
Downloads
11
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide
  • 今晩は、クラブのピコアと主します。今日のため何かを話そうかを悩んでたのですが、全体的にモバイルの描画の仕組みと、Playgroundの仕組みの話をしようと思います。よろしくお願いします。描画は奥が深い専門なので、10分程度ですから、コンパクトに正確な情報を説明したいと思います。(30 - 40秒)
  • まず、現代のモバイル用のGraphic Pipelineを説明する必要があります。これがそのパイプラインの図です。それぞれの機能を連続に実行して、入力されたベクターデータが画像を作る事になります。頂点のそれぞれのバッファーの構造が設定できるため、まずデータを集まる・変換する仕組みが存在します。(Vertex Gather)そして、頂点の計算を行う。(Vertex Shader)そのあと、三角の場合のみの話ですが、頂点を3個ずつにまとめ、描画できるように三角を設定します。(Primitive Assembly)そして、ピクセル毎にRasterizerが働いて、ピクセル毎の計算を行う(Pixel Shader)そのあと、Depth TestやStencilを行う。この図はKhronos Groupからの図ですが、実はHWではEarly Z と言いまして、先にZ機能の一部を使う事でPixel Shaderを実行しない事もできる。そうすると、節約につながっています。モジュール毎にプログラム可能と固定機能を設定するだけの2種類に分かれており、それぞれの機能にパラメターを設定して、描画を実行する。(1分30秒程度): 2 mn
  • 状態を変更し、描画を実行するの繰り返しで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
  • そして、全体的にMatrixの計算更新を実際実行するのはフラグによってされるので、必要な部分のみを再計算します。そのあと、変わったMatrixにつながっている2Dインスタンス(つまり描画命令の一部)、Matrixをかけたあとの状態を再計算します。ですので、Cache的な役割を持ち、変わった時にだけ再計算されます。そして描画ループで描画リストをみながら、さらに、フラグ情報でバッチ自身が変わったかどうか、ずれがあったどうか、色やUVや座標だけが変わったのかをうまく確認し、バッチ自身のコストも最適化可能。9.5mn
  • 9.75mn
  • Unityの場合、モデル毎にmesh / materialになってて、Mesh が 3Dモデルの頂点の事です。Materialがどんなshaderで、どんなtextureを利用しているのかを意味する。そうしますと、同じMaterialでまとめる処理を行う。つまりバッチする。さらに、動かないオブジェクトであれば、同じmeshにまとめるUnity Proの機能があります。(Dynamic バッチのコストを下がる)Materialを気をつければ、うまくバッチできるはず。しかし、2Dの場合、例えば、ex2Dのライブラリではバッチを自前で実装している。純粋に3Dモデルを使って、2Dをやる分にはとくに問題ないですが、2Dライブラリによって、処理が違うかもしれないので、気をつける点です。1分30 – total 10mn30 sec.
  • Playground内の描画仕組み

    1. 1. 第7回テックヒルズ PLAYGROUND内の描画仕組み ロマン ピコア
    2. 2. 現代のモバイル用描画パイプライン 固定機能 プログラム可能
    3. 3. 状態の変更のコスト
    4. 4. 実行回数や負担を減らすための一般方法 まったく描画しないために処理 カメラの空間に無い物を描画しない。(カリング) ピクセル毎の負担を減らす又ステート変更を減 らす 透明ではないオブジェクトを「近く遠く」にソート 透明であるオブジェクトを「遠く近く」にソート 高級なゲームはモデルOcclusionを計算 シェーダーの種類・パラメターでソート テクスチャーでソート A A A B B B
    5. 5. モバイル、2Dの場合  Shader数が少ない、変わらないゲームも多い。   透明ではない物はほとんどありません:背景のみ。    画像とαブレンド・足し算ブレンドはほとんど。 Z Bufferのトリックは無意味。 3Dに比べてベクターデータ/頂点が少ない。 塗る面積が3Dとやや同じ・もっと大きいかも。 (Overdraw)
    6. 6. 次のボトルネック:切り替えより回数減らそう 描画回数を減らすため、ステートが同じなら、バッチを実現。 4回実行(頂点情報だけが違う) 一回で描画 複数の描画命令を同じステートなら、同じ頂点リストにまとめて、実行数を減らす。 変わりにCPUがVertex Shaderの計算の一部を自前で計算し、バッファー作成する。
    7. 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 同じステートで実行
    8. 8. 速度を保つためにはキャッシュ&フラグ ①変わった時にフラグのみを変更 ②変更された所だけのMatrixを再計算(フラグがあるため、 最適化ができて、無駄な計算せずにすむ) Index XY UV 2Dモデル 2Dインスタンス シーングラフのノード XUXUXUXU YVYVYVYV ③変更された時だけにMatrixをかけて、画面空間で XYを計算。そしてXYUVをインターレス化:キャッ シュ CO L ④フラグによって、コピーの最適化: XYUV, COLOR, INDEX XYU V Index COL
    9. 9. 気になる、Cocos 2Dはどうしている? 見た限り、バッチは可能ですが、純粋にプログラマーの責任
    10. 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#で自前でバッチする。

    ×