60fpsアクションを実現する秘訣を伝授 解析編【UNREAL FEST EAST 2019】

143.3K Views

October 08, 19

スライド概要

講演動画:https://youtu.be/YXGmiWzHxeo
基礎編:https://www.docswell.com/s/EpicGamesJapan/53M7JK-UE4_UFE19_Soleil_60fpsAction_Basic

2019年10月6日に行われた「UNREAL FEST EAST 2019」における「60fpsアクションを実現する秘訣を伝授」の登壇資料です。
●公式サイト
https://unrealengine.jp/unrealfest/
===
発売中のタイトル「NARUTO TO BORUTO シノビストライカー」に開発中のプロジェクトの事例も加えて、60fpsアクションゲームを実現するためのポイントや、パフォーマンス・チューニングについて解説します。おまけとして「NARUTO TO BORUTO シノビストライカー」のグラフィック面の技術を紹介。

profile-image

Unreal Engineを開発・提供しているエピック ゲームズ ジャパンによる公式アカウントです。 勉強会や配信などで行った講演資料を公開しています。 公式サイトはこちら https://www.unrealengine.com/ja/

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

60fpsゲームのために 解析編 Winter Crown WORKS 梶井 祐 協力: ソレイユ株式会社 尾田 委久 協力: Winter Crown WORKS 石濃 潤一郎 #ue4fest

2.

梶井 祐 • IndieGame Studio WinterCrownWORKSのプログラマー。 主に分野はグラフィックスプログラム。 仕事では各会社様からパフォーマンス関連のご相談を承って おります。 WinterCrownWORKSのアーティスト石濃、プログラマー梶 井で、アーティストとプログラマー両方の視点から改善案、 サンプル提供、エンジン改造などを行っております。 ご相談の際には [email protected] までお気軽にご連絡ください。 #ue4fest

3.

はじめに • この解析編は基礎編でも触れた基本的な問題をクリアしてい る前提でのお話になります。 なので、「そんなところまで見るの?」と思う事もあるでし ょうが、より多くのものを画面に出しつつ、クオリティを出 そうと思うと必要になってきます。 • ここではより低レイヤーに近いところから解析、説明をして いきたいと思います。 #ue4fest

4.

目次 1.GraphicsをProfile 2. 軽量化、高速化に入る前に ...p7 ...p14 3.Maskedなマテリアル ...p17 4.BasePass 5.アセットについて 6.Translucency ...p69 ...p127 ...p179 7.PostProcessに関して ...p201 8.CPU軽量化、最適化 ...p214 9.オマケメモリに関して ...p267 10.総括 11.参考文献 ...p283 ...p289 #ue4fest

5.

テストに使ったPCの構成 • CPU i7-6700K 4GHz • グラフィックボード NVidia Geforce GTX 750 Ti • メモリ 64GB #ue4fest

6.

GraphicsをProfile #ue4fest

7.

ProfilingTool • コンソールは各コンソール専用のものがある。 • PC側も様々なものがあり、お手軽なものから低レイヤーの値 を見るものまで。 -PIX -RenderDoc -NSight -Radeon GPU Profiler …等々 #ue4fest

8.

Profilerで見ると何がいいの? • より詳細な情報が得られる(情報の精度、範囲はProfiler次第) - どんなデータがセットアップされたのか、シェーダース テージ間では何が受け渡されているのか? - 実際に描画されたポリゴン数は?ピクセル数は? - 計算が重いのか?テクスチャのアクセスか? #ue4fest

9.

この度使うProfilerはNSight 2019.5 • ダウンロードしてすぐ試せる。 • 低レイヤー部分の調査が出来る。(根拠のために必要) • NVIDIA様のドキュメントやBlogで多くの情報が得られる。 低レイヤーの情報も多く載っている。 • 【今人気のプラットフォーム】の解析に近 い感覚 #ue4fest

10.

NSight • NVIDIA 様のサイトより(翻訳): NVIDIA Nsight Graphicsは、グラフィックアプリケーション のデバッグとプロファイリングのためのスタンドアロンアプ リケーションです。 Nsightは、DirectCompute、Direct3D(11、12、DXR)、 OpenGL、Vulkan(1.1、NV Vulkan Raytracing Extension )、Oculus SDK、およびOpenVRで構築されたアプリケーシ ョンをサポートしています。 #ue4fest

11.

実行してキャプチャ → Profile結果 #ue4fest

12.

注意:管理者モードで実行にチェック • デフォルトの場合実行する際は常に管理者モードにしないと FrameCaptureが出来ない。 もしくは管理者以外にも カウンタを公開する。 #ue4fest

13.

軽量化、高速化に入る前に #ue4fest

14.

どんな問題がある? • • • • • Lightの置きすぎによるLighting負荷 広範囲に半透明を重ねすぎたOverDraw負荷 高解像度、テクスチャ枚数多すぎのマテリアル負荷 PostProcessによるフィルター負荷 草原、森の作り方によるMaskedMaterial負荷 等々・・・・。 #ue4fest

15.

ゲームエンジンを使用しても、なんでも お任せとはいかない・・・。 • 大前提として - デバイスの性能を上回る事はない - デバイスの影響は必ず受ける デバイスの性能を使い切るために Profileingを行い正確な情報を得る。 #ue4fest

16.

Maskedなマテリアル #ue4fest

17.

え?重いの? • 4.16で入ったMask Material only in Early Z-pass使ったら 軽くなるんじゃなかったっけ? 参考文献:Mask Material only in Early Z-passの効果と仕組 み • 抜きを使ったらポリゴン数少ないでしょ?軽いんじゃない の? #ue4fest

18.

整理しましょう。 • Mask Material only in Early Z-pass MaskedMaterialのBasePassの負荷は下がります。 が、 MaskedMaterialのすべてが解決する訳ではない。 • 板ポリの積極運用でポリゴンを減らす 抜きを使ってポリゴン数を減らして行っても、頂点数がボト ルネックのケースでない限りは効果は微妙 #ue4fest

19.

ポイント • Prepassの負荷 • ShadowDepthの負荷 • BasePassの負荷 Mask Material only in Early Z-pass で対処されるのはBasePassについて。 他の描画パスでは注意が必要。 #ue4fest

20.

Masked Material の実行 MaskMaterialOnly in Early Z pass未使用 • Prepass(Masked又は描画 しない) • BasePass(Masked) • ShadowDepth(Masked) MaskMaterialOnly in Early Z pass使用 • Prepass(Masked) • BasePass(Opaque) • ShadowDepth(Masked) #ue4fest

21.

BasePassはOpaqueだが他は・・・ • PrepassとShadowDepthにおいてはMaskedでレンダリング される。 つまりBasePass以外では依然としてMasked特有の制限を受 ける。 #ue4fest

22.

テストをしてみよう。 • 葉っぱ部分がMaskedMaterialで出来ています。 #ue4fest

23.

負荷の内訳 • Prepass 1.34ms • ShadowDepth 1.42ms • BasePass 2.31ms #ue4fest

24.

まずはPrepassを見てみる • 木の葉部分のみのDrawCallで 1.34msの内、1.06msも使わ れている。8割以上が葉っぱに使われている #ue4fest

25.

たかがこの程度の画面にしては重い • 60fpsは16.6ms その内1msがPrepassは妥当に見えますが、 画面の物量から見ると重すぎるように思える。 画面にもっとオブジェクトを載せたいのでもう ちょっと軽くしたいとか思いますよね? この際にやるべきことはポリゴンを削る事でしょうか? #ue4fest

26.

葉っぱ部分をProfile #ue4fest

27.

RangeInfo • DrawCall Count 1 Profileをかけた範囲で発生したDrawCallが1つ。 • API Primitive Total / Avg 投入されたポリゴン数の合計 / DrawCall辺りの平均 • Shaded Pixel Total / Avg ピクセルシェーダーの動作したフラグメント数 / DrawCall辺 りの平均 *PrepassでOpaqueマテリアルは 0 で計上される。(PDO を使ってない場合) #ue4fest

28.

PipeLineOverView • TOP SOL 各ワークロードの実行効率が最大理論値にどれだけ近いかの 割合 ここでは一番大きい値から5つ並べられます。 おおよその原因はこの辺りから順に割り出していきます。(各 ユニットは後述) #ue4fest

29.

GPU ユニット • • • • • • • • PD(Primitive Distribute) = インデックスバッファのロード VAF(頂点属性のフェッチ) = 頂点バッファの読み込み SM(ストリーミングマルチプロセッサ) = シェーダーの実行 FMA fp32(FADD,FMUL,FMAD) = 32bit浮動小数演算 ALU = 整数および論理演算 FP16 = 半精度の計算 SFU = 三角関数等(rsqrt,cos/sin ) TEX = SRV,UAVのフェッチ #ue4fest

30.

GPU ユニット • • • • • • VPC L2 CROP ZROP VRAM SOL = ViewPort変換、錐台カリング = L2キャッシュ = ColorRenderTargetへの書き込み、ブレンド = 深度ステンシルテストを行う = GPU Video Memory = Speed Of Light 理論値に対する達成率 #ue4fest

31.

SM Section • シェーダー実行に関する値になります。 この辺りは全部を解説しようとすると、複雑になり過ぎるた め、今回のボトルネックに関してだけ解説しようと思います。 SM Activeは100%に近い値が出ているため、ほぼ理論値が出 ている。 Stall部分が計上されているのが確認できる。 #ue4fest

32.

