Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

【GTMF2018TOKYO】ScriptableRenderPipelineでアプリに最適な描画をしよう

12,568 views

Published on

2018/7/13に開催されたGTMF2018TOKYOの講演資料です。
講師:黒河 優介(ユニティ・テクノロジーズ・ジャパン合同会社)

Published in: Technology
  • Be the first to comment

【GTMF2018TOKYO】ScriptableRenderPipelineでアプリに最適な描画をしよう

  1. 1. ScriptableRenderPipelineでアプリに最適な描画をしよう 2018/7/13 講演者名 黒河 優介 所属団体 Unity Technologies Japan 肩書・役職 Developer Relation Engineer
  2. 2. • • • • •
  3. 3. • Unity RenderPipeline • ScriptableRenderPipeline(SRP) •
  4. 4. ※ ForwardRendering
  5. 5. Unity • • • Shadow
  6. 6. Opaque → Depth Test Transparent →
  7. 7. Opaque
  8. 8. Opaque
  9. 9. Opaque
  10. 10. Opaque Z-Buffer ZTest Z-Test
  11. 11. Transparent
  12. 12. Transparent
  13. 13. Transparent
  14. 14. Transparent
  15. 15. • Camera Depth • Renderer sortingLayerName • Renderer sortingOrder • MeshRenderer sortingOrder • Material.renderQueue
  16. 16. 地面の部分は3つのオブジェクトを描画後に描画して、塗るピクセル数を 減らしてほしいが、一番最初に描画されてしまっています。
  17. 17. これはRendererのBoundingBoxの中心位置で手前・奥の判定を行っている ため、地面が一番手前と判定されてしまっています。
  18. 18. まず最初に三つのオブジェクトが描画されて…
  19. 19. その後に地面が描画されることが理想形です。
  20. 20. Unity …
  21. 21. vertex
  22. 22. このようにポイントライト3つ あるシーンを描画する場合…
  23. 23. まず、ポイントライト適応前の状態を描画します
  24. 24. その後、ポイントライト一つ一つ当たった状態のオブ ジェクトを描画して加算合成していきます。 そのため余計な描画負荷を伴います
  25. 25. Point Light....
  26. 26. Shadow Shadow QualitySettings
  27. 27. Shadow …
  28. 28. Unity
  29. 29. ScriptableRenderPipeline(SRP) • SRP • LightWeightRenderPipeline(LWRP) •
  30. 30. SRP • Unity SRP • • • Shadow •
  31. 31. SRP // 描画時にコールバックされます。引数contextに対して描画命令を発行していきます void OnRender(ScriptableRenderContext context, Camera[] cameras) { foreach (var camera in cameras){ // まず Camera毎のShader のパラメーターセットアップして… SetupShaderParams(camera); // スクリプトで決めたルールでカリングをして… var res = CullResults.Cull(ref cullingParams, context, ref cull); // そしてカリングして得た Rendererを引数で指定したルールで描画します context.DrawRenderers(res.visibleRenderers, ref settings, filterSettings); } }
  32. 32. SRP 1.RenderPipelineAsset/RenderPipeline 2. RenderPipelineAsset Asset GraphicsSettings.renderPipelineAsset 3.Shader Renderpipeline LightMode
  33. 33. 1. [ExecuteInEditMode] public class MySRPAsset : RenderPipelineAsset{ protected override IRenderPipeline InternalCreatePipeline(){ return new MyScriptableRenderPipelineInstance(); } } public class MyScriptableRenderPipelineInstance : RenderPipeline{ // 描画のタイミングでコールバックされます public override void Render(ScriptableRenderContext context, Camera[] cameras){ base.Render(context, cameras); foreach (var camera in cameras){ // 描画処理をここに書いていきます } } }
  34. 34. 2-1. GraphicsSettings var instance = ScriptableObject.CreateInstance<MySRPAsset>(); AssetDatabase.CreateAsset(instance, "Assets/MyScriptableRenderPipeline.asset"); 上記のようなEditor拡張で、独自のRenderPipelineAsset のアセットを作成します
  35. 35. 2-2. GraphicsSettings 先ほど作成したRenderPipelineAssetを指定します
  36. 36. 3. Shader RenderPipeline Renderer ShaderPassName Pass Shader Pass LightMode
  37. 37. var settings = new DrawRendererSettings(camera, new ShaderPassName("BasicPass")); settings.sorting.flags = SortFlags.CommonOpaque; var filterSettings = new FilterRenderersSettings(true) { renderQueueRange = RenderQueueRange.opaque, layerMask = 1 << LayerDefine.BG }; context.DrawRenderers(cull.visibleRenderers, ref settings, filterSettings); SubShader{ Tags { "Queue"=“Geometry" "RenderType"=“Opaque"} Pass{ Tags { "LightMode" = "BasicPass"} ....処理等 } } C#側の処理 Shader側
  38. 38. var settings = new DrawRendererSettings(camera, new ShaderPassName("BasicPass")); settings.sorting.flags = SortFlags.CommonOpaque; var filterSettings = new FilterRenderersSettings(true) { renderQueueRange = RenderQueueRange.opaque, layerMask = 1 << LayerDefine.BG }; context.DrawRenderers(cull.visibleRenderers, ref settings, filterSettings); SubShader{ Tags { "Queue"=“Geometry" "RenderType"=“Opaque"} Pass{ Tags { "LightMode" = "BasicPass"} ....処理等 } } C#側の処理 Shader側 描画設定で指定したShaderPassNameと ShaderのLightModeを一致させる必要が あります。
  39. 39. SRP
  40. 40. SRP Camera ImageEffect public class MyScriptableRenderPipelineInstance : RenderPipeline{ // 描画のタイミングでコールバックされます public override void Render(ScriptableRenderContext context, Camera[] cameras){ base.Render(context, cameras); foreach (var camera in cameras){ // 描画処理をここに書いていきます } // ImageEffect等の実装はココで実行されるようにする等が必要です } }
  41. 41. SRP Surface Shader SRP vertex shader / fragment shader 2018.1 ShaderGraph Shader
  42. 42. ScriptableRender Pipeline
  43. 43. LightWeightRenderPipeline(LWRP) SRP 0 Unity LightWeithRenderPipeline(LWRP) HDRenderPipeline(HDRP)
  44. 44. LightWeightRenderPipeline(LWRP) Unity (Built-In) RenderPipeline LWRP URL https://blogs.unity3d.com/jp/2018/02/21/the-lightweight-render- pipeline-optimizing-real-time-performance/
  45. 45. LightWeightRenderPipeline(LWRP) 標準のレンダリングパイプラインで問題だったポイントライトの加算問題も LWRPでは起こりません。ピクセルシェーダー側でキチンとポイントライトを 扱い1パスで描画されます
  46. 46. LWRP • PackageManager • • github • https://github.com/Unity-Technologies/ScriptableRenderPipeline
  47. 47. PackageManager LWRP LightweightRenderPipelineをInstall するだけです
  48. 48. LWRP • Shader LWRP • Unity Shader Material Editor
  49. 49. LWRP • Shader LWRP • LightMode LightweightForward • ShadowMapTexture Shadow 参考URL https://connect.unity.com/p/lightweightrenderpipelinexiang-kenishaderwoshu-itemita
  50. 50. LWRP • LightWeightRenderPipeline • PostProcessingStack v2 • ShaderGraph • Core RP
  51. 51. • [ShaderIncludePath] • Stripping scriptable shader variants(2018.2 ) • SRP Batcher
  52. 52. [ShaderIncludePath] • Unity Shader include • Assets or
  53. 53. [ShaderIncludePath] public class ShaderIncludePathSetting{ [ShaderIncludePath] public static string[] GetPaths(){ return new[]{ "Assets/SRP/Core/", "Assets/SRP/LightWeightPipeline/", }; } } Shader内のincludeをコチラからの相対パスで 指定できるようになります。
  54. 54. [ShaderIncludePath] • Github LWRP Shader ShaderIncludePath
  55. 55. Stripping scriptable shader variants • Shader variants Shader • • 参考URL https://blogs.unity3d.com/2018/05/14/stripping-scriptable-shader-variants/
  56. 56. Stripping scriptable shader variants LWRP • LWRP 2.0 Stripping scriptable shader variants • LWRP 2.x Unity2018.1 • LWRP 2.0 Renderpipeline
  57. 57. SRP Batcher • CPU • Shader • GPU • 5 • DirectX11/Metal Experimental 2018.3 Vulkan Experimental
  58. 58. SRP Batcher GraphicsSettings.useScriptableRenderPipelineBatching= true; ※LWRP/HDRP Unity CBuffer
  59. 59. SRP Batcher DrawCall CPU GPU Material ConstantBuffer Material CPU
  60. 60. SRP Batcher (RenderDoc ) SRP Batcher有効時 SRP Batcher無効時
  61. 61. SRP Batcher (RenderDoc ) SRP Batcher有効時 SRP Batcher無効時 ドローコール数や順番はSRP Batcherの有無で は変わっていません。
  62. 62. SRP Batcher (RenderDoc ) SRP Batcher有効時 SRP Batcher無効時 実際に描画する前に行うShaderパラメーター のセット周りの処理が異なっています
  63. 63. • 0 RenderPipeline • LWRP RenderPipeline
  64. 64. 0 RenderPipeline
  65. 65. キャラクターは板ポリゴンに スプライトを貼っただけ
  66. 66. RenderPipeline …
  67. 67. RenderPipeline … Transparentは奥から手前を 遵守します
  68. 68. RenderPipeline … Materialの切り替えを都度しな がら奥から手前へ描画します
  69. 69. RenderPipeline … そのため、描画するのに非常に多くの Material切り替えが発生しました
  70. 70. Material … …
  71. 71. ScriptableRender Pipeline
  72. 72. … var pass = new ShaderPassName("BasicPass"); var settings = new DrawRendererSettings(camera, pass); settings.sorting.flags = SortFlags.CommonOpaque; var filterSettings = new FilterRenderersSettings(true){ renderQueueRange = RenderQueueRange.transparent, layerMask = 1 << LayerDefine.BG }; context.DrawRenderers(cull.visibleRenderers, ref settings, filterSettings);
  73. 73. … var pass = new ShaderPassName("BasicPass"); var settings = new DrawRendererSettings(camera, pass); settings.sorting.flags = SortFlags.CommonOpaque; var filterSettings = new FilterRenderersSettings(true){ renderQueueRange = RenderQueueRange.transparent, layerMask = 1 << LayerDefine.BG }; context.DrawRenderers(cull.visibleRenderers, ref settings, filterSettings); 描画する時のShaderのPass名 を指定できます
  74. 74. … var pass = new ShaderPassName("BasicPass"); var settings = new DrawRendererSettings(camera, pass); settings.sorting.flags = SortFlags.CommonOpaque; var filterSettings = new FilterRenderersSettings(true){ renderQueueRange = RenderQueueRange.transparent, layerMask = 1 << LayerDefine.BG }; context.DrawRenderers(cull.visibleRenderers, ref settings, filterSettings); 描画する時のソート順を指 定できます
  75. 75. … var pass = new ShaderPassName("BasicPass"); var settings = new DrawRendererSettings(camera, pass); settings.sorting.flags = SortFlags.CommonOpaque; var filterSettings = new FilterRenderersSettings(true){ renderQueueRange = RenderQueueRange.transparent, layerMask = 1 << LayerDefine.BG }; context.DrawRenderers(cull.visibleRenderers, ref settings, filterSettings); 描画する対象のオブジェクトの Opaque・Transparent等を指定 できます。
  76. 76. … var pass = new ShaderPassName("BasicPass"); var settings = new DrawRendererSettings(camera, pass); settings.sorting.flags = SortFlags.CommonOpaque; var filterSettings = new FilterRenderersSettings(true){ renderQueueRange = RenderQueueRange.transparent, layerMask = 1 << LayerDefine.BG }; context.DrawRenderers(cull.visibleRenderers, ref settings, filterSettings); Layer単位で描画するオブジェクト を切り替えられます。
  77. 77. Shader Z Pre-Pass
  78. 78. SubShader{ Tags { "Queue"="Transparent" "RenderType"="Transparent"} // Z Pre-Pass Pass{ Tags { "LightMode" = "ZPrepass"} ZWrite On ColorMask 0 //...実際の処理 } // 実際の描画用のパス Pass{ Tags { "LightMode" = "BasicPass"} ZWrite Off ZTest Equal Blend SrcAlpha OneMinusSrcAlpha //...実際の処理 } }
  79. 79. SRP
  80. 80. Depth αが一定値以下の場合はdiscard して描画を行うShader Pass 「ZPrepass」で一旦キャラク ターを描画します。 ※Z Bufferの様子です
  81. 81. その後 床を描画します
  82. 82. キャラクターを通常のShaderPassで描画します。 この時、マテリアル切り替えを最小に抑える順番になるように sorting.flagに「SortFlags.OptimizeStateChanges」を指定します
  83. 83. 最後に影を描画します
  84. 84. Z Pre-Pass ※α …
  85. 85. Z BufferのZ値と一致した部分のピクセルでない と、Zテストを通らず、ピクセルが塗られないた め絵が破綻しません
  86. 86. Material
  87. 87. LWRP 背景からキャラクター。 キャラクターから背景への影 はリアルタイムShadowで、他 は焼いたShadowです。
  88. 88. LWRP わかりやすくするため、 リアルタイムのShadowのみ青 くしました。
  89. 89. … Shadow → Shadow → → →
  90. 90. LWRP … 焼いたShadowの上からリアル タイムのShadowも描いてしま います
  91. 91. LWRP … それを防ごうとすると、 キャラクターへのShadowが なくなってしまいます
  92. 92. • Shadow • Shadow •
  93. 93. 始めにキャラクターだけの ShadowMapを生成します
  94. 94. キャラクターだけのShadowMapを 適応して背景を描きます
  95. 95. キャラクターだけのShadowMapに 背景オブジェクトも描き足します。
  96. 96. 最後にキャラクターを描画します。
  97. 97. // 描画時にコールバックされます。引数contextに対して描画命令を発行していきます void OnRender(ScriptableRenderContext context, Camera[] cameras) { foreach (var camera in cameras){ // 「Chara」レイヤーだけ先にShadowを処理します ShadowPass( 1 << Layers.Chara); // 「Chara」レイヤー以外のオブジェクトをレンダリングします DrawObjects( ~( 1<< Layers.Chara) ); // 「Chara」レイヤー以外のShadowを処理します ShadowPass( ~( 1 << Layers.Chara) ); // 「Chara」レイヤーのオブジェクトだけをレンダリングします DrawObjects( 1<< Layers.Chara ); } }
  98. 98. 通常では、SelfShadowが発 生してしまいます 今回の特殊パスを用いれば、 キャラクターのSelfShadowのみオフ に出来ます
  99. 99. SRP ShadowPass
  100. 100. ScriptableRenderPipeline • • • Shadow • Unity LWRP
  101. 101. 3
  102. 102. Appendix 0 https://github.com/wotakuro/CustomScriptRenderPipelineTest LWRP https://github.com/wotakuro/MixedShadowSample SRP https://connect.unity.com/u/5768a3b332b306001aaf2d1f

×