SlideShare a Scribd company logo
1 of 107
Download to read offline
動くものが何もないタイトルシーンで 16FPS
バトルシーンに至っては 5FPS しかでない
Yomuneco Inc. 権藤丈人
ガルガンチュア on Oculus Quest
72FPS への挑戦
アジェンダ
プロファイリング
レンダリング最適化機能・手法
最適化事例
プロファイラ紹介
まとめ
プロファイリング
プロファイリングの必要性
半透明は重いらしいので、エフェクトを減らしました!
テクスチャが大きいと重いらしいので、すべてのテクスチ
ャの解像度を落としました!
ドローコールが多いと重いらしいので、オブジェクトをま
とめました!
プロファイリングを行わず、ボトルネックと違うところの最適化に
時間をかけても、パフォーマンスは上がらず、クオリティだけ下が
ってしまう。
プロファイリングでボトルネックを探しだし、効果が高く短時間で
行える最適化から取り組むことが重要。
CPU負荷傾向と対策
主にアクター数、物理シミュレーション、クロスシミュレーシ
ョン、アクターやパーティクルなどの生成負荷に影響を受ける
ので、アクター数を減らす。クロスシミュレーションの処理を
簡略化するなど。
主にマテリアル数、マスターマテリアルの数、カリング、ライ
ト数などの影響を受ける。アクターのマージ、マテリアルのマ
ージ、メッシュのマージ、マスターマテリアルの共通化などを
適用した軽量LoDモデルを表示に利用する。
主にシェーダーにわたすパラメータやテクスチャの数で負荷が
増大する。基本的にはDrawCall数の削減が重要。
Game Thread
Render Thread
RHI Thread
GPU負荷傾向と対策
メッシュをまとめる
LODの有効化やメッシュを分割することでカリングが効くよ
うにし、無駄な頂点計算を抑制する
ピクセルシェーダーの軽量化
テクスチャルックアップを減らす
半透明オブジェクトの場合、メッシュのサイズを最適にする
アルファで非表示にしないでドローコールから消す
オーバードローを減らす
ドローコール過多
頂点負荷
ピクセル負荷
デバイスの限界性能を引き出すには
Developmentビルドでは、様々なデバッグ機能やプロファイリング
機能が動作している為、ゲームの処理負荷を正確にプロファイリン
グすることが出来ない。
まずは、Testビルドでボトルネックを絞り込み、Developmentビル
ドで詳細なプロファイリングを行う。
Testビルドではエンジンの詳細なプロファイラーが使えないので、
外部のプロファイラーを併用する。
TESTビルドでプロファイリングを行う
レンダリング最適化機能・手法
フラスタムカリング
視錐台と各オブジェクトのバウンディングボックスを計算し、見える
オブジェクトのみを GPU へ投入することで、ドローコールを減らす。
VR では頭を振ることで HMD の向きに基づくフラスタムが一瞬にして
大きく切り替わってしまい、カリング処理の遅れによる画面のチラツ
キが発生する為、ガルガンチュアではカリング時のバウンディングボ
ックスにスケールを掛けている。
[CEDEC2017] UE4プロファイリングツール総おさらい(グラフィクス編) https://www.slideshare.net/EpicGamesJapan/cedec2017-ue4
オクルージョンカリング
前面のオブジェクトに隠れて見えないオブジェクトを描画対象
から排除する機能。
[CEDEC2017] UE4プロファイリングツール総おさらい(グラフィクス編) https://www.slideshare.net/EpicGamesJapan/cedec2017-ue4
LOD (Level of Details)
カメラから離れる程(スクリーンに対するオブジェクトのサイズが小さ
い程)ローポリなメッシュに変更して負荷を下げる。
サイズが小さくなれば細かい部分は目立たない。
LODはメッシュだけでなく、パーティクルやマテリアルにも設定可能。
Oculus Quest では LOD Bias 設定を使い、最小LODを変更している。
早期深度テスト (Early Depth Stencil Test)
Input
Assembler
Vertex
Shader
Rasterizer
Pixel
Shader
Output
Merger
Early Depth
Stencil Test
深度テストをピクセルシェーダーより前に行うことで、テスト
を通過しないピクセルのピクセルシェーダーの起動を抑制する
機能。
ハードウェア機能なので、実装されていないデバイスでは使え
ない。
ピクセルシェーダーで深度値の変更やピクセル破棄(アルファ
テスト)を行ってはならない等の制約がある。
Input
Assembler
Vertex
Shader
Rasterizer
Pixel
Shader
Output
Merger
Early Depth
Stencil Test
プリミティブアセンブリでプリミティブが構成された時点で、
頂点レベルで深度値が計算されており、ラスタライザーにより
各ピクセルの深度値に補完される。
この頂点の深度値を元に、早期深度テストが実行される。
ピクセルシェーダーで深度値の変更やピクセル破棄を行う場合
、ピクセルシェーダーを実行しないと最終的な深度値が確定し
ないため、早期深度テストは機能しない。
テクスチャのアルファでマスクするような不透明シェーダーは
、ピクセル破棄が行われている。
早期深度テスト (Early Depth Stencil Test)
Z Pre Pass
レンダリングパスの初めに、不透明オブジェクトの深度デー
タのみを深度バッファへ書き込むパスを追加することで、
Early Depth Stencil Test による無駄なピクセルシェーダーの
起動を抑制する効果を最大限に引き出すことができる。
ドローコールや頂点シェーダーの起動数が増えるが、概ね軽
量化が望めるらしい。
Z Pre Pass Base Pass Translucency Post Process
ガルガンチュアでは PC 版で利用している。
Oculus Quest 用のレンダラーに実装してみたところ、Z Pre
Pass で増える負荷と、Base Pass で減る負荷がだいたい同じ
くらいだった。ワーストケースでは逆に重くなる場合も。
SoC ではバッファの書き込みや、ドローコールを減らす方が
効果がありそう。
Z Pre Pass Base Pass Translucency Post Process
Z Pre Pass
Frame Buffer Fetch
OpenGL ES 2.0 では、Frame Buffer Fetch という拡張機能がサポ
ートされている。
本来、フレームバッファは書き込みのみをサポートしており、シ
ェーダーから読み込むことはできず、シーンのカラーが必要な場
合は、予めフレームバッファのデータを別のテクスチャリソース
としてコピーし、シェーダーリソースとしてシェーダーに与える
必要がある。
この機能により、処理中のピクセルのフレームバッファの値を直
接読み込むことができる為、テクスチャリソースの確保やコピー
が不要となる。
利用するにはハードウェアサポートが必要。
シェーダーの並列動作
頂点シェーダーとピクセルシェーダーは並列で動作する。
過密度なモデルはピクセルシェーダーへのピクセル提供が間に合わずにボ
トルネックになりレンダリング全体のパフォーマンスを低下させる。
頂点読み込みはバンド幅を大量に消費するので少ないほど良い。
頂点数を減らすには、軽量LoDの適用、不要頂点の削除する。
過密度なモデルとは、頂点数に対するピクセル数の割合が極端に
少ないもの。
多頂点のオブジェクトが遠方に大量にあるなど。
頂点シェーダーが頂点の座標変換を行い、プリミティブアセンブ
リで構築が完了したプリミティブからラスタライザーを通りピク
セルシェーダーが実行される。
頂点数に対してピクセル数が少ない場合、ピクセルシェーダーは
、プリミティブアセンブリからのプリミティブを待っている時間
が長くなりパフォーマンスが落ちる。
ピクセル未満のプリミティブが発生すると、1ピクセルに複数の
プリミティブが割り当てられ、オーバードローが発生し、ピクセ
ルシェーダーの処理にも無駄が発生する。
ピクセル単位でしか色を塗れないので、ピクセル未満のプリミテ
ィブは無駄でしかない。
シェーダーの並列動作
最適化事例
Oculus Quest 版 レンダリング設定
OpenGL ES 3.1
フォワードレンダリング
基本的にダイナミックライトなし
ライトはライトマップにベイク
ダイナミックオブジェクトの影はフェイク
アンチエイリアス無し
デカール無し
Multi View Rendering
OpenGL RHI Thread
ほとんど動くものがないシーンで、16FPS しか出ていな。
とりあえず動いたタイトルシーン
シンプルなメッシュにコンクリートシェーダーを
画面いっぱいに描いただけでも 72FPS に届かない。
GPU 処理時間が 15.74ms、72FPS を達成するため
には 13.8888.. ms に収めなければならない。
SnapDragon Profiler で調査したところ、主なボトルネックは
Texture Fetch Stall だったため、Texture Lookup を減らす。
Texture Lookup: 21 > 7
GPU: 15.74ms > 4.35ms
Texture Lookup 4 以下はそんなに減らない
Texture Lookup: 7 > 2
GPU: 4.35ms > 3.59ms
テクスチャフェッチストール
GPU も CPU と同じくメモリアクセス(I/O)には大きなレイテンシが
発生する。
GPUの主なメモリアクセスは頂点データとテクスチャアクセス。
テクスチャフェッチには数100〜数1000のクロックサイクルを必要
とするため、全体のパフォーマンスを落とす原因になりやすい。
デスクトップ向けGPUに搭載される GDDR5 と Oculus Quest に搭
載される LPDDR4x では、10倍以上の速度差がある。
シェーダーユニットはストールに遭遇すると別のピクセルの処理を
行うというのを繰り返す。中断したピクセルの処理に戻ってきた際
にテクスチャの値が返ってきていなければ、シェーダーユニットは
何の処理も行わず待つことになる。
また、テクスチャを処理できるユニットにも物理的に上限がある。
そもそもストールを発生させなければ、シェーダーユニットはより
早く他のプリミティブの処理に移ることができる。
テクスチャルックアップ削減
大理石のタイルシェーダー
タイル内の模様(ディテール)を、タイル毎に向きを変えようと
している。
ディテールの向きを表すのは、赤青緑のテクスチャ。
定数定義された 4つの回転値で UV を回転させて、ディテールテ
クスチャをルックアップしたカラーを、ディテールの向きを表す
テクスチャの値でブレンドしている。
ディテールの向きテクスチャ1回、ディテールテクスチャ4回で
、合計5回のテクスチャルックアップが行われている。
4つの回転値を、ディテールの向きを表すテクスチャの値でブレン
ドした後に、ブレンドされた回転値で UV を回転させて、ディテ
ールテクスチャをルックアップすることで、ディテールの向きテ
クスチャ1回、ディテールテクスチャ1回で、合計2回のテクス
チャルックアップで同じ結果を得ることができる。
大理石のタイルシェーダー
大理石のタイルシェーダー
タイルパターンのテクスチャは、ディテールの向きを表すテクス
チャをグレースケールにしたものと大差ない。
ディテールの向きを表すテクスチャは、ディテールカラーを計算
する際にルックアップ済みのため、この値をグレースケール化し
て、タイルパターンとして扱うことでテクスチャルックアップを
1回分減らすことができ、タイルパターンテクスチャそのものも
不要となる。
大理石のタイルシェーダー
大理石のタイルシェーダー
模様の入り方は同じ。
タイルパターンは変わってしまったが、全体のイメージは同じ。
キャラクターシェーダー
ガルガンチュアのキャラクターには、発光する部分があり、その
位置と色を表すためのテクスチャ(Emissive Map)が用意されて
いる。
一般的に Diffuse Color に使われるテクスチャは RGB の3チャン
ネルしか使われていないが、テクスチャフォーマットとしては
RGBA の4チャンネルを扱うことができ、A(アルファ)チャン
ネルが余っている状態。
次の例では、Diffuse Color と Emmisive Map で使われる UV が同
じ(テクスチャ内の位置関係が同じ)且つ Emmivie Color が単色
であるため、Emmivie Map をグレースケール化(明るさ情報)に
変換し、Diffuse Color のアルファチャンネルに統合することで、
Emissive Map のテクスチャルックアップを削減。
マテリアルパラメーター(シェーダーパラメーター)として色を
設定し、アルファチャンネルの明るさ情報と掛け算することで、
ほぼ同等の見た目になる。
キャラクターシェーダー
キャラクターシェーダー
メッシュリダクション
見えない部分の頂点を削減
プレイヤーが近づけない位置のメッシュ。
細かい表面の凹凸は頂点を使わずノーマル
マップで誤魔化す。
プレイヤーからは見上げる位
置にあるので見えない角度に
ある上部の頂点を削る。
台座の裏側の頂点もざっくり
カット。
メッシュをマージ&裏面除去
天井から伸びているオブジェクトはインスタンス化されているが、手
前のオブジェクトに隠れている部分にも大量の頂点がある。DCC ツー
ルでメッシュをマージして裏面を除去することで大量に減らせる。
描画領域の最適化
描画領域の最適化
フェイクシャドウは丸影ベースで作成しているが、描画している
メッシュは矩形状であり、四隅のピクセルは無駄にシェーダーが
走る。
描画領域の最適化
フェイクシャドウのメッシュを円形にすることで、頂点数は
増えるがピクセル数を大幅に減らすことができる。
無駄なドローコール
何も描かれない無駄な半透明メッシュ。
メッシュ自体の表示設定を制御してドローコールを発行しない。
無駄なドローコール
何も描かれない無駄な半透明メッシュ。
メッシュ自体の表示設定を制御してドローコールを発行しない。
Texture Lookup
Pixel Shader
GPUはピクセルシェーダーを起動して得られた結果を
ブレンドし、結果何も変わらなかったというのを全て
のピクセルで実行してしまう。
両面レンダリングを安易に使わない
腰布は一枚のメッシュで構成されているため、裏から見ると消えてしまう。
両面レンダリングにすると、モデル全体の裏面もピクセルシェーダーが起動
するようになる為、腰布に裏を向いたメッシュを重ねる。
モデルのお腹側のポリゴンはカメラの方向を向いているが、背中側
のポリゴンはカメラと反対方向(裏面)を向いている。
裏面プリミティブは、プリミティブアセンブリで除去されピクセル
シェーダーは走らないが、両面レンダリングを有効化した場合、背
中側の裏面プリミティブもピクセルシェーダーが走ってしまう。同
一ピクセルで背中側のシェーダーが先に実行された場合、背中側・
お腹側で2回シェーダーが実行される。先にお腹側が実行された場
合、背中側は深度テストでカットされる。
どちらの面から描画するかを制御する方法はない。やるとすれば、
両面レンダリングしたい部分のドローコールを分けるくらい。
両面レンダリングを安易に使わない
不透明オブジェクトのオーバードロー
不透明オブジェクトのオーバードローはピクセル未満のプリミティブに
よって発生する。LOD を追加することで緩和できる。遠方のオブジェク
トは多少形状が破綻しても分からない。
描画領域の最適化
描画範囲を最小限にする為に、頂点シェーダーで頂点位置を加工する。
攻撃範囲を示すメッシュ。
描画負荷を抑えるため、不透明で描いている。
様々な大きさのリングを描くためにメッシュのスケール
を利用するとリングの幅も変わってしまうため、頂点カ
ラーを利用し、頂点シェーダーで頂点位置を加工してい
る。
描画領域の最適化
描画範囲を最小限にする為に、頂点シェーダーで頂点位置を加工する。
大きなリングの中にプレイヤーがいる場合、リングを視
認しづらい。かといって半透明で広範囲を塗りつぶすと
重いため不透明メッシュの頂点を時間で動かすことで視
認性と低負荷を両立させている。
パーティクル
描画領域の最適化&オーバードローの削減
青い炎のメッシュパーティクル
変化が視認できるピクセルに対して、メッシュの面積がかなり大きい。
オーバードローも多く、高負荷。
板ポリ1枚に描くように修正し、面積・オーバードローを削減。
ピクセルシェーダーの複雑度
白いところが無くなるようにする。
描画領域の最適化&オーバードローの削減
稲妻のメッシュパーティクル
描画範囲が広く、オーバードローも多い。
メッシュの幅をできる限り細くすることで、面積・オーバードローを削減。
描画領域の最適化&オーバードローの削減
パーティクルエミッタの軽量化
多数のエミッターがドローコールを発行している。
LODで重要度の低いエミッターを無効化する。
描画面積に対して負荷が高い。「描画面積が小さい=視覚効果への影響度
は小さい」と言えるのでパーティクルエミッターを簡略化する。
パーティクルエミッタの軽量化
パーティクル カットアウト
CPU でテクスチャのアルファな
どを参照して不要な領域をカット
アウトする機能。
CPU の処理負荷が若干増えるが
、GPU の処理を軽減できる。
UI
描画領域の最適化
UI の表示。
ビューポートを覆う、巨大なメッシュで UI を描いている。
全ピクセルに対してピクセルシェーダーが起動する為、とても重いが、面積の
殆どは完全に透明であり無駄が多い。
描画範囲を最小限に減らし、上・中・下段に分割することで、ドローコールは
増えるが、ゲームプレイ中は何も描画しない中央部分の描画負荷を削減した。
描画領域の最適化
味方のいる方向を示すカーソルの描画。
面積の多くは完全に透明であり無駄が多い。
描画領域の最適化
また、UIウィジェットとして作成されているため、
レンダーターゲットへの描画が実行される。
描画領域の最適化
メッシュ化することで、必要最小限の面積にダイレクトに描画
できる。デメリットとして、エディタのUIデザイナを用いた編
集ができない。
シェーダーの統合
UI の背景のグラデーションをレンダーターゲット全体に描いたあと
に飾り枠を描いているが、この時もほぼレンダーターゲット全体に
ピクセルシェーダーが起動している。背景と飾り枠を同時に描くよ
うに修正。
レンダーターゲットへの描画を分散
全NPC のステータスパネル用のレンダーターゲットが毎フレーム描画され
ている。レンダーターゲットの内容はゲージに変更がなければ再描画する
必要はない。
ステータスパネルのレンダーターゲットへの描画は8フレームに分散させ
、1フレームあたり最大2体分に抑制。
毎フレーム、ウィジェットのCPU処理が動いている。
ウィジェットに変更がなければ、レイアウトをキャッシュすること
で処理を軽減できる。
InvalidationBox を使うことでレイアウトをキャッシュできる。
UE4 のバグなのか、ScaleBoxを利用するとフォントキャッシュが
効かなくなる。
Widget: InvalidationBox
Invalidiation Box | Unreal Engine ドキュメント https://docs.unrealengine.com/ja/Engine/UMG/UserGuide/WidgetTypeReference/Invalidation/index.ht
Widget: RetainerBox
UI のレンダーターゲットが毎フレーム描画されている。
パーツ単位で更新フレームを分散させることで負荷を軽減する
RetainerBox でレンダーターゲットの描画間隔を設定できる。
Widget タイプのリファレンス | Unreal Engine ドキュメント https://docs.unrealengine.com/ja/Engine/UMG/UserGuide/WidgetTypeReference/index.ht
その他の最適化
カリングの最適化
インスタンス化されたオブジェクトがレベルを
覆っており、常にすべての頂点が計算される。
カリング効率を考えてインスタンス化する。
Precomputed Visibility
レベルビルド時にキャラクターが移動可能な範囲をグリッドに分
割して、グリッド単位で静的オブジェクトの可視性を事前に計算
しておく機能。
ランタイムでのカリング処理を軽減できる。
事前計算されたビジビリティ ボリューム (Precomputed Visibility Volume) | Unreal Engine ドキュメント
https://docs.unrealengine.com/ja/Engine/Rendering/VisibilityCulling/PrecomputedVisibilityVolume/index.html
Cull Distance Volume
オブジェクトとカメラの距離とサイズに応じてオブジェクト
をカリングする機能。
一般的なオクルージョンカリングは、GPU での処理が必要に
なり、カリング処理自体にそれなりの負荷がある。
CPU で、距離やサイズによって描画対象から除外することに
よって、オクルージョンカリングの負荷を軽減することがで
きる。
カリング距離ボリューム (Cull Distance Volume) | Unreal Engine ドキュメント
https://docs.unrealengine.com/ja/Engine/Rendering/VisibilityCulling/CullDistanceVolume/index.html
存在価値の低いオブジェクトの削減
暗くてよく見えないオブジェクトや手前のオブジェクトに
隠れて殆ど見えないオブジェクトを削除
※画像はガンマで明るくしてます
タイムラインアニメーション
タイムラインアニメーションは CPU で処理が行われるため、大量
に生成されるオブジェクトで利用すると無視できない負荷となる。
ダメージ数値の表示は UI ウィジェットをタイムラインで動かすという作り
になっていて、フォントテクスチャも生成されており、とても重かった。
予め数字のみを並べたテクスチャを作り、UV を加工することで任意の数字
を表示できるシェーダーを作成し、タイムラインアニメーションと同様の頂
点アニメーションも組み込み、全て GPU で処理を行うように変更した。
タスク実行スレッドの調整
Oculus Quest ではゲームが使えるコアは3つしかなく、ガルガン
チュアでは RHI スレッドを有効化しているため、Game, Render,
RHI スレッドが常に3コアを利用している状態であり、下の画像
の様に、タイミング悪くタスクスレッドが Render や RHI スレッ
ドに割り込まれた場合、タスクの完了を待っている Game スレッ
ドが遅延する。
今回の例では、FParallelBlendPhysicsTask 自体の処理は非常に軽
い為、タスク化せず、Game スレッドで行うように変更してヒッ
チを解決した。
ガルガンチュアでは、手の先
に掴めるオブジェクトがある
か、エンチャントアクション
を起こせる武器があるか、手
が貫通できない壁があるか、
を判定する為、計6回の
Raycast を行っている。
これをそれぞれ毎フレーム行
わずに6フレームに分散させ
ることで Physics 負荷を抑え
ている。
レイキャスト
オーバーラップイベント
オーバーラップが有効なコンポーネントは、位置を動かした際に
、Physics Scene の更新処理が入るが、これがそこそこ重い。
UPrimitiveComponent はデフォルトで有効になっているため、必
要なければオフにする。
同一アクター内の複数のコンポーネントでオーバーラップが有効
になっている場合(カプセルコンポーネントとメッシュコンポー
ネント等)複数回 Physics Scene の更新処理が入る。
武器などの一部のオブジェクトは必要に応じて ON/OFF を切り替
えている。
パーティクルコリジョン
22.726ms ( 13) - Thread_1362_0 - TaskGraphThreadHP 4 - STATGROUP_Threads - STATCAT_Advanced
11.676ms ( 6) - Other TaskGraph Tasks - STAT_TaskGraph_OtherTasks - STATGROUP_Threading - STATCAT_Advanced
7.289ms ( 5) - FParticleAsyncTask - STATGROUP_TaskGraphTasks - STATCAT_Advanced
7.240ms ( 5) - Particle Compute Time GT,AT - STAT_ParticleComputeTickTime - STATGROUP_Particles - STATCAT_Advanced
7.141ms ( 1) - ParticleSystem/Game/Effect/Asset/BattleEffect/Enemy/EnemySkill/PowerStrike_001/PS_PowerStrike_001_ed.PS_PoweSTATCAT_Advanced
7.024ms ( 1) - Emitter/PS_PowerStrike_001_ed/Spark Red 002 - STATGROUP_Emitters - STATCAT_Advanced
7.021ms ( 1) - Sprite Tick Time GT - STAT_SpriteTickTime - STATGROUP_Particles - STATCAT_Advanced
7.012ms ( 1) - Sprite Update Time GT - STAT_SpriteUpdateTime - STATGROUP_Particles - STATCAT_Advanced
6.972ms ( 1) - Particle Collision Time GT - STAT_ParticleCollisionTime - STATGROUP_Particles - STATCAT_Advanced
6.924ms ( 75) - SceneQueryTotal - STAT_Collision_SceneQueryTotal - STATGROUP_Collision - STATCAT_Advanced
6.913ms ( 75) - RaycastSingle - STAT_Collision_RaycastSingle - STATGROUP_Collision - STATCAT_Advanced
6.902ms ( 75) - ParticleCollision - STATGROUP_CollisionTags - STATCAT_Advanced
6.428ms ( 75) - PhysX Scene ReadLock - STAT_PhysSceneReadLock - STATGROUP_Physics - STATCAT_Advanced
Game スレッドが Physical Animation のタスク完了を待っている状
態であるが、Physical Animation のタスクが振り分けられたスレッ
ドに、パーティクルコリジョンのタスクも振り分けられており、パ
ーティクルコリジョンの処理に引きずられて、Physical Animation
Task, Physical Animation Completion Task が遅れてしまい Game ス
レッドがヒッチする原因となる。パーティクルのコリジョンを外す
ことでパフォーマンスを解決。
Fixed Foveated Rendering
ガルガンチュアでは、GPU のレンダリングコストを抑える為にベー
ス解像度をデバイスの性能に応じて変更している。
Oculus Quest では 70% まで下げている。
また、”Fixed Foveated Rendering” という技術を利用し、視野周辺の
解像度を更に落としている。
1/2
1/4
1/8
1/16
Oculus Go: Fixed Foveated Rendering
https://developer.oculus.com/documentation/unreal/latest/concepts/unreal-ffr/
Multi View Rendering
複数の View (左目・右目) を一度に
描画できる機能。
ドローコールを半減できる。
Multi View に対応したシェーダーを
書く必要がある。
ハードウェアサポートが必要。
Multi View Rendering
モバイルHDRのポストプロセスの負荷を SnapDragon Profiler で計測したもの。
ポストプロセスは MultiView に対応していないため、左目と右目が別々にレンダ
リングされる。
また、MultiView で書き込まれている SceneColor をポストプロセスで使えるよ
うに Resolve が走る。
Multi View Rendering
モバイルHDRのポストプロセスの処理を MultiView 化したもの。
単純に左目と右目の処理を足した負荷よりも低い。
また、MultiView で描かれた SceneColor をそのまま使えるので Resolve の
負荷も削減できる。
RHI Thread
通常 Render スレッドはコマンドバッファの作成とGPUへの転送まで
を行うが、コマンドバッファの転送処理を RHI スレッドに任せること
で Render スレッドの負荷を軽減できる。
描画ステップが増えることで Input Latency が増えるが、それぞれの
スレッドが規定時間内に処理を完了することで FPS を維持すること
ができる。
Frame 1 Frame 2 Frame 3 Frame 4 Frame 5
1/60 秒 1/60 秒 1/60 秒 1/60 秒 1/60 秒
Game Game
Render
Game
Render
RHI
Game
Render
RHI
GPU
Game
Render
RHI
GPU
UE4のスレッドの流れとInput Latency改善の仕組み https://www.slideshare.net/EpicGamesJapan/ue4input-latency
Significance Manager
Optimizing UE4 for Fortnite: Battle Royale - Part 1 | GDC 2018 | Unreal Engine - YouTube https://www.youtube.com/watch?v=KHWquMYtji0
The Significance Manager | Unreal Engine Documentation https://docs.unrealengine.com/en-US/Engine/Performance/SignificanceManager/index.html
距離や視野角などにより、各オブジェクトの重要性をリアルタイ
ムに定義し、Tick 処理や Visibility の切り替え等を行い、ゲーム性
を保ちつつ処理負荷を抑えることができる。
ガルガンチュアでは、武器・パーティクル・キャラクターのアニ
メーションなどをコントロールしている。
Update Rate Optimization (URO)
距離などにより、アニメーションの更新頻度やブレンド処理が
調整され、アニメーションにかかる CPU 負荷を下げることが可
能。
ガルガンチュアでの NPC の攻撃判定は、アニメーションによっ
て動いた武器の当たり判定を利用しており、URO の有効化によ
って攻撃が当たらなくなる等の不都合がある為、サーバー側で
は無効化している。
アニメーションの最適化 | Unreal Engine ドキュメント https://docs.unrealengine.com/ja/Engine/Animation/Optimization/index.html
Shader Pipeline Cache (PSO Caching)
シェーダーコードは GPU へ投入する前に、シェーダーバイナリ
へコンパイルする必要がある。OpenGL は実機でコンパイルす
る必要があるため、初めて使われるシェーダーは Render (RHI)
Thread でコンパイルが走り大きくヒッチを引き起こす。
ガルガンチュアでは PSO を利用し、動的にポップする武器やエ
フェクトのシェーダーをゲーム起動時に事前コンパイルするこ
とでシェーダーコンパイルの発生を抑制している。
PSO Caching | Unreal Engine Documentation https://docs.unrealengine.com/en-US/Engine/Rendering/PSOCaching/index.html
UE4 にはプラットフォーム固有のマテリアル品質の設定があり
、プラットフォーム毎にマテリアルの品質をオーバーライドする
ことができる。
しかし、ここで設定すると全てのマテリアルの品質が落ちてしま
うため、マテリアルエディタを拡張して “Mobile Fully Rough” と
いう設定を追加した。
これにより、モバイルでは基本的にラフネスの映り込みの負荷を
カットしつつ、キャラクター等の一部のマテリアルでは映り込み
を適用している。
マテリアル品質
テクスチャを使わない
フェイクシャドウの影色やリングマーカー等、形状がシンプルな物
はテクスチャを使わずに描くことで、ストールを発生させない。
オフラインレンダリング
ボスレベルの空は雲のメッシュが1つづつ配置してあり、雲だけ
でドローコールが100を超え非常に重かった。雲だけを配置し
たレベルで CubeMap にキャプチャし天球に貼ることで大幅にパ
フォーマンスを改善。
LDR ベースのポストプロセス
UE4 がサポートしているポストプロセスは HDR を前提としたリッ
チなポストプロセスとなっており、モバイルVR で利用するにはとて
も重い。
ガルガンチュアでは LDR ベースのポストプロセスを追加している。
実装しているポストプロセスは VR 酔い対策としての Vignette と画
面のフェード効果の Overlay Color のみ。
ガルガンチュアでは、シーンカラーをバックバッファへ直接書き込
んでいる為、Frame Buffer Fetch を利用してシーンカラーのコピー
を行わずにバックバッファへポストプロセス効果を適用している。
また、ポストプロセスでガンマスペースへの変換を行うため、Base
Pass でのガンマスペース変換を行わないように変更し、描画負荷を
緩和している。
LDRベースのライティング
モバイルで LDR を利用することにより、PC ↔ モバイル間での見
た目を統一するため、全てのレベルのライティングを見直し、ポ
ストプロセスを前提としないライティングを行った。
マテリアルとシェーダープログラム
UE4エディターで作成したマテリアルは ShaderCompiler というツ
ールで各プラットフォーム向けのシェーダープログラムにコンパイ
ルされる。
マテリアルインスタンスでシェーダーコンパイルが走るようなスイ
ッチを変更すると、元のマテリアルとは別のシェーダープログラム
としてコンパイルされる。
グラフィックスAPIのシェーダープログラムの切り替えは高コスト
(CPU)なので、シェーダープログラムの総数は少ないほうが良いが
、巨大なシェーダーは頂点・ピクセルあたりのコスト(GPU)が増え
てしまう。
出来る限りマテリアルは共有し、無駄にマテリアルインスタンスの
スイッチを変更しないことが望ましい。
マテリアルLOD
UE4のメッシュエディター上で、各LODにマテリアルを設定するこ
とができ、LODに合わせてマテリアルも簡略化したものを与えるこ
とが出来る。
一般的にメッシュのLODが上がれば、専有ピクセル数が減り、GPU
負荷も減るため積極的に利用はしていないが、ガルガンチュアでは
ボスのヒット判定のために、LOD0 では細かく分けたセクションに
物理マテリアルを設定し、LOD1以上に描画に必要なセクション分
けでマテリアルを設定している。
物理処理には LOD0 が使われるため、描画に LOD1 以上を使うこと
で、ドローコールを抑えつつ、物理マテリアルによるヒット処理を
行っている。
マテリアルLOD
マテリアルLOD
シェーダーのフロー制御
GPU は1つのシェーダープログラムを複数のスレッド(CPUのスレ
ッドとは別物)を束ねたワープ(ウェーブフロント)を利用し並列に計
算を行うため、ワープ内で別の経路をとるスレッドがある場合、両
方の分岐を実行し、不要な結果を捨てるという動作をとる。
if (x == 0) {
return func(0);
} else {
return func(1);
}
half i = 0;
if (x == 0) {
i = 0;
} else {
i = 1;
}
return func(i);
func の実行回数が減るため
こちらの方が速い
条件分岐は遅い?
遅くはない。CPUとは動作が違うので、条件分岐で最適化を行
おうとしても速くはならない。
clip(x);
...
早期にclip/discardしても
全てのスレッドが処理を完
了するまで待機する。
反響音・音の遮蔽
音響の立体感を演出するために、サウンドシステムは音の発生源
の位置からレイキャスト (Physics)を行い反響率や遮蔽率を計算
する。
このため、ワーストケースではオーディオコンポーネントからの
レイキャストの負荷により処理落ちが発生する。(足音とか)
ガルガンチュアでは、Wwise プラグインを改造し、Oculus Quest
では音の反響・遮蔽処理を切っている。また、それぞれのオブジ
ェクトの音を再生する必要のない場面では、明示的にオーディオ
ソースに停止処理を行いゲーム全体のサウンド周りの処理負荷を
抑えている。
新プロジェクト DoG での最適化
Bloom
SWORDS of GARGANTUA ではポストエフェクトを諦めていたが、や
っぱブルーム欲しいよねって事で色々試してみた。
ポストプロセスを MultiView 化
レンダリング設定を調整
シェーダーのサンプリングを簡略化
思いつきにより、左目を+, 右目を☓方向にサンプリングしてみた。
左右の View でサンプリング方向をずらすことにより、片眼あたりのサン
プリング数を半減できる。
両眼で見たときに大して違和感はなかった。
Bloom
全画面エフェクト
全画面のエフェクトはスクリーン全体にピクセルシェーダーが走
り、非常に重いため、ダメージを受けたときの血糊エフェクト等
は Oculus Quest で無効化していた。
DUELS of GARGANTUA では、Tonemap で全画面エフェクトを
適用することでシェーダー起動数を抑えている。
全画面エフェクト
Tonemap のみ
エフェクトを適用したTonemapと
同様のエフェクトを実装したPostprocess Material
利用したプロファイラー
ANDROID SDK/NDK に含まれるプロファイラ
Simpleperf
https://developer.android.com/ndk/guides/simpleperf
サンプリングプロファイラ。CPUのボトルネックを調査できる。
使うのはちょっと手間がかかる。
simpleperf_report_lib.py でレポートのカスタマイズもできる。
systrace
https://developer.android.com/studio/command-line/systrace
systrace, OSやアプリのスレッドスケジュールを調査できる。利
用も簡単。
SOCベンダー製プロファイラ
SnapDragon Profiler
https://developer.qualcomm.com/software/snapdragon-profiler
残念ながら、Oculus Quest ではまともに動作しなかったので使
っていない。
すごくシンプルなレベルでドローコールを減らせば、メトリクス
くらいはたまに取れる。
サードパーティプロファイラ
RenderDoc
プロファイラというより、グラフィックスデバッガ。
処理時間はあてにならない。
利用した感じ、頂点負荷は出ない。ピクセル負荷は高ければ処理
時間は大きくなる。
レンダリングの不具合調査には最強。
UE4プロファイラ
Stat StartFile / その他 stat 系
Development ビルドでしか使えない。コアが少なければ、stat
スレッドに引きずられて不正な処理時間が出る。
QUICK_SCOPE_CYCLE_COUNTER( STAT_EVENT_NAME )
マクロを使って、スコープ単位の stat 情報を追加できる。
CPU のボトルネックを探すのには有用。Test / Shipping でのプ
ロファイルには、Android や SoC ベンダーが提供しているプロ
ファイラを使う。
GPU Profile
ALLOW_PROFILEGPU_IN_TEST を付けてエンジンをビルドす
れば Test ビルドでも使える。
UE4プロファイラ
CSV Profile
Game Thread / Render Thread / GPU のフレーム処理時間が取れ
る。
どのスレッドがボトルネックなのかが分かる。 Test でも動く。
カスタマイズすれば RHI Thread もとれる。
Tracing Profile
タスク単位での systrace の様なものが取れる。
デフォルトだと Game Thread くらいしかとれないので、カスタ
マイズ必須。
Stat Hitches
閾値を超えてヒッチしたフレームの stat 情報が出力される。
ゲーム実行中に解像度を変更し、FPS が改善するようであれ
ばピクセル負荷。
改善しない場合は、CPU か頂点負荷、ドローコール過多が
ボトルネック。
ゲームをポーズして FPS が改善すれば Game Thread (CPU)
がボトルネック。
改善しない場合は、Render Thread (CPU)、ドローコール
(CPU/GPU)、頂点負荷 (GPU) がボトルネック。
簡易的なボトルネックの切り分け
まとめ
何でもかんでも Tick で処理せずイベントドリブンな
実装を意識する
不必要な処理 (Tick やドローコール) は止める
GPU負荷はドローコール毎の頂点数・ピクセル数に
比例する
ドローコールは CPU/GPU にオーバーヘッドがある
ため、少ないほど良い
GPUはメモリフェッチストールのレイテンシのイン
パクトがでかい
プロファイリングをちゃんとやる
プロファイリングは実機上でTestビルドで行う
グラフィックスの最適化はCPUと違って、速ければ良
い、省メモリなら良い、という訳にはいかず、パフォ
ーマンスとクオリティの面から最適化方法を模索する
必要がある。
Oculus Quest では、ハードウェアにより72FPSに固定
されているため、1/72 秒を贅沢に使って最大限のクオ
リティを出すことが目標となる。