まず見るべき場所 • SOL TEX 100% , ZROP 42.9% , SM 21.9% , L2 20.8% TEXユニットへのアクセスが理論値最大で出ている。(テクス チャアクセスによって速度が制限されている可能性が高い) ZROPが高いのはPrepassは深度の構築なため深度に対する書 き込み、読み込みが多いため。 SMは若干低い気がする。 次にシェーダーの実行周りを見てみる #ue4fest

33.

SM Sectionを詳しく見てみる #ue4fest

34.

どう見る? • SM Active が100%に近いのにStall Long ScoreBoard が非 常に高い。 FS Invocations(ピクセルシェーダーの実行数)が非常に多 い。 #ue4fest

35.

MaskedMaterial おさらい • Prepass は Maskedのままでレンダリング - 抜きの計算のためにPixelShaderが走る 抜きのためのテクスチャアクセスも行われる。 - EarlyZが効かない 深度の裏に回ってもレンダリングされる。その上でピクセ ルシェーダーもテクスチャアクセスも行われるので尚負荷に #ue4fest

36.

α抜きの動作 • 流れ - 頂点シェーダー (画面に入っていた場合) Early Zを通り抜けピクセルシェーダーへ - ピクセルシェーダー OpacityMaskに繋がってるノードを計算。 αテストを通っていれば 深度テストへ(Late Z Test) - 深度テストを抜けた場合、DepthBufferへ出力 #ue4fest

37.

OpaqueMaterielの動作 • 流れ - 頂点シェーダー (画面に入っていた場合) 深度テスト(EarlyZ) - 深度テストを抜けた場合DepthBufferへ出力 ピクセルシェーダーは走らず、テクスチャアクセスも頂点で のフェッチまでしか発生しない。 #ue4fest

38.

EarlyZ(PreZ),LateZ(PostZ)に関して • ちょっとだけお話させて頂きます。 パイプライン上、深度テストのタイミングがより早い段階で 行われるものがEarlyZ。 深度テストがもっとも遅いタイミングで行われるものがLateZ になります。 尚、説明を簡略化するため、ReZの説明は省かせて頂きます。 #ue4fest

39.

描画パイプラインの深度テストの流れ 三角形 HiZ(階層Z/ステンシルテスト) EarlyZ(Z/ステンシルテスト) ピクセルシェーダー LateZ(Z/ステンシルテスト) カラーブレンド、出力 #ue4fest

40.

EarlyZ(PreZ) の深度テストの流れ • OpaqueMaterialがPrepass, Basepass,Shadowで行う 深度テストの流れです。 ピクセルシェーダー実行前に リジェクトできるので高速 三角形 HiZ(階層Z/ステンシルテスト) EarlyZ(Z/ステンシルテスト) ピクセルシェーダー カラーブレンド、出力 #ue4fest

41.

LateZ(PostZ) の深度テストの流れ • MaskedMaterialがPrepass時、 またはShadowDepth時に 行う深度テストの流れです。 ピクセルシェーダー実行後に リジェクトするので低速 三角形 HiZ(階層Z/ステンシルテスト) ピクセルシェーダー LateZ(Z/ステンシルテスト) カラーブレンド、出力 #ue4fest

42.

HiZって? • タイル単位に低精度で行う深度テスト 大雑把に大きい範囲で行うため、リジェクト自体は高速。 手前で大きい面積が深度でおおわれてるケースで効率的。 ハードウェアによってタイルのサイズは8x8,16x16等になる。 深度のビット幅も狭いので、本当に荒く深度テストを行う。 タイル分まるっと覆われてないといけない。 EarlyZ,LateZのどちらでも有効。 #ue4fest

43.

PrepassはMaskedの面積はそのまま負荷 に • 深度の裏に回った分もすべて負荷になる。 Maskedでレンダリングする際には、画面で見えてる以上に負 荷が高い という事に注意が必要。 今回の場合FS Invocationsが非常に多く、その上で TextureAccessも多い状態。 FS Invocationsはピクセルシェーダーが呼び出された数。 #ue4fest

44.

対処方法は? • 基本は面積を減らす事 裏に回っていてもピクセルシェーダーが走るため、重なる面 が多いほど負荷になる。 MaskedMaterialを減らす、頂点がボトルネックにならない程 度に抜きの形をとり重なる面積を減らす、面積を減らす為に LODを入れる、等が効果が出てくる。 *QuadOverDrawでは確認できないので注意 #ue4fest

45.

軽量化してみよう :少々変化球を用意し てみました。 • 実はLODモデルに仕込みがあり、Maskの領域が減っています。 #ue4fest

46.

モデルの構成: #ue4fest

47.

何をしたのか? LOD1からOpaqueのモデルが仕 込まれている 解説 • 中心に葉っぱの模様の球を Opaqueで入れる事で、葉っ ぱ部分を間引く。 こうする事でMaskの板の重 なりを大きく減らしつつ、 見た目のボリュームを維持。 #ue4fest

48.

計測してみる • Prepass が 1.34ms→0.83ms へ。 Mask部分に関して言えば0.55msと約半分に。 LODの分DrawCallは増えているものの軽量に。 #ue4fest

49.

MaskedMaterialそのものが軽くなった わけではないが・・・ • FS Invocationsが半分以下。 つまり単純に処理の総量が減っている。TEXが100%、Stall Long ScoreBardが高いのはMaskなので仕方ない。(Prepass全体では下がってる) #ue4fest

50.

Prepass まとめ • Mask Material only in early – Z-passを使っても注意が必要 • 重なる面積は最小に • 抜きの形状を綺麗にとるかどうかは配置数やシーン全体のポ リゴン数と相談 • 出来るだけ不必要なMaskを避ける 親マテリアルを意図せずMaskedMaterialで作っただけなんて いうケースも・・・。 #ue4fest

51.

実はShadowDepthも・・・ • ShadowDepthも同じようにMaskedMaterialの影響を強く受 けます。 基本的にはPrepassと同じような負荷の出方をします。 その上で、レンダリング先のバッファ解像度もカスケードの 影響が出てくるため注意が必要です。 Maskedとレンダリング解像度が原因のため細かい解説は飛ば しながら見て行きます。 #ue4fest

52.

LODなしのShadowDepth #ue4fest

53.

ShadowDepth 1.42ms 内訳 • 葉っぱ部分の合計が1ms #ue4fest

54.

ShadowDepth 1.42ms 内訳 • 床の部分もDynamicShadowを落としていた。 面積が広いため、合計が0.25msちょっとぐらい。 落としても見た目が変わらないなら積極的にオミット #ue4fest

55.

軽量化してみよう :Prepassの軽量化と 同じものです。 #ue4fest

56.

軽量版: 0.65ms • 何と半分以下!! #ue4fest

57.

葉っぱ部分の合計が0.45ms前後 • 葉っぱ部分だけを抽出しても半分になっている。(単純に書 き込む面積が減っただけですが) #ue4fest

58.

床はDynamicShadowを落とす先がない • 床部分はDynamicShadowを切りました。 影響する先がないため、切っても見た目が変わらないからで す。 その結果、各Cascadeからも床のDrawCallが消えました。 結果 0.25msの軽量化 #ue4fest

59.

解像度を2048→1024に落とす事でさら に半分の負荷に(見た目は変わる) • 0.30ms #ue4fest

60.

影の解像度は下げても良い? • Maskedの総面積がボトルネックになるという事は? 単純に影の解像度を下げても同じような効果を期待できそう です。 ただし解像度が下がった分、見た目を許容するのかは要確認 になります。 影がボケる、細かい影が消える等は向上する速度とのトレー ドオフ。 #ue4fest

61.

軽量化小ネタ:影モデルの利用 • 影モデル UE4のMeshComponentのRendering設定を調整する事で影 を落とすだけのComponentを配置することが出来ます。 #ue4fest

62.

影モデルを用意してどうするの? • 運用方法 - 影モデルとして配置するものはLODを1段下げる ポリゴン数を抑える効果、maskの場合は書き込みの総面積 の抑制効果による軽量化が出来ます。 - シルエットを合わせた別モデルを用意する。 こちらもMaskedの場合は総面積を減らせますし、シルエッ トを合わせる事でOpaqueMaterialで配置も出来るかも知れま せん。 #ue4fest

63.

ShadowDepthのまとめ • MaskedMaterialはDynamicShadowにも影響 重なる面積で負荷が非常にあがる • こちらもPrepass同様、無駄な書き込み面積を減らす事が重 要 • 解像度は要調整 BaseScalability.iniで各スケーラビリティごとに、 r.Shadow.MaxCSMResolution で解像度が設定されている。 タイトル側でiniファイルを作りスケーラビリティをタイトル の方針に合わせる。 #ue4fest

64.

MaskedMaterialのまとめ • Prepass と ShadowDepthで負荷に影響が出てくる。 重なる総面積に注意。 よく目にするBush(茂み)モデルはパッと見の見た目以上に重 なっているので、負荷が高い。 頂点をただ削られて総面積が変わらないデータを見る事があ りますが、広く重なる面積を減らす方が効果が高い事が多い。 FS Invocations 、Shaded Pixelの数が非常に大きい値になっ てないか確認を。 #ue4fest

65.

気づいたでしょうか? • 軽量化しようとするととっても手間がかかりますね? 軽量化、高速化には手間、コストがかかります。 「今時そこに手をかけるなんてナンセンス」なんて意見もあ る訳ですが、効果の高いやり方ほど手がかかります。 もちろん手間やコストをかけずに済ませられるならそれに越 した事はありません。 より良い知見があれば是非共有を‼ #ue4fest

