Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Unity+スマホで3Dゲーム開発最適化するための考え方
Search
Cygames
January 14, 2016
Programming
15
24k
Unity+スマホで3Dゲーム開発最適化するための考え方
2015/11/15 Cygames Tech Fes
Cygames
January 14, 2016
Tweet
Share
More Decks by Cygames
See All by Cygames
『GRANBLUE FANTASY Relink』キャラクターの魅力を支えるリグ・シミュレーション制作事例
cygames
0
410
『GRANBLUE FANTASY: Relink』最高の「没入感」を実現するカットシーン制作手法とそれを支える技術
cygames
1
350
『GRANBLUE FANTASY Relink』ソフトウェアラスタライザによる実践的なオクルージョンカリング
cygames
0
320
高品質なフォトグラメトリデータを取得するためのハードウェア&ソフトウェア開発
cygames
0
1.1k
AIを活用した柔軟かつ効率的な社内リソース検索への取り組み
cygames
0
1k
『GRANBLUE FANTASY: Relink』開発からリリースまでを支えたCI/CDの取り組み
cygames
0
250
『GRANBLUE FANTASY: Relink』専任エンジニアチームで回す大規模開発QAサイクル
cygames
0
260
『GRANBLUE FANTASY: Relink』クオリティと物量の両立に挑戦したフェイシャルアニメーション事例 ~カットシーンからランタイムまで~
cygames
0
310
『GRANBLUE FANTASY: Relink』キャラクターの個性にlinkした効果音表現
cygames
0
130
Other Decks in Programming
See All in Programming
Jakarta EE meets AI
ivargrimstad
0
380
rails new flags - `rails new` のフラグから Rails を構成するコンポーネントの変遷をザックリ眺める
snaka
0
1.8k
タクシーアプリ『GO』のリアルタイムデータ分析基盤における機械学習サービスの活用
mot_techtalk
6
1.7k
シェーダーで魅せるMapLibreの動的ラスタータイル
satoshi7190
1
480
Why Jakarta EE Matters to Spring - and Vice Versa
ivargrimstad
0
1.3k
subpath importsで始めるモック生活
10tera
0
340
Outline View in SwiftUI
1024jp
1
350
Hotwire or React? ~アフタートーク・本編に含めなかった話~ / Hotwire or React? after talk
harunatsujita
1
120
CSC509 Lecture 12
javiergs
PRO
0
160
Amazon Bedrock Agentsを用いてアプリ開発してみた!
har1101
0
350
AI時代におけるSRE、 あるいはエンジニアの生存戦略
pyama86
6
1.2k
Jakarta EE meets AI
ivargrimstad
0
760
Featured
See All Featured
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
4
380
Large-scale JavaScript Application Architecture
addyosmani
510
110k
For a Future-Friendly Web
brad_frost
175
9.4k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
16
2.1k
The Pragmatic Product Professional
lauravandoore
31
6.3k
Music & Morning Musume
bryan
46
6.2k
Code Reviewing Like a Champion
maltzj
520
39k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
28
2k
We Have a Design System, Now What?
morganepeng
50
7.2k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.4k
RailsConf 2023
tenderlove
29
910
Transcript
Unity+スマホで3Dゲーム開発/最適化 するための考え方 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE 株式会社Cygames エンジニア
金井 大
自己紹介 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 金井 大
• 技術研究チーム所属のエンジニアです • VR、ゲームエンジン、グラフィックスとかの研究 開発してます
アジェンダ $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • Unity +
スマホで3Dゲーム開発/最適化する ための考え方を、以下で紹介します – 開発の指針 – 構成およびスペックの一例 – 開発と最適化のためのTIPS – 指針と手法の答え合わせ
開発の指針 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
大事なこと $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 端末の性能を把握する •
コンテンツの要素を把握する – 適切な単位で区切り – コストを把握し – そのコストを最適化する • 要素を選択できるようにする
UNITY HARDWARE STATISTICS $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE •
出典:http://hwstats.unity3d.com/mobile/ • unity mobile stat で検索
詳細 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • Mali 400
MP: 20.0% • Adreno 305: 12.5% • PowerVR SGX543: 10.9% • Apple A7: 8.5% • Adreno 330: 5.9% • Adreno 306: 5.4% • Apple A8: 4.7% • PowerVR SGX544: 4.1% • Adreno 320: 2.8% • Vivante GC1000: 2.3% • Videocore IV: 2.2% • Mali 450 MP: 2.1% • Mali T760: 2.1% • PowerVR SGX540: 1.6% • PowerVR SGX531: 1.5% • Adreno 203: 1.4% • PowerVR SGX535: 1.3% • Adreno 200: 1.2% • PowerVR SGX554: 1.0% • Adreno 225: 0.9% • Adreno 405: 0.8% • Mali T628: 0.7% • Apple A8X: 0.6% • PowerVR G62xx: 0.5% • Mali T624: 0.5% • Tegra 2: 0.5% • Intel HD BayTrail: 0.4% • Adreno 220: 0.4% • Vivante GC2000: 0.4% • BlueStacks ES2.0 Emu: 0.3% • Tegra 3: 0.3% • Mali 300: 0.3% • Mali T720: 0.3% • Mali T622: 0.2% • Adreno 205: 0.2% • PowerVR G64xx: 0.2% • Adreno 420: 0.2% • Adreno 430: 0.1% • Immersion.16: 0.1% • Adreno 418: 0.1% • Vivante GC7000: 0.1% • Vivante GC800: 0.1% • Something strange: 0.1% • Adreno 304: 0.0% • PowerVR SGX530: 0.0% • Vivante GC4000: 0.0% • Android ES Emulator (GeForce): 0.0% • Tegra 4: 0.0% • Mali T604: 0.0% • Android ES Emulator (Radeon): 0.0%
3DMARK $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 出典:http://www.futuremark.com/hardware/mobile/ •
3DMARK mobile results で検索
3DMARK $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 拡大
どうしてこうなった $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • キャリア •
チップセット • CPU – コア数 – クロック • GPU • メモリ
PCゲームのグラフィックス設定 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 出典: http://doope.jp/media/15q1/img2826_01.j
pg
$POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • どこまでユーザーに選択させるか?
スマホでの現実解は? $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • ある程度は大まかに制御したい –
エフェクト ON/OFF – 効果音 ON/OFF – FPS – スペックの抽象化
$POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 「スペックの抽象化」ってなんやねん
例えばシェーダーを例に $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • Vertex shader
– カラーアニメーション – UVアニメーション – アウトラインメッシュの法線方向への拡大 – セルルック • Fragment shader – イメージエフェクト – スキンシェーダー – ノーマルマップ – セルルック
アプリケーションでの抽象化 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • Vertex shader
– カラーアニメーション – UVアニメーション – アウトラインメッシュ – セルルック • Fragment shader – イメージエフェクト – スキンシェーダー – ノーマルマップ – セルルック 低スペック 高スペック 使わない
端末に落とし込む $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • Vertex shader
– カラーアニメーション – UVアニメーション – アウトラインメッシュ – セルルック • Fragment shader – イメージエフェクト – スキンシェーダー – ノーマルマップ – セルルック 低スペック 高スペック 使わない iPhone5s iPhone6 iPhone6s Galaxy S5 Galaxy S6
大事なこと $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 端末の性能を把握する •
コンテンツの要素を把握する – 適切な単位で区切り – コストを把握し – そのコストを最適化する • 要素を選択できるようにする
構成およびスペックの一例 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
目標 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 60fpsをキープしたい •
キャラクターを5体表示 • 絵力 – フェイシャル – モーションキャプチャー – 他と差別された強い絵力が欲しい! • タイトなスケジュールに負けない
より現実的なゴール $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 低スペック端末では –
幅広く動作するようクオリティぎりぎりまでスペック を落としつつ60fpsをキープ • 高スペック端末では – 高性能端末で高品質な画面を提供しつつ60fpsを キープ
キャラクター $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • スペック –
テクスチャ • ETC1(αチャンネルなし)/PVR • Mipmapなし(データサイズ縮小のため – ウェイト • 基本は2ボーン – 3ボーンをPlayerSettingで2にするとメッシュが崩れることがあ る
キャラクター $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • フェイシャル –
ボーン制御 – Animatorで眼球、リップの動きを用意し、外部から 制御 – 眼球の追従先をプログラム制御 • アウトライン – アウトラインメッシュ – 頂点カラーでの調整 – リムライト、セルルックは…? • 造形が良ければアウトラインでも
キャラクター $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • クロス –
独自実装 – それなりに重いので、まずはC#でチューン • 計算部分のみなら22行程 – マルチスレッド化できるようにデータ局所化 – あとはネイティブプラグイン化すれば…
背景 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • テクスチャ –
基本はETC1(αチャンネルなし)/PVR – Mipmapあり – UVアニメーション用に3MB程度を確保 • 画面キャプチャ – ImageEffectで作成した中間バッファを流用 – 1フレーム遅れた絵になるが低コスト
その他 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • ライティング –
基本的にはライティングしない – アンビエント – 板を1軸回転してカメラに向けてボリュームライトっぽく • シャドウ – リアルタイムシャドウは断念 – 板ポリの安いやつ。Diffuseに焼く。 • ないと立体感なくなります • パーティクル – 一定数まとまったメッシュを用意 – パーティクルとして降らせる – Vertex shaderで動きをつける
Image Effect $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • ImageEffect
– DOF(被写界深度 – Bloom – カラーコレクトはオミット • Unityのシェーダーをベースに – 1カメラで実現できるようカスタマイズ – ついでに高速化
Directシーン $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • キャラクターや背景の任意組み合わせを確認でき る専用シーン
• デザイナー/プランナーの作業、確認が主用途 • 各種アセットのデータ形式に対応 – 通常アセット – アセットバンドル(サーバー上 – アセットバンドル(ローカルPCにつくったやつ • 端末でも動作可能 – アプリ本体を経由しないので、単体テストやコスト計測 にも使える
開発と最適化のTIPS $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
計測 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
Unity Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
Statistics $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
FrameDebugger $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • DrawCallを確認可能 –
Unity5から こ の へ ん が 描 画 リ ク エ ス ト
GPU Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 描画系の追跡はUnity
Profilerでは限界がある – オーバーヘッド – GPUのプロファイルに難アリ • チップセットと対になったGPU Profilerを使う – iOS -> instruments / OpenGL ES Frame Debugger – Adreno -> Adreno Profiler – Tegra -> PerfHUD ES • 端末や要素の性能を把握できる
例:Adreno Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
Adreno Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • プロファイルした情報を保存することが可能
– チューニング前後の比較に • 頂点データ/テクスチャの保存 • シェーダーの可視化と変更 • Etc…
Adreno Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • FrameDebuggerと同じくDrawCallが目視で
きる
Adreno Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • フレームバッファ、テクスチャのキャプチャ
• シェーダー修正
Adreno Profiler $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • FPSやGPU使用率などをグラフ化
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • おおざっぱに以下のように考える –
vertex負荷 = (描画リクエストされた頂点数) x (vertex shaderの命令数) – fragment負荷 = (描画されたピクセル数) x (fragment shaderの命令数) – 厳密にはパイプライン次第だと思う • 各ベンダー/各世代のチップ考慮するのは大変なので
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 出典: http://climserv.ipsl.polytechnique.fr/documentation/idl_he
lp/images/shader_detail.gif
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 例:球(4000頂点)を(1/1)と(1/4)で描画し た時の比較
– vertex負荷は同じ – fragment負荷は約1/16になる
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • vertex負荷の制御はデリケート –
描画対象となる頂点数を減らしたい – 何らかで頂点数を削れば良いのだが… • データ削減するとシルエット崩れや作業コストが懸念 • カリング精度を上げるにはCPU/GPU負荷が懸念 • fragment負荷は比較的制御しやすい – 描画面積とシェーダーで制御できる – カメラワークには注意
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • vertexは最初から低めに抑さえる –
特に低スペック端末を考えると低めにせざるを得 ない – 最低限のLODデータを用意する • fragment負荷を制御できる手段を用意する – ImageEffectをOn/Offする – 画面解像度を制御する – Meshのfragmentシェーダーを軽量版に切り替える
描画負荷軽減のポリシー $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 前提として「描画順」と「ZTest」を理解する –
ZTestが有効な場合、隠れたfragmentは描画されない • 1がZ値的に手前にある時、1を描いてから2を描 くと、一部は描画されない 2 1
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 極端にすると。 •
1を描画してから2を描くと、2は殆ど描画されな い 2 1
隠れているのがポイント $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • アウトラインメッシュの描画が無駄になるので •
こういう順番にしたい
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 不透明は(基本的には)手前から描く –
隠れた個所はfragmentシェーダーが走らない – 基本的にUnity側が手前からソートしてくれてる
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • なんだけど –
原点位置を基準にソーティングする – 意図した結果になるとは限らない – こういう時は床を最後にしたいが原点基準だと。。。
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • Unityで描画順を制御する手段 –
Camera.depth – MeshRenderer.sortingLayerName – MeshRenderer.sortingOrder – Material.renderQueue
描画順の制御 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 優先としては以下になる Camera.depth
sortingLayerName =“default” sortingOrder =0 renderQueue=2000 renderQueue=2010 renderQueue=3000 sortingOrder =100 renderQueue=2000 renderQueue=2010 renderQueue=3000 sortingLayerName =“after” sortingOrder =10 renderQueue=2000 renderQueue=2010 renderQueue=3000 sortingOrder =200 renderQueue=2000 renderQueue=2010 renderQueue=3000
Camera.depth $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • CameraはCullingMask設定が必要になるなど、 色々面倒
– ImageEffect使用時は注意! • Camera.clearFlags=Depthだとclearが劇重 • GPU20%程度の消費することも
MeshRenderer.sortingLayerName $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • sortingLayerNameは以下で追加可能 –
Layers -> Sorting Layers • 記載の順番に処理される
MeshRenderer.sortingOrder $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 同じsortingLayerNameでの描画順 •
sortingLayerNameと合わせて運用を考える
Material.renderQueue $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • マテリアル単位で描画順を制御する •
Material.renderQueueはシェーダーからも設定可能 – Tags {"Queue"="Geometry-1" "RenderType"="Opaque"} • Queueは文字列に見えるけど実際は数値 – Background = 1000 – Geometry = 2000 – AlphaTest = 2450 – Transparent = 3000 – Overlay = 4000 • なので、前述の例は「1999」になる
こんな事も $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 「髪の毛より手前にある眉」
髪の毛より手前にある眉 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 髪の毛に隠れてしまう眉毛を何とかして手前 に出したい
– ZTest / ZWriteをOffにして対処 – ZTestしないので、「必ず」最前面に眉が描かれる (髪の上に描かれる) – ZWriteしないので、他のオブジェクトにZ値干渉し ない
髪の毛より手前にある眉 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 弊害として、他キャラの眉毛が貫通してくる可 能性がある
– 描画順を制御して奥から描く • キャラA頭 • キャラA眉 • キャラB頭 • キャラB眉 • …
髪の毛より手前にある眉 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 問題はいくつか残る –
頭と眉の形状によっては、自キャラの眉が貫通して くる • カメラワークでの回避 – 無駄な描画が発生する • 我慢する
SetPassとDrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
DrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • まずDrawCall –
GPUへ描画リクエストする、ということ – 固有のマテリアルを描画リクエストすると 1DrawCall消費する – Unity5からStatisticsより消失しました
$POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 「固有のマテリアルを描画リクエストするとDrawCall 消費する」ってなんやねん •
「固有のマテリアル」ってなんやねん
DrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 固有のマテリアルとは –
UnityEngine.Materialのメンバがユニークであるこ と – 例えば • Colorが異なる • Textureが異なる • Shaderが異なる • Etc… – 他と異なるメンバがあれば、それは固有である
DrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • BOX全体にマテリアルA →
DrawCall=1 • BOX各面にマテリアルABC → DrawCall=3 A A B C
DrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX全体にマテリアルA)x2 →
DrawCall=2 • (BOX各面にマテリアルABC)x2 → DrawCall=6 A A B C A A B C
DrawCallとバッチ処理 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 同じマテリアルだったら最適化できそう •
そこでバッチ処理 • 同じマテリアルをもつドローコールを統合する
DrawCallとバッチ処理 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX全体にマテリアルA)x2 →
DrawCall=1 A A
DrawCallとバッチ処理 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX各面にマテリアルABC)x2 →DrawCall
数は描画順に依存する(後述) A B C A B C
DrawCallとバッチ処理 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • バッチ処理は2種類ある •
StaticBatch – 移動しない同一マテリアルを持つメッシュをマーキングし、 事前にバッチ用のデータをしこむ – 統合の効果が高いが、移動したりマテリアル操作するメッ シュには適応できない • DynamicBatch – 前後のドローコールが同一マテリアルをもつ場合、ランタイ ム時に統合する – ランタイムに行うのでCPUコストがそこそこある – StaticBatchより効果が低い(頂点数等の制限数がある) • http://docs.unity3d.com/ja/current/Manual/DrawCallBatchin g.html
DynamicBatch $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • DynamicBatchの注意点 –
前後のドローコールが同一マテリアルを持たないと統 合しない – 描画順によっては統合できない! – 例えば描画順が以下だと統合されない • BOX(マテリアルA • BOX(マテリアルB • BOX(マテリアルC • BOX(マテリアルA • BOX(マテリアルB • BOX(マテリアルC • DrawCall=6になる
DynamicBatch $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 描画順が以下であれば統合される –
BOX(マテリアルA – BOX(マテリアルA – BOX(マテリアルB – BOX(マテリアルB – BOX(マテリアルC – BOX(マテリアルC – DrawCall=3になる • 描画順は前述のsortingOrderで制御可能
DrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • DrawCallを減らすのであれば、描画時に固有 マテリアルが連続するよう、ルールを決めてお
く – Batch処理を利用する – sortingOrder等で描画順を制御する – そもそも固有マテリアルを減らす • テクスチャを共有化する • シェーダーを共有化する • 変更するパラメーターを限定する • Etc…
SetPass $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • SetPassとは –
よりパフォーマンスの指針となる数値 – DrawCall時に前回使用したマテリアルから変更が あった場合、1SetPass消費する
SetPassとDrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 【Unity】Unity Performance
Casual Talk 「ド ローコール伝説の終わり」 レポート – http://qiita.com/baba_s/items/5260807ced7fc3c02ca 6
SetPassとDrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX全体にマテリアルA)x2 →
SetPass=1 • バッチに依存せず、SetPassは1になる A A
SetPassとDrawCall $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • (BOX各面にマテリアルABC)x2 →
SetPassは描 画順に依存する • SetPassを減らすにはDrawCallと同じく描画順を 意識する • DrawCallと同じノウハウが利用できる A B C A B C
Depth Texture $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
Depth Texture $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • ImageEffectの被写界深度はZ値を参照してボカ
シ処理を行う • Z値を参照するには、DepthTextureが必要 – Camera.depthTextureMode = DepthTextureMode.Depth; • 注意点 – DepthTextureはRenderTargetへ描画を行うことで 生成されてる – DepthTextureへポリゴンを描いている、ということ – 単純に描画頂点数が二倍になる
Depth Texture $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • DepthTextureへの描画時に利用されるシェー
ダーは? – シェーダー中のTagsを参照してます • http://docs.unity3d.com/ja/current/Manual/SL- ShaderReplacement.html – UnityにLightModeというタグが用意されており、以 下タグを持つSubShaderに置き換わる • Tags{ "LightMode" = "ShadowCaster" } – Unity4 -> 5で変更された箇所なので注意
Depth Texture $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • ShadowCasterシェーダーを実装する理由
– アウトライン+DOF時に必要となる事がある – キャラクターはアウトライン分微妙にサイズが大き くなる • ので、DepthBufferに書き込む大きさを調整する – やらないとアウトラインがボケてしまう
Multi threaded Rendering $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
Multi threaded Rendering $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE •
CPUがGPUを待つケースが減り、FPSの上昇が 期待できる • (空いてるCPUコア数が少ないと意味はない)
Multi threaded Rendering $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE •
なのですが。。。 – UnityのMultiThreaded Renderingに関する資料は 少ない – マルチスレッド関係は不具合出やすい個所なので 注意しましょう。 • Multithreaded + DynamicBatchでハングする事例あり • Unity5.0.2p3で発生
指針と手法の答え合わせ $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE
大事なこと $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 端末の性能を把握する •
コンテンツの要素を把握する – 適切な単位で区切り – コストを把握し – そのコストを最適化する • 要素を選択できるようにする
端末の性能を把握する $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 実際に計測すること •
Profiler – Unity Profiler – Frame Debugger – GPU Profiler • 各種サイト – 3DMARK – Unity Hardware Statistics
要素を適切な単位で区切る $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • ゲーム的かつ技術的な視点で区切る –
キャラクタ/背景/エフェクト – 頂点数/テクスチャ/ボーン数 – シェーダー – ImageEffect – CPU/GPU
コストを把握 $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 実際に計測すること •
Profiler – Unity Profiler – Drame Debugger – GPU Profiler • CPU/GPUどちらがネックなのか • GPUネックならこれが参考になります • Computer Graphics Gems JP 2015 • http://www.borndigital.co.jp/book/5498.html# • 2.5.4 パイプラインのボトルネック解析
コストを最適化する $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 定期的に監視すること –
できるだけ早いタイミングから – 想定された端末でのチェック – 機能が入ると知らない間にコスト上がる • 配分を決めること • FPS/SetPassといった性能指針を
要素を選択する $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • What if
– ◦◦したらどうなるだろう • キャラクタを増やすor減らす • ImageEffectをOn/Offする • シェーダーを切り替える • 選択を容易にする機能を実装する • ゲームと独立した場所があるとベスト
おしまいです $POGJEFOUJBM $PQZSJHIU $ZHBNFT *OD "MM3JHIUT3FTFSWFE • 時間があればDEMO