More Related Content

What's hot

ヒストリア HelixCore(Perforce) 運用レギュレーションドキュメント
ヒストリア HelixCore(Perforce) 運用レギュレーションドキュメントヒストリア HelixCore(Perforce) 運用レギュレーションドキュメント
ヒストリア HelixCore(Perforce) 運用レギュレーションドキュメントhistoria_Inc
 
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動についてUE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動についてcom044
 
そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...
  そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...  そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...
そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...エピック・ゲームズ・ジャパン Epic Games Japan
 
UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~
UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~
UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~エピック・ゲームズ・ジャパン Epic Games Japan
 
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る! | UNREAL FEST EXTREME 2020 WINTER
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る!  | UNREAL FEST EXTREME 2020 WINTERUE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る!  | UNREAL FEST EXTREME 2020 WINTER
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る! | UNREAL FEST EXTREME 2020 WINTERエピック・ゲームズ・ジャパン Epic Games Japan
 
UE4 LODs for Optimization -Beginner-
UE4 LODs for Optimization -Beginner-UE4 LODs for Optimization -Beginner-
UE4 LODs for Optimization -Beginner-com044
 

What's hot (20)

猫でも分かる UE4のAnimation Blueprintの運用について
猫でも分かる UE4のAnimation Blueprintの運用について猫でも分かる UE4のAnimation Blueprintの運用について
猫でも分かる UE4のAnimation Blueprintの運用について
 