66.

コストがかかるので • チームが何を求めているのかゴールをはっきりさせましょう。 手間のかかる事は後半には出来なくなります。 作業者も疲弊しているので、タスクを積んでも「無理」とおっしゃられ るか、雑な対応で戻ってくる事も往々にしてあります。 雑な仕事では効果は半減、クオリティにも影響します。 手間のかかる方法を実践する場合は、適応範囲を絞ったり、早々にスケ ジューリング、ワークフローを確立させる、作業者の確保等の戦略を立 てる必要があります。 *マネージメントの段階からの影響が大きい #ue4fest

67.

Maskedで気を付けるシチュエーション • 草原 • 森 • オブジェクトのカメラフェード これらのシチュエーションは負荷がかかる筆頭です。 もし大量に配置が必要な場合、なんらかの方法を確立したり コストをかけないとクオリティを下げる結果になりやすい。 *よく誤解がありますが、InstancingやFoliageを使っても ピクセルシェーダーの負荷は特別軽くなったりはしません。 #ue4fest

68.

Basepass #ue4fest

69.

ここからがNSIGHTの本領発揮です • ShadowDepthやPrepassは深度を書き込むだけの単純なパス なため、「NSightじゃなくてもいいじゃん」というものが多 かったです。 BasePassは非常に動作が複雑なため確認する価値が出てきま す。 時間やページの都合上かなり端折ってはいるのですが、出来 るだけ説明させて頂きます。 #ue4fest

70.

負荷のポイントが分かりづらい • BasePassはシェーダーの動作が複雑な動作をしやすい個所で す。 ノードの組み方自体複雑化するために、本当のボトルネック が隠れやすい。 あからさまなデータ以外はなかなか最適化が難しく、全体を 効率よくシェーダーが走るようにしないと、軽量化の差が出 てこないところも最適化が難しい部分になるかと思います。 #ue4fest

71.

負荷が重いケース 頂点シェーダー • 頂点シェーダーの負荷 - ポリゴン数の超過 - 頂点アトリビュートのデータサイズ 頂点座標やUV等のデータ。UE4だと主にUV部分や SkeletalMeshかStaticMeshかで可変する。 - シェーダーステージ間のデータサイズ カスタムUVで拡張、PixelShaderで使用される最大UVイン デックス(どういう事かは後述します) #ue4fest

72.

負荷が重いケース ピクセルシェーダー • ピクセルシェーダーの負荷 - 計算量が多い(ALU,FMA,FP16) - テクスチャアクセスが多い,大きいmipへのアクセス - 冗長なTexturFormatが使われている - RenderTargetのFormatが冗長 - PixelShaderの動く面積が広い - LateZの実行(PixelDepthOffset) - マイクロポリゴン、細長いポリゴンが多い #ue4fest

73.

サンプルシーン #ue4fest

74.

構成 • まず簡単なモデルデータのBasePassがどうNSightで解析で きるのか見てみます。 注目するデータ:消火栓モデル ポリゴン数 29,014 UVチャンネル 2 マテリアル:BC,Normal,MRの3枚 #ue4fest

75.

消火栓のマテリアル #ue4fest

76.

キャプチャしてみる。消火栓で0.179ms #ue4fest

77.

概要を見る #ue4fest

78.

TOP SOL • TEX が56.5%,SMも56.1% 上位のSOLが50%~60%、大変非効率に実行が行われている。 少なくともTextureアクセスによる制限は受けていそう。 CROPも40%と非効率な値になっているが、これは DeferredRenderingで出力先のGBUFFERが多いため仕方な いと思われる。 #ue4fest

79.

SM Sectionの詳細 #ue4fest

80.

値をそれぞれ検討してみる。 • SM Activeの割合が若干低い SM Occpancyも低く、シェーダーの実行効率が悪そう。 • Long ScoreBoardが高い L1の命令キュー待ちが多いほど高くなる。 (SM Occpancyが低くなってる原因ではないか?) • FS Invocationの値を見ると実行されているスレッド数が多い マイクロポリゴンが発生していないか? #ue4fest

81.

ちょっとユニットの補足 • L1 Cache Vertexのフェッチ、次のシェーダーステージへのアウトプッ ト、Textureのフェッチ時等でアクセスされる。 • L2 Cache L1でフェッチにミスするとアクセスが発生。 メモリアクセス時に頻繁にアクセスされる。 #ue4fest

82.

マイクロポリゴンについて • 表示面積が極小なポリゴン ROPユニットの都合上、1ピクセルのポリゴンや細長いポリゴ ンは効率が非常に悪い。 半ピクセルの面積もない場合 頂点をフェッチ→Viewport変換→カリング計算→ポリゴン化 できずにReject ただ無駄なだけの計算が発生する。 #ue4fest

83.

ポリゴンからピクセルが出力される例 • 一番左が3ピクセルが画面に出力、真ん中と右のケースはポリ ゴンが出来ない。 #ue4fest

84.

OverDrawも発生する。 • Opaqueにも関わらず3,4回もOverDrawされている個所があ る。 恐らく画面にOutPut出来ていないポリゴンもある。 #ue4fest

85.

PixelShaderの最小実行は2x2,8スレッド 分同時処理 • PixelShaderの最小実行単位は2x2のQuad単位になります。 32ピクセル分のスレッドをバッチ処理して出力する 。 つまりQuad以下であったり、細長いポリゴン、例えば【横に 11ピクセル分の直線に近いポリゴン】などは実行効率が悪い 状態です。 ポリゴン数が少ないものでもLODを作った方が良いのは、出 来る限りマイクロポリゴンを作らないようにするため。 #ue4fest

86.

とはいえコントロールは難しいですよね • 完全に最適にすることはできません。 配置場所、シチュエーションに応じて適切な作りにする、 LODを用意する、適切な場所で切り替える、ポリゴンの割方 を綺麗にする等を行う。 完全に遠景にしか置かないと分かっているものは遠景用のも のを作るべきかどうかも検討材料です。 #ue4fest

87.

まとめると • テクスチャアクセス より小さいmipアクセスにする。 1回のサンプリングで出来るだけ情報を拾えるように各チャン ネルにマージする。 *アトラス化の事では無い事に注意‼よく勘違いされる事が あります • マイクロポリゴンを削る 見た目が変わらない程度であっても、ピクセルシェーダーの 実行数が減るため、頂点負荷以外も軽くなります。 結果的に同じ面積でメモリアクセスも減る。 #ue4fest

88.

で、軽量化をしてみた #ue4fest

89.

マテリアルの軽量化 • RG:NormalMap+B:Metallic+A:Roughnessでテクスチャを パックすることでサンプリングを一回減らしました。 TextureはLinerTexture #ue4fest

90.

オマケ:UnPackNormalのコード CustomShaderノードの中身です。これ自体はunreal内で宣言されているコードとほぼ同一のもの になります。 MaterialFloat2 NormalXY = vRG.rg; NormalXY = NormalXY * MaterialFloat2(2.0f,2.0f) - MaterialFloat2(1.0f,1.0f); MaterialFloat NormalZ = sqrt( saturate( 1.0f - dot( NormalXY, NormalXY ) ) ); return MaterialFloat4( NormalXY.xy, NormalZ, 1.0f ); #ue4fest

91.

LODで細かいポリゴンを削る。 LOD 0 LOD 1 #ue4fest

92.

OverDrawの比較 LOD0 LOD1 #ue4fest

93.

解析してみる。 • 0.03ms~0.04msの速度向上が見られる。 単なるノイズかも知れないので、さらにProfileをかけてみる 事に。 #ue4fest

94.

TOP SOLの順位が変わっている • 以前のTOP SOL は TEX が56.5%,SMが56.1% #ue4fest

95.

さらに詳しく #ue4fest

96.

考察 • Long Scoreboard 、Tex Throttle 共に下がっている。 テクスチャアクセスを減らしたことでL1の待機が減ったと思 われる。(TEXのSOLも下がっている事が確認できた) • FS Invocationが下がっている。 見た目の面積は一緒だが、マイクロポリゴンやOverDrawが 減った事により、ピクセルシェーダーの実行が減っている。 • SM Active Min/Maxも少し上がっている 多少シェーダーユニットの並列性が上がったものと思われる。 #ue4fest

97.

まだ効率は悪いが・・・ • TEX,CROPが中途半端で気になる割合。 Textureのアクセス枚数は減らしたものの効率が悪い。 2048x2048のテクスチャで、カメラ近くで映っているので 大きいmipアクセスが発生しているように思われる。 CROPはレンダーターゲットへの出力。 DeferredだとGBUFFERが多くどうしてもネックになる。 #ue4fest

98.

CROPの軽量化 • CROPが気になる割合。 SceneRenderTargetのフォーマットを下げる、Sceneの解像 度を下げる、出力バッファ枚数を減らす。 今回のシーンのフォーマットは既にR11G11B10Float。 GBUFFERの枚数を減らす事に関しては、Forwardにする以外 のやり方だとエンジンを改造しないといけない。 Forwardにしたとして、テクスチャアクセスとLightingの分 の計算がBasePass内で増える。効率の意味では効果はいまい ち #ue4fest

99.

TEXの軽量化 • できるだけ低いmipへのアクセス 必要がなければTextureの解像度を下げる • 単色やグラデーションだけのテクスチャはパラメーターに置 き換える • TextureFilterを必要最小限に Anisotropyを低いレベルに指定する等でもう少し改善は出来 ると思われます。 #ue4fest

100.

