Slide 1

Slide 1 text

「IDOLY PRIDE」に おける描画最適化術 株式会社QualiArts 渡邉俊光

Slide 2

Slide 2 text

自己紹介 ● 2012年CyberAgent新卒入社 ● オルタナティブガールズ等の開発を経て 株式会社QualiArtsのTA室で「IDOLY PRIDE」(以下アイプラ)の 3D実装全般を担当

Slide 3

Slide 3 text

アイプラとは? 2021年6月リリース、アイドルマネジメントRPG

Slide 4

Slide 4 text

アジェンダ ● 実行環境 ● ScriptableRenderPipeline(SRPBatch) ● 描画API ○ レンズフレア(DrawProcedural) ○ ボリュームライト(DrawMeshInstancedProcedural) ○ 観客(DrawMeshInstancedIndirect)

Slide 5

Slide 5 text

実行環境

Slide 6

Slide 6 text

実行環境 ● Unity2020.3.4f1 ● UniversalRenderPipeline 10.5.0 ● GPU Lightmapper ● HDR+Linear Rendering ● 対象プラットフォーム ○ Android→Vulkan(OpenGLES3.1も一応動作…) ○ iOS→Metal GPU family 3以降(Apple A9) ○ 5年前のハイエンドがギリギリ動く目安 Unity新機能たくさん かなり攻めてる

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

ScriptableRenderPipeline

Slide 9

Slide 9 text

UniversalRenderPipeline(SRP) ● ScriptableRenderPipelineを拡張したUnityの新 しい描画システム ● HDRPと違い、様々な端末で動作するように チューニングされている ● RendererFeatureを作成することで簡単に CommandBufferを追加できる Legacyではカメラに追加だったので非常に面倒 +SceneViewの扱いが面倒だった ● ポストエフェクトはPostProcessPassを複製して 書き換えすることで処理効率化

Slide 10

Slide 10 text

ShaderGraph ● ShaderGraph 10.5.0 ● UniversalTargetを追加して自前の 処理を挿入 ● バージョンが上がるたびに仕様が変 わっていて泣く ● SRPBatchやUnity標準の最適化が入 るのでとても便利

Slide 11

Slide 11 text

SRPBatch ● ScriptableRenderPipelineのメイン機能?とも言える新しいバッチシステム ● Metal又はVulkanに対応 ● SetPassを最小限にしてDrawCallの発行効率を最適化高速化→CPU高速化 ● アイプラではキャラクター、背景全てでSRPBatch対応 ● 適用には様々な条件や罠がある ● 割と最近まで動作が不安定だった ● Unity公式→ SRP Batcher:レンダリングをスピードアップ

Slide 12

Slide 12 text

SetPassCall 283 → 155 !!

Slide 13

Slide 13 text

描画API

Slide 14

Slide 14 text

軽量化するには? ● C#が重すぎる!!(100個くらいのオブジェクトで割とアウト) ● C# JobSystem (Burst) = 神 ● ComputeShader = 超神 ● ComputeBufferを描画APIと組み合わせる(SSBO対応必須) Compute >>>…>>> Burst >>>>>...>>>>>C# 体感これくらい

Slide 15

Slide 15 text

レンズフレア(DrawProcedural) ● アイプラではProFlareを使用 ● 描画、更新処理はほぼ全て書き換え ● DrawProceduralで描画 ● 9ms → 1.6ms(ベンチマークシーン) C# 座標系、画面内判定 Burst 値更新しつつ ComputeBufferに整形 ComputeShader DepthTextureと当たり判定

Slide 16

Slide 16 text

DrawProcedural ● https://docs.unity3d.com/ja/current/ScriptReference/Rendering.Comm andBuffer.DrawProcedural.html ● メッシュ不要 ● 頂点のつなぎ方と数だけで大抵の描画ができるAPI ● GraphicsBufferでIndexのバッファを送ることで自由なつなぎ方も出来る void DrawProcedural (GraphicsBuffer indexBuffer, Matrix4x4 matrix, Material material, int shaderPass, MeshTopology topology, int indexCount, int instanceCount, MaterialPropertyBlock properties);

Slide 17

Slide 17 text

ボリュームライト(DrawMeshInstancedProcedural) ● ボリュームライトには VolumetricLightBeam(VLB)を使用 ● 描画、更新処理はほぼ全て書き換え ● DrawMeshInstancedProceduralで描画 C# VLB値更新 Burst AABBカリング

Slide 18

Slide 18 text

DrawMeshInstancedProcedural ● https://docs.unity3d.com/ja/current/ScriptReference/Rendering.Comm andBuffer.DrawMeshInstancedProcedural.html ● メッシュを複製して描画 ● 細かい設定は出来ないがMaterialPropertyBlockでComputeBufferを入れて おくことでInstancing毎に色を変更できる void DrawMeshInstancedProcedural (Mesh mesh, int submeshIndex, Material material, int shaderPass, int count, MaterialPropertyBlock properties);

Slide 19

Slide 19 text

観客(DrawMeshInstancedIndirect) ● 観客は動員人数を自在に変動可能(Max32768) ● 座席データに優先度がある ● カメラに近い観客は体も描画 ● DrawMeshInstancedIndirectで描画 C# 座席データから ComputeBuffer生成 ComputeShader 境界球カリング ModelMatrix更新 数値更新

Slide 20

Slide 20 text

DrawMeshInstancedIndirect ● https://docs.unity3d.com/ja/current/ScriptReference/Rendering.Comm andBuffer.DrawMeshInstancedIndirect.html ● パラメータにIndirectBufferを使用してメッシュを描画 ● IndirectBufferにInstancing数等を入れておくことでCPU側での指定が不要 ● ComputeShaderで全て計算できる! void DrawMeshInstancedIndirect (Mesh mesh, int submeshIndex, Material material, int shaderPass, ComputeBuffer bufferWithArgs, int argsOffset, MaterialPropertyBlock properties);

Slide 21

Slide 21 text

まとめ ● Vulkan世代をベースにすることで様々な最適化が可能になり今まで出来な かった表現が可能となる ● Burst対応をすることでCPU問題はかなり解決できる (Burst出来ない箇所が重すぎるのが課題…DOTS? ) ● ComputeShaderは爆速だがAndroidでは過信しすぎないように →iPhoneに比べてComputeの実行速度はそこまで進化していない罠 ● Androidローエンド端末問題はある…