60fpsアクションを実現する秘訣を伝授 基礎編
60fpsアクションを実現する秘訣を伝授 基礎編60fpsアクションを実現する秘訣を伝授 基礎編
60fpsアクションを実現する秘訣を伝授 基礎編
 
UE4における大規模背景制作事例(コリジョン編)
UE4における大規模背景制作事例(コリジョン編) UE4における大規模背景制作事例(コリジョン編)
UE4における大規模背景制作事例(コリジョン編)
 
UE4 MultiPlayer Online Deep Dive 基礎編1 -Getting Started- (historia様ご講演) #UE4DD
UE4 MultiPlayer Online Deep Dive 基礎編1 -Getting Started-  (historia様ご講演) #UE4DDUE4 MultiPlayer Online Deep Dive 基礎編1 -Getting Started-  (historia様ご講演) #UE4DD
UE4 MultiPlayer Online Deep Dive 基礎編1 -Getting Started- (historia様ご講演) #UE4DD
 
UE4.25 Update - Unreal Insights -
UE4.25 Update - Unreal Insights -UE4.25 Update - Unreal Insights -
UE4.25 Update - Unreal Insights -
 
ヒストリア HelixCore(Perforce) 運用レギュレーションドキュメント
ヒストリア HelixCore(Perforce) 運用レギュレーションドキュメントヒストリア HelixCore(Perforce) 運用レギュレーションドキュメント
ヒストリア HelixCore(Perforce) 運用レギュレーションドキュメント
 