負荷のかかりやすい場所 • 実際のデータで想定すると もっと複雑にブレンドしたりアクセスするテクスチャ枚数が 多かったり、不必要に大きい解像度のテクスチャ という事 が多いと思います。 細かい計算よりはメモリアクセスの方がボトルネックのケー スは多く、メモリアクセスの遅延により計算、instructionを 隠蔽できるケースが多い。 計算が負荷として問題になるのはVoronoiNoiseのような極端 なinstruction数が増えるケース。 #ue4fest

101.

オマケ:Imposter Baker • 最近、結構誤解がある と感じたので軽くImposter Bakerに 触れておきます。 こちらはモデルを多方面からキャプチャした画像を使い、視 点方向に合わせたテクスチャを選択し、補間を行い、板ポリ でモデルを表現するような手法になります。 #ue4fest

102.

板ポリなら当然軽いでしょ #ue4fest

103.

・・・本当にそうですか? #ue4fest

104.

軽いかどうかはケース・バイ・ケース • こんなシーンを作ってみました。 左がモデル、右がimposter Bakerで作成した板ポリです。 #ue4fest

105.

まずはRendering時間の比較 Imposter Prepass+BasePass=0.047ms Model Prepass+BasePass=0.022ms #ue4fest

106.

画像が見づらかったのでもう一度 • #ue4fest

107.

意外でしたでしょうか? #ue4fest

108.

Imposter : 概要 #ue4fest

109.

Imposter : 詳細 #ue4fest

110.

Model : 概要 #ue4fest

111.

Model:詳細 #ue4fest

112.

一見するとImposterの方が効率良さそう に見えるが・・・ • TOP SOLのTEXの割合はImposterの方が高い そしてL2のHitRate 、SOLがImposterの方が低い。 角度補間のために同じテクスチャへのサンプリングが多く、 キャッシュミスが多いためと思われる。 • ShortScoreBoardがImposterの方がかなり高い。 恐らくUVを求めるための計算が非常に長い。 • FS InvocationsもImposterの方が高い。 つまり上記二点のボトルネックがあるにも関わらずピクセル シェーダーの実行数も多い #ue4fest

113.

今回使ったImposterはSamplers5,TextureLookUpsが 24 とかなり多い。 #ue4fest

114.

Model側:Samplerは5,Texture Lookups は2、Instructionsも少ない。 #ue4fest

115.

表示面積の違い #ue4fest

116.

Imposterを使う事が有効なケース • 頂点がシーンのボトルネックのケース • 表示領域が十分に小さい事,見る方向を変化させてもできるだ け一定の大きさである事。 • 用途に合わせてマテリアルも最適化した方が良い。 PixelDepthOffsetの使用を最低限にしたり、ライティングの 有無。 #ue4fest

117.

まだちょっとネタがあります #ue4fest

118.

頂点Attribute • ポリゴン数が多い場合に、よりネックになってくる部分です。 頂点アトリビュートは頂点の入力属性。 UE4のStaticMeshにおいてはInstancingとUVに気を付ける事 になります。 SkeletalMeshはそもそもアトリビュートが多いため、ポリゴ ン数の負荷がロースペック環境だと、比較的高くなりやすい です。 *対応方法はUVチャンネル数を抑えるぐらいしか出来ないた め割愛します。 #ue4fest

119.

シェーダーステージ間のデータ • 主に VertexShader → PixelShader で受け渡されるデータ このサイズが大きいとシェーダーの実行効率が落ちます。 PSが起動する際、このデータを読み取り終える必要があるた めです。 こちらは、PS内で使うUVが多い場合(CustomUVでの拡張も 含む)、Vertex InterpolaterノードでPixelShaderへデータを 受け渡した場合にサイズが増えます。 #ue4fest

120.

拡張前のマテリアル:VSの出力 #ue4fest

121.

CustomUVでUVを拡張する • UV7にUV0を出力して、PSでUV7でテクスチャサンプリング を行います。 #ue4fest

122.

使用するレジスタ数が増えました。 • 尚、CustomUVを使わなくてもTextureCood に入れた最大 の大きさのindexでoutputは拡張される #ue4fest

123.

で、BasePassが重い原因って? TextureAccess マイクロポリゴン RenderTargetのフォーマット ポリゴン数が多いケースで、VS to PSのoutputParamaterの サイズ。 • 極端に多いポリゴン数 • PixelDepthOffset (UE4においてはBasePassでもHizが効く LateZの実行という感じ) 等々・・・・。 • • • • #ue4fest

124.

原因が多すぎない? • 組み合わせもありますし、非常に多いです。 そして、基本的なものが守られた上での状態であれば、対処 をしても一個一個に対する効果は薄く、塵を積もらせていく ことになりやすいです。 ゲームによっては多少の負荷は目をつぶっても良いと思いま す。 しかし60fpsのゲームにおいては0.5ms捻りだすだけで軽めの PostProcess1個分捻出できたりするので、必要があるケース というのはあります・・・・。 #ue4fest

125.

シーンのポリゴン数を気にする • シーン内のインスタンスが多いオブジェクト その上でOcclusionに引っかかりづらい位置のもの • Instancing系の機能 • 大きいサイズのモデル(BoundingBoxの大きいもの) • 極端にポリゴン数が多いモデル。(数十万など) これらには十分注意が必要です。 カリング効率が悪いオブジェクト達が増えるとポリゴン数がボ トルネックになる事はおおいにあり得ます。 #ue4fest

126.

アセットについて #ue4fest

127.

概要 • ここまでで通常使われるようなモデルが関係するPrePass、 Shadow Depth,BasePassを扱ってきました。 ここからアセットに注目した話をしていきたいと思います。 #ue4fest

128.

負荷の原因はアセットにあり? • アセットはそこにあるだけで負荷になります。 一つ一つは大した負荷ではなくてもチリツモで取返しのつか ない事態に 開発終盤で追加したい項目があっても負荷が高ければ諦める 事にも →ゲーム要件の減少 #ue4fest

129.

アセットを調べよう • 専門のスタッフ(グラフィックスプログラマー)がいるなら 協力を仰ぎましょう。 よほど専門的な知識が無ければゲームデザイナー、アーティ ストだけでは調査しきれません。 ユースケースだけに頼らないように、調査し根拠を詰めます。 #ue4fest

130.

LODを設定しましょう • 近景に物が置かれた状況でLODが必要ないケースは稀ですの で、必ず導入を検討しましょう。 基本的なことですが、アセットの数が何百何千個とふえてく ると確認がおろそかになります。 ステージに配置した数万個のアクターがLODモデルに切り替 わらないというケースを見かけた事もあります。 意図した動作をしているか確認を‼ #ue4fest

131.

LODの状況を確認しましょう • 実際の画面で適切 に切り替わってる か確認しましょう。 #ue4fest

132.

崩れにくい形状 #ue4fest

133.

崩れやすい形状 #ue4fest

134.

ジャンルの影響を受ける • SFや現代劇は角ばった構造物が多く軽量化しにくい。 ファンタジーや自然を取り扱ったものは流線型が多く軽量化 しやすい。 扱うジャンルによってリダクションの難易度に差がでてきま す。 *角ばったものはシェーディンググループが切れやすく、見 た目より頂点が多かったり、Primitiveが非効率になりやすい。 #ue4fest

135.

マテリアル • メタリック、ラフネスは省略しやすい(パラメーターで済む ケースが多い) #ue4fest

136.

テクスチャストリーミング • 3Dゲームの場合カメラが不用意に近づくことがあります。 その際、巨大なテクスチャにアクセスされ負荷になっても困 るので最大サイズは必要最小限にしておきましょう。 #ue4fest

137.

テクスチャサイズ • UE4上でデータごとに設定していると管理が煩雑になるので テクスチャの割り当てサイズはアセットの形状、サイズから 適切にルール化しましょう。 2K,4Kのテクスチャは(PSDも含むと)サーバー容量を圧迫し、 作業コストを増大させます。 開発終盤でサーバー容量が不足する経験をしている人はそこ そこいるのではないでしょうか? #ue4fest

138.

テクスチャ 最大サイズはどうする? 1Mのボックスに岩のマテリアルを適用 当たり前ですが左の方がディティールが出ていて綺麗 サイズ2048 サイズ512 #ue4fest

139.

テクスチャ 最大サイズはどうする? サイズ2048 サイズ512 #ue4fest

140.

テクスチャ 最大サイズはどうする? 前画像をアップ ミップマップがかかりほぼ同じ見た目に サイズ2048 サイズ512 #ue4fest

141.

テクスチャ 最大サイズはどうする? サイズ2048 サイズ512 #ue4fest

142.

テクスチャ 最大サイズはどうする? 前画像をアップ 右がややシャープに? サイズ2048 サイズ512 #ue4fest

143.

テクスチャ 最大サイズはどうする? • 登録されたテクスチャサイズが大きいとユーザーの操作によ りイレギュラーでカメラの目の前に写ってしまい大きなサイ ズで読み込まれて想定外の負荷に。 客観視点のゲームではカメラがキャラクターの背後にありま す。 通常のゲームプレイに則った距離感を想定しておくとテクス チャの適切なサイズが割り出しやすくなります。 #ue4fest

144.

ヒートマップに沿ったリソースの割り振 り #ue4fest

145.

アセットのサイズや分割、まとめ • アセットは大きすぎても、細かすぎてもいけないものになり ます。 ここからはまとめ方に注力してお話させて頂きます。 もちろんこちらも、前ページのヒートマップに沿ったリソー スの割り振りが重要になります。 #ue4fest

146.

広さ 狭い方がコントロールしやすいが・・・。 #ue4fest

147.

視点 トップビュー 画面に収まる情報量(リソース)をコント ロールしやすい #ue4fest

148.

視点 プラットフォーマー いわゆる横スクロール こちらもリソースコントロールはしやすい #ue4fest

149.

視点 3D 3D視点は遠くまで見渡せる ユーザーの視点を制御しにくく、他視点よ りもリソース管理が難しい #ue4fest

150.

オブジェクトの属性 静的か? →まとめやすい 破壊オブジェクト(動的か?) →まとめにくい まとめるか否か #ue4fest

151.

まとめたいケース • DrawCallが多すぎる、OcclusionCullingやトラバースが負 荷になってしまう。 まとめる事でテクスチャアクセスが増えたり、1モデルの Primitive数が増えたり、マテリアルが冗長なものになってし まう事には注意が必要です。 配置が細かすぎる時にはOcclusionCullingがCPU側のボトル ネックになる事もあるので、まとめる事も、細かくすること も程々に。 #ue4fest

152.

カリングとアセットサイズとアクター数 • カリングを考慮してアセットのサイズを決める時何を考える でしょうか? アセットが大きい→カリング効率は下がるがアクター数は減 少 →GPUを圧迫しやすい アセットが小さい→カリング効率は上がるがアクター数や DrawCallは増加。 →CPUとメモリにしわ寄せが。 #ue4fest

153.

GPU,CPU,メモリ • どれか一つ破綻してもゲーム開発は苦しくなります。 負荷ができるだけ偏らないように分散を。 #ue4fest

154.

簡単なカリング例! 背景アセット 背景アセット 椅子は一つ一つ分けておけば、カ リング処理で片方は弾く事ができ そうです。 カメラ キャラクター ゲーム画面 この椅子は描画せずに済む #ue4fest

155.

簡単なカリング例? 全体を俯瞰 ではこう配置されたら? ある程度はまとめていいのかも #ue4fest

156.

適切なアセットサイズ まとめと分割 • どう分けるか、どうまとめれば効率的なのか? 販売ターゲットによってはある程度の負荷は許容できるかも 知れません。 時間が取れずに作業効率を優先するかも知れません。 どうしても大事な場面のため時間をかけて最適化する必要が あったり。 条件が多すぎるためケースバイケースになります。 #ue4fest

157.

適切なアセットサイズ まとめと分割 別な例で考えましょう この場合はどう分けた方がよいでしょうか? #ue4fest

158.

適切なアセットサイズ まとめと分割 天井は視界に入りにくいので別アセットに分けるとカリング効果が高い 横から #ue4fest

159.

適切なアセットサイズ まとめと分割 俯瞰 床はどこを向いても視界に入ってくるので切りに くい 左右の壁は視界によってはカリングできるので切 りやすいです。 カメラの視界を大雑把に考慮すると・・・ カメラ #ue4fest

160.

適切なアセットサイズ まとめと分割 俯瞰 岩壁はこれぐらいには分割したい #ue4fest

161.

適切なアセットサイズ まとめと分割 #ue4fest

162.

分割はすでにしてあるが・・・ • これだけ分割してあればカリング効率は最高です。 では細かくしておけば問題ないのでしょうか? この部屋だけでゲームが完結するなら問題ないかも知れませ ん。 ではもっとたくさんの部屋で1ステージが構成されていた場合 は? #ue4fest

163.

1ステージの構成 通常のレベルデザインでは複数の空間からステージを構成 することになるでしょう。 アセットの数も要素とともに増えていきます。 アクター数と描画負荷、メモリ 上記要件の決定にはゲーム要件に照らし合わせながらバラ ンスを取る事が求められます。 #ue4fest

164.

最適化の影響と効果 • ゲーム企画→最適なデータ構成を決定していく過程で データの構成をめぐってグラフィック担当に影響します。 設計に跳ね返るとプランナーにまで影響が及びます。 最適化を最後にエンジニアに任せればいいと考えていると余 計なコストを支払うことになります。 →処理落ちの原因の多くは設計→アセットにあるため #ue4fest

165.

最適化の影響と効果 • つまり、最適化の効果は・・・・ エンジニアだけが対応 → 効果小 グラフィッカーも協力 → 設計段階から考慮 効果中 → 効果大 #ue4fest

166.

ゲーム設計は出来るだけ早めに • プランナーやゲームデザイナーは最適化まで考慮する必要は ありませんが設計は早めに固めましょう。 設計が早く固まればアーティスト、プログラマーがゲーム内 容を損ねないような最適化の着手を早いタイミングで行えま す。 設計待ちの状態が続くと作業者は作業効率を優先してアセッ トを整理しません。できません。 結果、アセットが重い状態で放置され続けます。 #ue4fest

167.

選択肢を絞るために • 植物や動物は生きるのに適正な環境下にいます。 家など建築物は手に入る資材で作られます。(もしかしたら 他国からの輸入などかも知れません) 地震が起きやすい地域では、壊れる前提の家で立て直しやす い安価な作りをする文化があったり逆に壊れないように作る 文化があったりします。 つまり世界観を詳細に設定できると、制作物を絞る事ができ ます。 #ue4fest

168.

現実に即するかどうかはあまり関係ない • 現実が全く参考にならないようなものを考えた場合 現実に手に入る資料以上の資料を用意しないと選択肢が無限 になってしまうので注意が必要です。(作業者側で絞るのは 大変) #ue4fest

169.

ちなみにアセット使いまわしを許容する と・・・ 壁の外側から撮影 岩アセットをコピペして壁を構成 しているので裏にも頂点がありま す。 岩の隣接個所の重複も合わせて無 駄な処理です。 アクター数も多い。 作業効率、カリング効率が高い一 方で犠牲にしている部分もあるの です。 #ue4fest

170.

まとめかた • アクターマージは非可逆です。 データとしては精度が落ちる(編集がしにくくなる)のでfix までいかないのであれば、DCCツール上で行った方が後々取 り回しが楽になります。 あまりプロジェクトの早い段階ではお勧めできません。 #ue4fest

171.

まとめるデメリット バラバラなアセット マージしたアセット まとめることで配置パターンが減り見た目 のバリエーションを用意しにくくなります。 バリエーションを用意すると同じような見 た目のデータが複数登録され容量を圧迫し ていきます。 左はバラバラに配置しやすい 右は同じパターン #ue4fest

172.

遠景アセットの分割 「ビークルゲーム」を例に 真ん中が移動可能なフィールド 外側は遠景用アセットです。 この場合、視界に入ってこないポリゴンもGPU上で カリングされるため非効率です。 もし、遠景が頂点過多でカリングしたい場合、どの ように分割するべきでしょうか? #ue4fest

173.

例えば:遠景アセットの分割 ビークルゲームを俯瞰 放射状に分割するとカリング効率が高くなります。 遠景なので大雑把に分けられるだけで良いと思います。 #ue4fest

174.

遠景にもLODは必要? 荒い作り 遠景は移動によるスクリーンサイズに差が出にくい →切り替わることが少ない →LODは不要なことが多い 細かい作り そもそも遠いものは荒く、近くのものはそれなりの精度 でつくっているはず はず! #ue4fest

175.

アクションゲームの軽量化は難しい • 敵が多く出現し、破壊表現もある3D視点のアクションゲーム は色んな意味で制作難易度が高い 同時に起こるインタラクティブな要素が多くユーザーの自由 度も高いため他ジャンルよりもボトルネックになる個所も多 い #ue4fest

176.

すべてを作り込む? • キーになる場所を設定できればその周辺だけを作り込めばい いので作業量を抑えられます。 →導線の整理、視線の誘導を利用するとユーザーをある程度 制御 →設計、グラフィック担当との協力が不可欠 #ue4fest

177.

イレギュラーをどこまで許容する? • ステージの端から見ると重くなりやすい • アセットに必要以上に近づく • ありえないくらいに敵を生成 開発においてはイレギュラーとして除外するラインを決めて おく。 おおよそ主要なプレイにのっとった視点でのチェックを行う ことで、無駄の無い軽量化の調査が可能 #ue4fest

178.

Translucency #ue4fest

179.

恐らく皆様お悩みの事と思われます • エフェクトはピクセルのレンダリング数が多くなりやすい。 - 半透明は重複で描き込みが行われる - 目立つエフェクトは表示面積も大きい - 発注されるエフェクト数も多い 作業コストを減らした作りは、相対的に重いエフェクトに なりがち。 逆に言えば、実行コストを下げるためには試行錯誤や丁寧 な仕事が必要なため時間がかかる。 (時間があっても雑に対応される事も・・・) #ue4fest

180.

問題の大きい部分はまずOverDraw • ただParticleを放出してしまうと、OverDrawが非常に大きく なってしまいます。 OverDrawが問題になる際、削る話をするとクオリティを下 げる話をしているかのように受け取られる事があります。 OverDrawすることが本当に高品質の道なのでしょうか? #ue4fest

181.

OverDrawを減らしたらクオリティは下 がる? • 作成済みのものから、ただパーティクル数を減らした場合は そうなるかも知れませんが、ただし、重ねただけのものでク オリティと呼んでいいのでしょうか? • OverDrawの原因は正しく解析できているでしょうか? テクスチャの作りに無駄は? • 重なった分の効果がちゃんと出ているのか? #ue4fest

182.