Fortniteを支える技術
Fortniteを支える技術Fortniteを支える技術
Fortniteを支える技術
 
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動についてUE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について
UE4プログラマー勉強会 in 大阪 -エンジンの内部挙動について
 
Mask Material only in Early Z-passの効果と仕組み
Mask Material only in Early Z-passの効果と仕組みMask Material only in Early Z-passの効果と仕組み
Mask Material only in Early Z-passの効果と仕組み
 
猫でも分かるUE4.22から入ったSubsystem
猫でも分かるUE4.22から入ったSubsystem 猫でも分かるUE4.22から入ったSubsystem
猫でも分かるUE4.22から入ったSubsystem
 
猫でも分かるUE4のポストプロセスを使った演出・絵作り
猫でも分かるUE4のポストプロセスを使った演出・絵作り猫でも分かるUE4のポストプロセスを使った演出・絵作り
猫でも分かるUE4のポストプロセスを使った演出・絵作り
 
そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...
  そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...  そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...
そう、UE4ならね。あなたのモバイルゲームをより快適にする沢山の冴えたやり方について Part 2 <Texture Streaming, メモリプロ...
 
UE4における大規模背景制作事例(データメンテナンス・大技設定編 )
UE4における大規模背景制作事例(データメンテナンス・大技設定編 )UE4における大規模背景制作事例(データメンテナンス・大技設定編 )
UE4における大規模背景制作事例(データメンテナンス・大技設定編 )
 
UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~
UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~
UE4のライティング解体新書~効果的なNPRのためにライティングの仕組みを理解しよう~
 
Nintendo Switch『OCTOPATH TRAVELER』はこうして作られた
Nintendo Switch『OCTOPATH TRAVELER』はこうして作られたNintendo Switch『OCTOPATH TRAVELER』はこうして作られた
Nintendo Switch『OCTOPATH TRAVELER』はこうして作られた
 
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る! | UNREAL FEST EXTREME 2020 WINTER
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る!  | UNREAL FEST EXTREME 2020 WINTERUE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る!  | UNREAL FEST EXTREME 2020 WINTER
UE4×Switchで60FPSの(ネットワーク)対戦アクションをなんとかして作る! | UNREAL FEST EXTREME 2020 WINTER
 
UE4におけるエフェクトの基本戦略事例 後半
UE4におけるエフェクトの基本戦略事例  後半UE4におけるエフェクトの基本戦略事例  後半
UE4におけるエフェクトの基本戦略事例 後半
 
Robo Recallで使われている 最新のVR開発テクニックをご紹介!
Robo Recallで使われている最新のVR開発テクニックをご紹介!Robo Recallで使われている最新のVR開発テクニックをご紹介!
Robo Recallで使われている 最新のVR開発テクニックをご紹介!
 