OverDrawを最小限にするために • 抜きの面積が大きいとパーティクルに無駄な面積が発生しや すい。 #ue4fest

183.

テクスチャはキャンバスのぎりぎりまで 使う。 • 余白はなるべく少なく • 明るさをはっきりとさせる。 • パーティクルのαに1.0以上を入力 概ねテクスチャと乗算することになるので、開始が1.0未満だ と想定より薄く出る。 #ue4fest

184.

許容できるビルボードの重なりかた #ue4fest

185.

OverDrawしても見た目が変わらない例 そこまで変わらないように見えますが 左はOverDrawに。薄いものを重ね ても見た目の効果が出てこない。 #ue4fest

186.

CutOutは? • 積極的に使いましょう。 ただし、これだけで十分な速度が得られる事は少ないと思い ます。 特に日本のゲームスタイルではCutOutの機能を使った上で OverDrawが多い。 #ue4fest

187.

OverDrawを減らすトリック #ue4fest

188.

OverDrawを減らす為に • ビルボードのマテリアルを複雑に 半透明の場合、出力するピクセル数の方が問題になる。 このケースではマテリアルは冗長になりますが、1枚の板で複 雑なアニメーションをする事でOverDrawを減らしています。 #ue4fest

189.

使ったマテリアル #ue4fest

190.

マテリアル自体は重そうでも • 比較 Particle側 = 0.46ms 板で作成した煙 = 0.06ms と圧勝でした。 マテリアル単体の負荷は増えても、一枚の板を十分な情報量 にする事でビルボードの数を減らし、結果的に負荷を減らす 事ができました。。 ここでのトレードオフは見た目ではなく手間です。 #ue4fest

191.

そのエフェクトにLighting必要? • ShadingModelにDefaultLitが設定されてる 1枚1枚のビルボードの表示面積分ライティング計算をしてし まいます。 煙などのエフェクトでは欲しいかも知れません。 しかし炎などの加算エフェクトの場合では、見た目的に要ら ない事も多いのではないかと思います。 #ue4fest

192.

不要な場合には? • ShadingModelにunlitを設定する。 そのマテリアルではライティングは行われなくなります。 ライティングの効果を受けるべきかどうか? 適切に判断することで見た目をあまり変えずに軽量化が行え るという事です。 #ue4fest

193.

ParticleからLightを発生 • 影響範囲が広いケース、パーティクルごとにLightがアタッチ されて大量に生まれるケースがあります。 意図した適切な範囲に、適切な光量が届いてるかは絶対に確 認してください。 減衰範囲が大きいほど高負荷に!! #ue4fest

194.

LightModuleの注意 ただLightModuleをぶら下げる CascadeEditor • 右の図のような感じにLight の減衰範囲が大きくなりま す。 この範囲は最大減衰範囲で あって、この範囲が必ず照 らされる訳ではありません。 RadiusScaleは親のスケー ルに乗算されるので注意 #ue4fest

195.

リフラクションはたくさん入れても大丈 夫? • 駄目です Resolveしたシーンを使って揺らぎ効果を出すので、何度も重 複で描いて効果のある個所ではない。 Distortion Pass内で、もう一回レンダリングされるため、そ の分のGPUコストもかかる。 #ue4fest

196.

リフラクションも効果を確認 • 揺らぎがそもそも想定した効果を出しているのか? 大量に重ねなくても出来るのか?不必要なものにリフラクシ ョンを入れてないかを確認することでオミットできるかも知 れない。 無駄なものを外せればその分GPUコストは下げられる。 特に細かいパーティクル全体に入れるのではなく、揺らぎは エミッタを分けて、目立つ部分の揺らぎは重複が少ない形で 行うなども考えられる。 #ue4fest

197.

エフェクトの最適化もとっても時間がか かる • 今回の軽量化一つとっても手間がかかる事が分かるかと思い ます。 今回のケースにおいてはパーティクルのパラメーターをいじ って作る訳ではなく、モデルを使ったトリックであるためで す。 その上この手のトリックが汎用的に使えるケースは少ないで す。 #ue4fest

198.

手っ取り早くできない? • もちろんお手軽にできるならそれに越した事はないです。 もしかしたらパーティクルLODやCutOutだけで済むものもあ るかも知れません。 しかし手間をかけた効果の高い方法は、画面に出せる情報量 を増やせる可能性があります。 チームが払えるコストや、目指すもの次第ではコストをかけ る価値があると思います。 #ue4fest

199.

まとめ • OverDrawを最小に • Lightの範囲、光量を適切に RadiusScaleをいくら広げても光量は変わらないので、意図 した広さを照らせているか、意図した数で出ているかは絶対 に確認 • Refractionを乱用しない • パーティクルの数≒クオリティではない #ue4fest

200.

PostProcessに関して #ue4fest

201.

ここだけはシノビストライカーで対応し た事をお伝えします。 • PostProcessは一個一個が重く、60fpsのゲームでは色々諦め る事が多いです。 ここではどういう視点で取捨選択したのかをお伝えしたいと 思います。 #ue4fest

202.

主に使われるもの • • • • • • • • AmbientOcclusion DOF TAA MotionBlur SSR AtmosphereFog CapsuleShadow ExponantialHeightFog #ue4fest

203.

AmbientOcclusiuon • テクスチャサンプリングが多い、範囲も広く負荷があがりや すい。 シノビストライカーにおいては画面への効果があまりなかっ たためにオミット。 エンジン改造する軽量化案としては半解像度で計算して、画 面へ適応する方法がある。 #ue4fest

204.

DOF • インゲームでは使用しない カットシーンでのみ使用するようにしました。 #ue4fest

205.

TAAは重い・・・ • TAA対策 根本的にシーン解像度が高いと負荷は高い。 TAAはカメラが素早く回る、動くタイトルではジッタが発生 しやすく品質的にもあまりよくない。 シノビストライカーではカメラの移動量や回転量が一定値を 上回った時には高速なFXAAへ変更。 TAAとFXAAでは倍以上パフォーマンスに差が生まれる。 #ue4fest

206.

MotionBlur • VelocityTextureを展開するVelocity Flattenが高負荷 • 追加コストとしてRenderVelocityがある TAAが有効か、MortionBlurが有効だとPer Bone MotionBlur が有効なオブジェクトがVelocityを書き込みに行く。 シノビストライカーではCharacterのLODが2からは RenderVelocityをSkip。 MotionBlurは負荷が高かったうえに、画面のイメージに合わ ないという事でオミット。 #ue4fest

207.

SSR • シノビストライカーにおいては画面の情報的に必要がないと 判断しました。 #ue4fest

208.

AtmoSphereFog • 空が開けたマップでのみ使用するようにしました。 視界内に空が見えてこないと、画面効果としてあまり見えな いため。 #ue4fest

209.

CapsuleShadow • 適応するRenderTargetの解像度が負荷の大きい部分だった シノビストライカーでは高い解像度は必要なかったため、エ ンジン側に手を入れて1/3の解像度でレンダリングしていた。 エンジンの設定だとFullResolutionかHalfResolutionしかない ため。 #ue4fest

210.

ExponentialHeightFog • シノビストライカーではすべてのステージで使用。 HeightFogのみの用途であれば比較的低負荷のため、許容。 #ue4fest

211.

まとめ • ゲームに本当に必要か確認 どうしても使いたい場合、優先順位と積極的なコントロール を。 • QualitySettingの確認 デフォルト値はコンソールではキツイ ローエンドのデバイスではScalabilityが低めに設定されてい ることもあり混乱の素だったりする。 実機で設定を必ず確認 #ue4fest

212.

それでもPostprocessingしたい場合 • 設定を変更しても尚もっともっと欲しいケース エンジン改造、機能追加 したくないと思いますが、チームの要求のために必要な時も あるのではないでしょうか。 もちろんリスクがあるので、チームで確認が必要だと思いま す。 結局のところ機能要件次第です。 #ue4fest

213.

CPU軽量化、最適化 #ue4fest

214.

概要 • 今回お話させて頂くのはGameThreadに対する対応を中心に していきたいと思います。 昨今のコンソールのCPUはコア数は多いものの、1コア辺りが 低速です。 そしてUE4では多くの処理がGameThread。 GameThreadに対する負荷が高く,GameThreadが占有する コアがボトルネックになる事が非常に多いです。 #ue4fest

215.

UE4はマルチスレッドで動いている? • マルチスレッドで動くタスクはあります。 だからといってすべて効率よくタスク化されている訳ではあ りません。 どうしても依存関係が強い個所などでは、並列化が行われな い個所も多いです。 #ue4fest

216.

CPUの負荷調査 • コンソール付属のProfiler それぞれのコンソールを解析するのに最も適しています。 • Stat startfile,Stat stopfile コンソール付属のものよりは大雑把に負荷調査が出来ます。 ただしスレッドの流れが追いづらい・・・。 • Stat その他 大雑把にトリアージするには大変有効。 • その他 VisualStudio 付属のProfiler等・・・ #ue4fest

217.

Unreal Insight • 4.23から実行可能なCPU Profiler 各スレッドのTimeLineや依存関係が見やすくなりました。 Engine/Binaries/Win64/UnrealInsight.exe を起動して、該当マシンに繋いだ後、タイトルの実行ファイ ルを-cpuprofilerTraceを付けて起動するとUnreal Insightで 計測可能な状態になります。 詳しくは公式の動画をご覧ください。 #ue4fest

218.

TestBuildで計測するために • Engine/Source/Runtime/Core/Public/Misc/Build.h をいじっておくと良いと思います。 Testビルドでも色々計測できるようにする を行う,もしくは #ifndef FORCE_USE_STATS #define FORCE_USE_STATS UE_BUILD_TEST #endif 個人的にはFORCE_USE_STATSの方がSTATS関係の使える幅 が広くて使い勝手が良かった。DO_CHECKはオミットされてる ので負荷は最小限のままです。 #ue4fest

219.

テストシーン: • ライントレースを飛ばしながらキャラクターを動かしてみる。 (尚PCだと軽いため、電源オプションでプロセッサに制限を加 えました。) #ue4fest

220.

前提 • 基本的なTickをしないようにであるとか、そういった部分は 皆さん語りつくされているので、その上でも実際に現場で何 度となく問題になった部分に注力していきたいと思います。 #ue4fest

221.

Characterを動かす時によく負荷になる 部分 • • • • • Overlap CharacterMovement UpdateComponentToWorld RayCast Animation #ue4fest

222.

Overlap • BoundingBox内のコリジョンを収集する機能 収集した結果を使ってイベントトリガーを引いたりします。 収集する際にはGameThreadから、場合によっては複数回収 集してしまうため、非常に重い。 今回のケースでは座標の更新をしていないため、Animation 後にOverlapが走っています。 #ue4fest

223.

UnrealInsightで確認 UpdateOverlapsがAnimationの 多くを占めている #ue4fest

224.

軽量化の候補 • 必要なものだけGenerateOverlapを行う。 不用意に有効にしたまま忘れるケースも・・・。 • Update Overlaps on Animation Finalize をUncheck Animation直後にOverlapが必要なければ切っても大丈夫です。 • Overlapで収集する対象を最小限にする *SetActorLocateやTickによる移動などではOverlapが追 加発生するので注意。(後述致します。) #ue4fest

225.

Update Overlaps on Animation Finalize • SkeletalMeshComponentにフラグがあります。 #ue4fest

226.

Overlapを抑制できました • しかし、本当にAnimation実行時に切っていいかどうかはゲ ーム次第。 例えばRootMotion側で高速移動している場合にはもしかした ら必要な事もあるかも知れません。 #ue4fest

227.

Overlapが発生する別ケース • 実はSetActorLocationでも発生します。 座標更新直後にOverlapが発生 頻繁に座標を更新するケースではすぐにボトルネックに。 #ue4fest

228.

座標を更新するテスト • わざとなんども1回のTickでActorの座標を更新させてみる。 #ue4fest

229.

UpdateOverlapが計上されました。 • しかもSetActorLocationの度に・・・ #ue4fest

230.

無駄ですよね? #ue4fest

231.

FScopedMovementUpdate • こちらを使う事で遅延させることが出来ます。 SetActorLocationやSetActorRotation直後ではなくScopeを 抜けるところまで遅延させることが可能です。 #ue4fest

232.

使ってみます。 #ue4fest

233.

UpdateはEndScopedMovementまで遅 延できました。 • CharacterMovementのtickの終了でも EndScopedMovementが呼ばれスコープから出た扱いになる ので注意。 #ue4fest

234.

FScopedMovementUpdateの注意点 • C++からしか設定できません。 ブループリントからSetActorLocationを呼ぶ際には設定がで きないので、前後からネイティブ化する必要があります。 #ue4fest

235.

構造的に難しいケースのために • エラーを誘発するので良くないのですが、明示的にSKipでき るようにエンジン改造もしました。 #ue4fest

236.

SceneComponent.h #ue4fest

237.

PrimitiveComponent.cpp #ue4fest

238.

SceneComponent.cpp #ue4fest

239.

SceneComponent.cpp #ue4fest

240.

ActorComponent.h #ue4fest

241.

やってはみたものの • 大丈夫かどうかはタイトル次第 移動した後すぐにOverlapやComponentの移動後の座標で判 定を取らないといけないケースはちょこちょこあったりする。 使うための手順も煩雑、あんまり良い処理ではない。 しかしながら、タイトルによっては2ms~3ms程度の軽量化 に。 そもそものデータ構造を綺麗にして、あまりこういったスマ ートでない方法に頼らないに越したことはないです。 #ue4fest

242.

Overlapまとめ • OverlapはGameThreadを圧迫しやすい筆頭 1.GenerateOverlapすべきかどうか 2.Overlapの対象は出来るだけ最小に 3.出来る限り余計な収集を走らせないようにする。 なるべくFScopedMovementUpdateを使うためにスコープ で覆えるように内部処理の構成を設計する。 #ue4fest

243.

CharacterMovement • キャラクターの歩行や移動の制御時の処理になります。 歩行移動で問題になるのはChar PhysWalkingになると思いま す。 今回のテストケースではPCの設定を変更したぐらいでは重く なってくれませんでしたが、コンソールでは負荷が高く計上 されやすい場所になります。 #ue4fest

244.

Char PhysWalking • CharacterMovementの大きい部分にCharPhysWalkingがい ます。 #ue4fest

245.