UE4におけるエフェクトの為のエンジン改造事例
UE4におけるエフェクトの為のエンジン改造事例UE4におけるエフェクトの為のエンジン改造事例
UE4におけるエフェクトの為のエンジン改造事例
 
UE4 LODs for Optimization -Beginner-
UE4 LODs for Optimization -Beginner-UE4 LODs for Optimization -Beginner-
UE4 LODs for Optimization -Beginner-
 

ガルガンチュア on Oculus Quest - 72FPSへの挑戦 -

Editor's Notes

  1. 前面のオブジェクトに完全に隠れているかを判断するには、ピクセル単位での判定が必要で、CPU では苦手な処理となり、GPU でカリング処理を行った結果を CPU が受け取るため、カリング処理自体のオーバーヘッドは高め。
  2. プリミティブアセンブリでプリミティブが構成された時点で、頂点レベルで深度値が計算されており、ラスタライザーにより各ピクセルの深度値に補完される。 この頂点の深度値を元に、早期深度テストが実行される。 ピクセルシェーダーで深度値の変更やピクセル破棄を行う場合、ピクセルシェーダーを実行しないと最終的な深度値が確定しないため、早期深度テストは機能しない。 テクスチャのアルファでマスクするような不透明シェーダーは、ピクセル破棄が行われている。
  3. プリミティブアセンブリでプリミティブが構成された時点で、頂点レベルで深度値が計算されており、ラスタライザーにより各ピクセルの深度値に補完される。 この頂点の深度値を元に、早期深度テストが実行される。 ピクセルシェーダーで深度値の変更やピクセル破棄を行う場合、ピクセルシェーダーを実行しないと最終的な深度値が確定しないため、早期深度テストは機能しない。 テクスチャのアルファでマスクするような不透明シェーダーは、ピクセル破棄が行われている。
  4. Z Pre Pass のレンダリングパスでは、ピクセルシェーダーを無効化し、頂点シェーダーのみで描画を行う。マスクされたメッシュも描く場合はピクセルシェーダーも実行する。 ガルガンチュアでは PC 版で利用している。 Oculus Quest 用のレンダラーに実装してみたところ、Z Pre Pass で増える負荷と、Base Pass で減る負荷がだいたい同じくらいだった。ワーストケースでは逆に重くなる場合も。 SoC ではバッファの書き込みや、ドローコールを減らす方が効果がありそう。
  5. Z Pre Pass のレンダリングパスでは、ピクセルシェーダーを無効化し、頂点シェーダーのみで描画を行う。マスクされたメッシュも描く場合はピクセルシェーダーも実行する。 ガルガンチュアでは PC 版で利用している。 Oculus Quest 用のレンダラーに実装してみたところ、Z Pre Pass で増える負荷と、Base Pass で減る負荷がだいたい同じくらいだった。ワーストケースでは逆に重くなる場合も。 SoC ではバッファの書き込みや、ドローコールを減らす方が効果がありそう。
  6. 過密度なモデルとは、頂点数に対するピクセル数の割合が極端に少ないもの。 多頂点のオブジェクトが遠方に大量にあるなど。 頂点シェーダーが頂点の座標変換を行い、プリミティブアセンブリで構築が完了したプリミティブからラスタライザーを通りピクセルシェーダーが実行されます。 頂点数に対してピクセル数が少ない場合、ラスタライザー・ピクセルシェーダーは、プリミティブアセンブリからのプリミティブを待っている時間が長くなりパフォーマンスが落ちる。 ピクセル未満のプリミティブが発生すると、1ピクセルに複数のプリミティブが割り当てられ、オーバードローが発生し、ピクセルシェーダーの処理にも無駄が発生する。 ピクセル単位でしか色を塗れないので、ピクセル未満のプリミティブは無駄でしかない。
  7. 過密度なモデルとは、頂点数に対するピクセル数の割合が極端に少ないもの。 多頂点のオブジェクトが遠方に大量にあるなど。 頂点シェーダーが頂点の座標変換を行い、プリミティブアセンブリで構築が完了したプリミティブからラスタライザーを通りピクセルシェーダーが実行されます。 頂点数に対してピクセル数が少ない場合、ラスタライザー・ピクセルシェーダーは、プリミティブアセンブリからのプリミティブを待っている時間が長くなりパフォーマンスが落ちる。 ピクセル未満のプリミティブが発生すると、1ピクセルに複数のプリミティブが割り当てられ、オーバードローが発生し、ピクセルシェーダーの処理にも無駄が発生する。 ピクセル単位でしか色を塗れないので、ピクセル未満のプリミティブは無駄でしかない。
  8. シーン内のシェーダーを1つづつ、単色の Emissive Color を出力するだけのシンプルな物に交換して FPS の改善を見ていく。 シーンの大部分で使われているコンクリートのシェーダーで変化が見られた為、コンクリートシェーダーの何がボトルネックなのか調査していく。
  9. 大理石のタイルシェーダー タイル内の模様(ディテール)を、タイル毎に向きを変えようとしている。 ディテールの向きを表すのは、赤青緑のテクスチャ。 定数定義された 4つの回転値で UV を回転させて、ディテールテクスチャをルックアップしたカラーを、ディテールの向きを表すテクスチャの値でブレンドしている。 ディテールの向きテクスチャ1回、ディテールテクスチャ4回で、合計5回のテクスチャルックアップが行われている。 4つの回転値を、ディテールの向きを表すテクスチャの値でブレンドした後に、ブレンドされた回転値で UV を回転させて、ディテールテクスチャをルックアップすることで、ディテールの向きテクスチャ1回、ディテールテクスチャ1回で、合計2回のテクスチャルックアップで同じ結果を得ることができる。
  10. 大理石のタイルシェーダー タイル内の模様(ディテール)を、タイル毎に向きを変えようとしている。 ディテールの向きを表すのは、赤青緑のテクスチャ。 定数定義された 4つの回転値で UV を回転させて、ディテールテクスチャをルックアップしたカラーを、ディテールの向きを表すテクスチャの値でブレンドしている。 ディテールの向きテクスチャ1回、ディテールテクスチャ4回で、合計5回のテクスチャルックアップが行われている。 4つの回転値を、ディテールの向きを表すテクスチャの値でブレンドした後に、ブレンドされた回転値で UV を回転させて、ディテールテクスチャをルックアップすることで、ディテールの向きテクスチャ1回、ディテールテクスチャ1回で、合計2回のテクスチャルックアップで同じ結果を得ることができる。
  11. 大理石のタイルシェーダー タイル内の模様(ディテール)を、タイル毎に向きを変えようとしている。 ディテールの向きを表すのは、赤青緑のテクスチャ。 定数定義された 4つの回転値で UV を回転させて、ディテールテクスチャをルックアップしたカラーを、ディテールの向きを表すテクスチャの値でブレンドしている。 ディテールの向きテクスチャ1回、ディテールテクスチャ4回で、合計5回のテクスチャルックアップが行われている。 4つの回転値を、ディテールの向きを表すテクスチャの値でブレンドした後に、ブレンドされた回転値で UV を回転させて、ディテールテクスチャをルックアップすることで、ディテールの向きテクスチャ1回、ディテールテクスチャ1回で、合計2回のテクスチャルックアップで同じ結果を得ることができる。
  12. 大理石のタイルシェーダー タイルパターンのテクスチャは、ディテールの向きを表すテクスチャをグレースケールにしたものと大差ない。 ディテールの向きを表すテクスチャは、ディテールカラーを計算する際にルックアップ済みのため、この値をグレースケール化して、タイルパターンとして扱うことでテクスチャルックアップを1回分減らすことができ、タイルパターンテクスチャそのものも不要となる。
  13. 模様の入り方は同じ。 タイルパターンは変わってしまったが、全体のイメージは同じ。
  14. ガルガンチュアのキャラクターには、発光する部分があり、その位置と色を表すためのテクスチャ(Emissive Map)が用意されている。 一般的に Diffuse Color に使われるテクスチャは RGB の3チャンネルしか使われていないが、テクスチャフォーマットとしては RGBA の4チャンネルを扱うことができ、A(アルファ)チャンネルが余っている状態。 この例では、Diffuse Color と Emmisive Map で使われる UV が同じ(テクスチャ内の位置関係が同じ)且つ Emmivie Color が単色であるため、Emmivie Map をグレースケール化(明るさ情報)に変換し、Diffuse Color のアルファチャンネルに統合することで、Emissive Map のテクスチャルックアップを削減。 マテリアルパラメーター(シェーダーパラメーター)として色を設定し、アルファチャンネルの明るさ情報と掛け算することで、ほぼ同等の見た目になる。
  15. ガルガンチュアのキャラクターには、発光する部分があり、その位置と色を表すためのテクスチャ(Emissive Map)が用意されている。 一般的に Diffuse Color に使われるテクスチャは RGB の3チャンネルしか使われていないが、テクスチャフォーマットとしては RGBA の4チャンネルを扱うことができ、A(アルファ)チャンネルが余っている状態。 この例では、Diffuse Color と Emmisive Map で使われる UV が同じ(テクスチャ内の位置関係が同じ)且つ Emmivie Color が単色であるため、Emmivie Map をグレースケール化(明るさ情報)に変換し、Diffuse Color のアルファチャンネルに統合することで、Emissive Map のテクスチャルックアップを削減。 マテリアルパラメーター(シェーダーパラメーター)として色を設定し、アルファチャンネルの明るさ情報と掛け算することで、ほぼ同等の見た目になる。
  16. 緑と赤の縦縞模様のテクスチャは、Gチャンネルしか利用されていない。 空いている Diffuse Color の Aチャンネルに統合した。 Metalness, Roughness (Smoothness), Specular, Ambient Occlusion といったディテールパラメータは、テクスチャを使わず定数化している。
  17. モデルのお腹側のポリゴンはカメラの方向を向いているが、背中側のポリゴンはカメラと反対方向(裏面)を向いている。 裏面プリミティブ(ポリゴン)は、ラスタライザー(プリミティブアセンブリ)で除去されピクセルシェーダーは走らないが、両面レンダリングを有効化(プリミティブアセンブリでのカリング OFF)した場合、背中側の裏面プリミティブもピクセルシェーダーが走ってしまう。同一ピクセルで背中側のシェーダーが先に実行された場合、背中側・お腹側で2回シェーダーが実行される。先にお腹側が実行された場合、背中側は深度テストでカットされる。どちらの面から描画するかを制御する方法はない。やるとすれば、両面レンダリングしたい部分のドローコールを分けるくらい。
  18. モデルのお腹側のポリゴンはカメラの方向を向いているが、背中側のポリゴンはカメラと反対方向(裏面)を向いている。 裏面プリミティブ(ポリゴン)は、ラスタライザー(プリミティブアセンブリ)で除去されピクセルシェーダーは走らないが、両面レンダリングを有効化(プリミティブアセンブリでのカリング OFF)した場合、背中側の裏面プリミティブもピクセルシェーダーが走ってしまう。同一ピクセルで背中側のシェーダーが先に実行された場合、背中側・お腹側で2回シェーダーが実行される。先にお腹側が実行された場合、背中側は深度テストでカットされる。どちらの面から描画するかを制御する方法はない。やるとすれば、両面レンダリングしたい部分のドローコールを分けるくらい。
  19. 改造は必要だが、開発時に実機でコンパイルしたシェーダーバイナリをパッケージに含め、コンパイル済みシェーダーバイナリをパッケージからロードするようなことも可能。
  20. 映り込みはリフレクションキャプチャーのキューブマップをフェッチする必要があり、テクスチャルックアップと同等に重い。
  21. 最近の SoC は、単純な演算性能はそこそこ高いため、数学的計算で描けるものはテクスチャを使うより軽い。 掴める物のリングマーカーも、元はテクスチャを利用したフリップブックアニメーションで実装されていたが、テクスチャを利用しない実装に修正している。
  22. ガンマ変換はディスプレイへ出力するために必ず必要となる変換処理。 エンジンの設定上ではポストプロセスは切っているため、出力されるシェーダーはガンマ変換処理が入っている。 この状態では、追加したポストプロセスで、デガンマ処理でリニアカラーに変換し、ポストプロセス効果をのせて、再度、ガンマスペースへ変換する必要がある。 シェーダーテンプレートのガンマ変換処理をカットすることで、無駄なガンマ / デガンマ処理を削っている。