C++だと • UCharacterMovementComponent::PhysWalking while ( (remainingTime >= MIN_TICK_TIME) && (Iterations < MaxSimulationIterations) &&・・・ こんな感じになっていて、Iterations < MaxSimulationIterations の条件から何度も Iterationしているようです。 このMaxSimulationIterationsは名前の通り、シミュレーションの反復回数の最大 で、ヒット判定を最大でこの回数分繰り返します。 下げるのには不安がありますが、Projectileなどでは半分の4が指定されていたりする。 恐らくゲームによって調整を行ってもいいはず。 #ue4fest

246.

パラメーターが表に出てました。 • どうやら調整しても良さそうです。 ただしこちらを下げると当然Iterationの回数が減るので、下 げた場合にゲームで問題が出ないか確認の必要があります。 *ただし、経験測的には8は多い印象ではあります。 #ue4fest

247.

2に減らして試してみた。 • 長いタスクでも60us前後、以前のものは100us超えるものが 多かった。 #ue4fest

248.

CharacterMovementまとめ • 地面との当たりを取る都合上どうしても重くなりやすいです。 大量に出すものはCharacterMovement以外を使用すること も検討していいかも知れません。 #ue4fest

249.

UpdateComponentToWorld • こちらは座標の親子関係のついているComponentがいると発 生します。 親が動いた場合に発生するのでSetActorLocation、 Animation等が重くなる原因にもなります。 #ue4fest

250.

ChildTransforms #ue4fest

251.

UpdateComponentToWorldのまとめ (こちらは正攻法しかないので) • SetActorLocation,SetActorRotation できるだけまとめて、FScopedMovementUpdateを使い遅延 させるようにする。 • 座標があまり必要のないものは座標的な依存関係をつけない。 (KeepWorldにする等) • 必要な時だけアタッチされるようにする。 攻撃に使うヒット用オブジェクトが、コリジョン切ってる間 も親子関係がついてるケースがあった・・・。 #ue4fest

252.

RayCast • 地形やキャラクターの周りにあるものを調べたい時によく使 うと思います。 通常のインターフェースでは、呼び出し元スレッドで同期を とってしまうため数を呼び出し始めると全部GameThreadの 負荷になってしまいます。 #ue4fest

253.

たくさん呼び出してみました。 • LineTraceMultiByChannel をたくさん呼び出してみたのですが、全部GameThreadに直 列になっております。 #ue4fest

254.

非同期で呼び出す • 実はAsyncLineTraceByChannelという非同期用のインターフ ェースが存在します。 若干古いですが、AnswerHubにサンプルが上がっています。 こちらのインターフェースを使うと、即時に結果が得られな くなる代わりに、TaskThread内でコリジョン判定を行い EndPhysics辺りで、デリゲートに登録した関数に結果が返っ て来ます。 #ue4fest

255.

ASyncインターフェースを使ったところ • TaskGraphThreadBP12で行われている事を確認。 メインスレッドとは別にバックグラウンドで行われるように なった。 ただし当たりの結果はデリゲード関数に返ってくるので、遅 延判定しても問題ないものや、遅延判定してもよいように設 計する必要があります。 #ue4fest

256.

他にも注意点 • 判定を取る距離が長いほど負荷に 検索範囲が広がるため負荷になります。 • FCollisionQueryParamsを確認 特にbTraceComplexが有効だと、詳細コリジョンの判定もと ってしまうので、簡易なもので良いのであればこちらはfalse。 • FCollisionObjectQueryParamsを確認 必要最小限のものと判定を取れるように、用途に応じて CollisionChannelは設計する。(適当に取らない) #ue4fest

257.

RayCast まとめ • 必要最小限のものと、必要最小限の範囲で判定 そのためには どんなコリジョンがあるのか?どういう反応を返すのか?誰 と判定を取るのか? 即時性は求められるか?求められないなら遅延判定可能か? 等の設計は不可欠です。 設計によってはコリジョンを作る詳細度も変わり、メモリや 作業コストにも反映されていきます。 #ue4fest

258.

Animation • こちらはEpic Games様より出ている UE4アニメーションシステム総おさらい UE4で多数のキャラクターを生かすためのテクニック の内容を守れば概ね改善致します。 一応UpdateRateOptimizeを使ってどう変化するのかを書い ていきます。 ちなみにUpdateRateOptimizeの改造例はAnswerHubにサン プルをあげてあります。 #ue4fest

259.

Animationそのものよりほかのものが気 になりますが・・・。 • とりあえずUROを有効にして計測してみたいと思います。 #ue4fest

260.

UpdateRateOptimizeを有効 • InterpolateSkippedFrames フレームSkipといっても、ただコマが飛ぶわけではなく、飛 び先のPoseへ線形補間が行われるものになります。 なのでSkipという言葉の響きほど、見た目が悪くなるような 事はありません。 #ue4fest

261.

他にも(Epic様の資料に大体書いてあり ますが・・・) • • • • Boneのシミュレーションの可否 見えてない時のBoneの更新 Pose同士の補間(ブレンド数で負荷が増大) BoundingBoxをアニメーションと同期させるのか? 等々・・・・。 #ue4fest

262.

CPU まとめ • どこまで行っても余計な処理を走らせないが基本 そのためにはゲームの機能はできるだけ意図を明確に、ゲー ムの機能同士がどういう関連があるのか等、余計な処理を走 らせないためには重要。 特にコリジョンはゲームの設計に大きく関わります。 そして、高速化、軽量化のためにはProfilerで詳しく調査する という事は非常に重要になります。 #ue4fest

263.

UnrealInsightsを使ってみて • 非常に強力 各スレッドをTimelineで確認できるだけでなく、スレッド間 の依存関係も見やすく非常に強力なツールだと思います。 なんとなく使うところまではすぐにいけました。 特にロード関連は、IO周り,初期化周り、GC周りなどは非常 に追いやすくなったのではないかと思います。 #ue4fest

264.

とはいえ・・・ • より詳細な調査は コンソールのSDK付属のProfilerを使うのが良いと思います。 さらに詳細に追う事ができます。 #ue4fest

265.

おまけ:wwiseを使っている場合 • ミドルウェアプラグインコードを載せる訳にはいかないので、 概要だけ書きます。 wwiseはデフォルトのAffinityMaskを設定していないため、 GameThreadやRenderThreadをよく長い時間阻害してきま す。 こちらはAffinityMaskをGameThreadやRenderThreadとは 共有しないように設定することで、割り込みを抑制すること が出来ます。 PCでは下手に設定しない方が良いですが、他のハイエンドコ ンソールでは設定した方が良いです。 #ue4fest

266.

オマケ:メモリに関して #ue4fest

267.

今どきメモリを気にするなんて… なんて思っていませんか? #ue4fest

268.

メモリに対する思い込み 思い込みでメモリを気にしない例 思い込みでメモリを気にする例 • 今どき気にする人なんて PS2世代の老人たちでし ょ? • 何GBなんてメモリ使い切れ る訳無いじゃん。(古くは数 MBの時代にも同じセリフが あった・・・) • 変数削らなきゃ文字列削ら なきゃ • テクスチャを低解像度にし なきゃ、ポリゴン減らさな きゃ #ue4fest

269.

コンソールマルチは特に • 以前よりメモリは増えていますが 増えれば増えるほど大量にあるものは雑に消費されやすいの 法則が発動する。 • 小さいものを削っても仕方ない 特にリソースは作りや使われ方による。 メモリがどう使われているのか確認を! #ue4fest

270.

でもwikiとか見るとコンソールはかなり メモリ積んでるよね? • 全部使用できるわけではない。 アプリケーション領域は非公開なためここには具体的な数値 は書けませんが、ハードが持っているメモリ量がそのままア プリケーションで使える訳ではないです。 OS、非ゲームアプリ等のシステムリザーブ領域がある。 コンソール開発をするなら、コンソールのドキュメントは絶 対に確認しないとダメ‼ #ue4fest

271.

RenderTarget シーンが1080pの場合 • • • • • TemporalAA ≒15MB(使ってる個所次第でもっと) DOFFullResSetup ≒15MB ScreenSpaceReflections ≒ 15MB CustomDepth ≒10MB SceneDepthZ≒10MB ・・・等々 トータルで180MB前後 瞬間的に取る量が増え る事もあるため、Poolしておくバッファとしてはもっと必要 になる。 #ue4fest

272.

テクスチャメモリ • テクスチャ解像度やフォーマット、読み込まれるmipに依存 • StreamingTexturePool TextureStreamに必要でフレキシブルなメモリ管理を行う。 sg.TextureQuality次第で400MB~3000MB(デフォルトがコ ンソールでsg.TextureQuality 2、PCで3なので800MB~ 1000MBが通常とられている) #ue4fest

273.

テクスチャのメモリ 使用例 BC5 : 4096x4096 mip 13 ≒ 21MB BC7 : 4096x4096 mip 13 ≒ 21MB DXT5:4096x4096 mip 13 ≒ 21MB DXT1:4096x4096 mip 13 ≒ 10MB G8 : 4096x4096 mip 13 ≒ 21MB RGBA8:4096x4096 mip13 ≒ 86MB *ただしこれはmipが全部読み込まれた場合のもの,実際には Streamerが読み込むmipを制御 • • • • • • #ue4fest

274.

実際のシーンのテクスチャメモリ例 • Total size: InMem ≒ - B8G8R8A8 size: InMem - DXT1 size: InMem - DXT5 size: InMem - FloatRGBA size: InMem - BC5 size: InMem - BC7 size: InMem 546.71 MB ≒ 72.91 MB ≒ 96.60 MB ≒ 187.54 MB ≒ 37.34 MB ≒ 69.82 MB ≒ 77.42 MB #ue4fest

275.

実際のシーンのclassオブジェクト • 194376 Objects Total: 147.278M 塵も積もればの場所ではありますが、何のclassが使っている かはよく確認。 地味にAnimSequenceはかなり大きかった。(80MBを占め ていた) #ue4fest

276.

Meshのメモリ • 頂点バッファ アトリビュートによって1頂点のメモリサイズは変わる。 UVをいくつ持っているか?ライトマップUVはあるのか? 頂点カラーは?LODはimportか? • インデックスバッファ UE4からのGenerateLODはIndexBufferだけが生成される。 #ue4fest

277.

Meshのメモリ使用例: • LOD0の△47246 2.1MB • LOD0の△21256 1.1MB • LOD0の△15360 1.2MB :UV 2ch: LOD3 :UV 3ch: LOD2 :UV 2ch: LOD3 #ue4fest

278.

実際のシーン • Static Mesh ≒ 128MB • SkeletalMesh ≒ 20MB #ue4fest

279.

他にも • • • • • • NaviMesh Collision Animation Physics Sound Pool Streamingのための予備バッファ 等々・・・・。 #ue4fest

280.

読み込み時間も増加する • 読み込むものが増える という事はロード時間も増加する つまりメモリ以外も影響を受ける。 ロード時間は快適なプレイを阻害し、解消するためには画面 設計や、ゲームの設計をクオリティダウンさせうるかも知れ ません。 #ue4fest

281.

昔に比べてメモリは増えました • しかし リソースの種類も、使用用途も、1リソースの容量も増えてま す。 まずは冷静に要素を分解、解析し設計に生かすのが良い。 ただし、昔より非常に複雑なので、単純な話では無いという 事に注意。 #ue4fest

282.

総括 #ue4fest

283.

説明しきれませんでしたが・・・ • 資料をいくら積み重ねても足りない そのぐらい60fpsのハイエンドのアクションゲームは大変、設 計もシビアになる。 やり方はケース・バイ・ケース、デバイスの性能限界に挑戦 しようとすると特にそうなります。 データだけ、プログラムだけ、企画ゲームデザインだけでな んとかしようとせずに相互に協力を。 #ue4fest

284.

より効果のある対応のためにも • より詳細な調査を行いましょう。 【各個人で調査をして、各個人で対処できるように】みたい な話はよく上がるのですが、本人がそれと気づかずにワーク アラウンドを入れてるケースがある。 修正や対応はレビューが出来ると尚良いと思います。 チームの状況によってはそれが出来ない事も多いと思います が、後ででもレビューできる状態にだけしておければ、いざ 何かあった時に調査のとっかかりになります。 #ue4fest

285.

実際そこまで頑張る価値は? • これもケース・バイ・ケースです。 なぜならゴール地点は座組やゲームによりけりだからです。 もしかしたら、背景がどれだけクオリティ落ちても軽くした いケースはあるかも知れませんし、落とされるのはエフェク トなのかも知れません。 ゴール地点にたどり着くならクオリティを落とすという判断 はあると思います。 もしくは出来るだけ全体を高めていきたい という話もある かも知れません。(コストも難易度も跳ね上がりますが) #ue4fest

286.

パフォーマンスを出すという事 • クオリティを落とす事 では決してありません。 ただ、クオリティが落ちる部分もあります。 何度も書きますがケース・バイ・ケースです。 クオリティを落とさないようにパフォーマンスを出すのは試 行錯誤が必須で手間がかかります。 即効性の高い対応がとれるとは限らない。 何か良い削減方法を思いついても、実行できない事もある。 #ue4fest

287.

よりよくしていくために • 知見を共有しましょう オープンソースなミドルウェアを使う最大 のメリットです。 試行錯誤を減らしコストを抑えるためにも、 そして何よりゲームをより良いもの にしていくためにも是非知見共有 を! #ue4fest

288.

参考文献: • • • • • • • • • • • RenderHellBook The Peak-Performance-Percentage Analysis Method for Optimizing Any GPU Workload What is Limiting Your Rendering Performance? Using ‘Nsight Graphics: GPU Trace’ and the Peak-PerformancePercentage Method life-triangle-nvidias-logical-pipeline GPU-DRIVEN RENDERING Mask Material only in Early Z-passの効果と仕組み NSightCompute NSight UserGuide UnrealInsights UE4アニメーションシステム総おさらい UE4で多数のキャラクターを生かすためのテクニック #ue4fest