【Unite Tokyo 2019】SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~

16.5K Views

September 26, 19

スライド概要

2019/9/25-6に開催されたUnite Tokyo 2019の講演スライドです。
堂前 嘉樹(株式会社ロジカルビート)

こんな人におすすめ
・Unityの描画フローにもどかしさを感じているプログラマー
・最適化を図りたいと思っているプログラマー
・どのゲームエンジンを選択するか悩んでいるプログラマー

受講者が得られる知見
・SRPを導入することで得られるメリット
・SRPを構築するための細かなテクニック
・描画フローの構築を一から行うための基礎知識

Unityのイベント資料はこちらから:
https://www.slideshare.net/UnityTechnologiesJapan/clipboards

profile-image

リアルタイム3Dコンテンツを制作・運用するための世界的にリードするプラットフォームである「Unity」の日本国内における販売、サポート、コミュニティ活動、研究開発、教育支援を行っています。ゲーム開発者からアーティスト、建築家、自動車デザイナー、映画製作者など、さまざまなクリエイターがUnityを使い想像力を発揮しています。

シェア

またはPlayer版

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

関連スライド

各ページのテキスト
2.

SRPで一から描画フローを作ってみた! ~Unity描画フローからの脱却~ 株式会社ロジカルビート 代表取締役 / プログラマー 堂前 嘉樹

3.

自己紹介 3

4.

自己紹介 — 株式会社ロジカルビートの代表取締役かつプログラマー。 — 新横浜にある、プログラマ主体の会社です。 — コンシューマ、スマホ、Unity、UE4、ネイティブと、なんでも対応。 — 前職は大手コンシューマ会社でグラフィックスプログラム担当。 — 2016年のUniteでも講演させてもらいました。 – Unity5を使った「いけにえと雪のセツナ」の雪世界の作り方 – https://www.youtube.com/watch?v=6RppDyZuTt4 4

5.

はじめに 5

6.

Scriptable Render Pipeline (SRP) 6

7.

LWRP HDRP LWRPやHDRPの情報は良く見るようになったが、 SRPで新規構築する話はあまり見ない! 7

8.

チャレンジしてみた! 8

9.

今回やってみたこと 9

10.

SRPを使ってやってみたこと — 某レンダラーソフトのレンダリングを(ある程度)移植。 – 最適化や手間の兼ね合いである程度の処理は省いた。 – ポストフィルタも実装。 — iPhone XSをターゲットとして実行。 – fpsはこだわらなかったが、30fpsでは動いた。 — 検証期間・約3ヶ月。 — LWRPやHDRPからの派生ではなく、SRPを一から構築! 10

11.

機能詳細 — PBRベースのシェーディング。 – Microsurface(Gloss) – Diffusion(Lambertian / Subsurface Scatter) – ※Subsurface Scatterはポスト処理も並行。 – Reflectivity(Specular / Metalness) – Reflection(Mirror / Blinn Phong / GGX / Anisotropic) – ※Subsurface ScatterとAnisotropicの併用不可。 — ライトはDirectional LightとPoint Lightのみ対応。 11

12.

機能詳細 — ベースはDeferred Rendering。 – 半透明はForwardで対応。ディザパターンも可。 – G-Bufferは4枚~8枚利用。 – Subsurface ScatterやAnisotropicを利用する時は8枚。 — シャドウはシンプル。カスケード無し。 – カスケード対応の時間が無かった。 — SSAOも対応。SSRは非対応。 – こちらも時間不足で作り込めていません。 12

13.

※Lee Perry-Smith の Infinite 3D Head Scan。クリエイティブ・コモンズ・ライセンス 3.0 (www.ir-ltd.net で入手可能) 13

14.

調整した状態 ※Lee Perry-Smith の Infinite 3D Head Scan。クリエイティブ・コモンズ・ライセンス 3.0 (www.ir-ltd.net で入手可能) 14

15.

off default Screen Space Sub Surface Scatter ※Lee Perry-Smith の Infinite 3D Head Scan。クリエイティブ・コモンズ・ライセンス 3.0 (www.ir-ltd.net で入手可能) 15 max

16.

Gloss 0.0 1.0 0.0 1.0 Metalness 16

17.

UnityのStandard利用 ※Lee Perry-Smith の Infinite 3D Head Scan。クリエイティブ・コモンズ・ライセンス 3.0 (www.ir-ltd.net で入手可能) 17

19.

自前でリッチな 描画が出来た 19

20.

注意点 20

21.

Unity 2018.3.14f1 ↓ Unity 2019.2.5f1 21

22.

「LWRP」で統一します (※2019.3からUniversal Render Pipeline) 22

23.

SRPを使ってみて 23

24.

最初に所感 24

25.

最高です! 積極的に使っていきたい 25

26.

Unityの描画フローに もどかしさ 26

27.

Unityでの経験談 27

28.

その1 投影テクスチャシャドウに変更したい! 28

29.

シンプルな影でいい 29 カメラが作る画像

30.

デプスシャドウ デプス比較 シャドウマップ 影を作る 必ずデプスバッファ 30

31.

投影テクスチャシャドウ デプス比較せず描画 シャドウマップ 影を作る 31 R8バッファでも良い が、変更できない!

32.

カメラを置いて シャドウマップを無理矢理作る Camera増によるコスト ボリュームを どう作る? Castオブジェクトだけ 描画するのが大変 32

33.

シャドウマップ自作 — Unityは通常、デプスシャドウでシャドウを描画する。 — ゲームのカテゴリやシチュエーションによっては、投影シャドウに したい場合がある。 – 主にセルフシャドウを必要としないシチュエーション。 – シャドウマップはR8程度でも良い。 — シャドウの処理をVSMにしたいということもあるかもしれない。 – その際はR16G16のシャドウマップを使いたい。 — シャドウマップのフォーマットは、ユーザー側では変更できない! 33

34.

シャドウマップ自作 — それならシャドウマップを自作しようと試みたとする。 – – 視錐台用のカメラを追加しなければならない。 – 独自フォーマットのRenderTextureを使いたいので。 – カメラ固有のCPU負荷が無駄に掛かる恐れがある。 そのカメラ位置などを自前で計算しなければならない。 – Unity側で算出する情報は取得できないため。 – 品質の高い視錐台を作るためには計算コストが掛かる。 — 総じて手間が掛かって面倒! 34

35.

その2 3D部と2D部での解像度変更 35

36.

3Dモデル等の描画 ・キャラクターや背景などの描画。 ・GPUコストが掛かりやすい。 ・フル解像度ではなく、縮小させた解 像度のバッファで描きたい。 (動的解像度も視野) Camera ポストフィルタ処理等 ・縮小して描いた3D部分のバッファ を、ポストフィルタを掛けつつ、フル 解像度に戻したい。 2D描画(UI) ・ゲーム的に必要なUIを描画。 ・ディスプレイと同じ解像度(フル解 像度)で描きたい。 ・モデル等は描かない。 Camera 36 Camera

37.

3Dモデル等の描画 不透明 半透明 SSAO 縮小バッファ etc.. 37

38.

3D部と2D部での解像度変更 — 3D部分は必要に応じて解像度を動的に変えたい! – 俗にいう動的解像度的なことが行えると良い。 — 2D部分はぼかしたくないのでフル解像度で描きたい。 — 3D→2Dで解像度を変えると、Cameraがまた必要になる。 – 3D→RenderTexture 2D→デフォルトターゲット – OnPreRender() ,OnPostRender(), OnRenderImage()もあるが、スクリ プトを用意しないといけないので手間。 38

39.

3D部と2D部での解像度変更 — 3D部分も、凝ったことがやりたくなる。 – 縮小バッファやSSAO等。 – SSAOはCommandBufferを使えば行けなくは無さそうだが、やや手間。 – 縮小バッファは、縮小バッファを作るところはCommandBufferで対応可 能そうだが、その後エフェクトを描画するところは別Cameraが必要。 (Layerが別なため) 39

40.

その3 RenderTextureとCamera管理 40

41.

描画システム Camera Camera Camera Camera RenderTexture RenderTexture RenderTexture RenderTexture RenderTexture RenderTexture RenderTexture RenderTexture prefab 41

42.

それぞれにスクリプトも 必要になる Cameraが複数必要 実行時に真っ先に ロードしないといけない Scene Game Sceneビューで確認できない! 42

43.

RenderTextureとCamera管理 — 複数のRenderTextureとCameraを管理する仕組みが必要。 それをprefabで用意して、起動時に適応させるしかない。 — 不都合が多く出てくる。 – 起動させないと絵が確認できない。(Sceneビューで見れない) – 実行した時にprefabを真っ先にロードする必要がある。 – Camera間を跨ぐScript処理も書かないといけない。 – 「Camera作ったらこのスクリプトも付けて!」も発生。 — 総じて管理、作成コストが大きくかかる! 43

44.

他にも もどかしいところが たくさん・・・ 44

45.

そこでSRP!! 45

46.

https://docs.unity3d.com/ja/2018.1/Manual/ScriptableRenderPipeline.html 46

47.

バイナリを作成 (RenderPipelineAsset) Graphics Settingsに設定 47

48.

特別なスクリプトも不要 (今回は追加しましたが。。) 48

49.

SRPの可能性 — SRPを使うと描画処理をほぼ乗っ取れるらしい? — 使い方も割と簡単。 – RenderPipelineAssetを作り、Graphics Settingsに設定。 – スクリプト(MonoBehaviour)も特に必要ない。 — Unity描画フローを使うより楽になるのではないか? レンダリング処理は完全に書かないとだけど。 49

50.

SRPの中身を作る(基礎) 50

51.

※弊社ブログで(近日中に)補足します https://logicalbeat.jp/blog/ 51

52.

「完全にカスタマイズ」 どのレベル? 52

53.

最小のRenderPipeline処理 53

54.

一切何も表示されない! 54

55.

LWRPを参考にしたい! 55

56.

— LWRPのパッケージをインストールした状態。 — Library/PackageCacheにインストールしてあるパッケージ の実データ(スクリプトなど)が収められている。 — LWRPは左図の赤枠のところに収められている。 56

57.

最初の取っ掛かり — SRPを新規に作ってRenderPipelineを空にする。 そうすると全く何も表示されない状態! – 「完全にカスタマイズ」なので、当然と言えば当然。 — 最初はLWRPを参考にすると進めやすいです。 – というより、他に無いです。 — LWRP自体はLibrary/PackageCacheにあるので、それを見る。 – LWRPを改造する場合もここから。 57

58.

描画の簡単な流れ 58

59.

最低限動作するRenderPipeline処理 59

60.

それに対応するシェーダ(Unlit相当) 60

61.

最低限の絵は実現できた 61

62.

カメラ一つずつに対して処理 最低限動作するRenderPipeline処理 62

63.

カメラのVPマトリクスなどを作ってる? レンダラやライト等のカリング処理 フィルタリング&ソート 描画命令 終了処理 最低限動作するRenderPipeline処理 63

64.

大きなポイントは 2箇所 64

65.

レンダラやライト等のカリング処理 フィルタリング&ソート 65

66.

レンダラやライト等のカリング処理 66

67.

不要なRendererとライトを省く 67

68.

https://docs.unity3d.com/ScriptReference/Rendering.CullingResults.html 68

69.

カリング処理 — カメラに対してオブジェクトの視錐台カリングを行う部分。 – カメラからカリングのための情報を取得。 – – Camera.TryGetCullingParameters()で行う。 結果は「CullingResult」に格納される。 — ライトのカリングも行われる。 – 視錐台の外にあって、オブジェクトに影響を及ぼさない点光源などはここ で排除される。 – CullingResults.visibleLights — シャドウも考慮。 69

70.

フィルタリング&ソート 70

71.

0 2500 LightModeの合致 Queueが範囲内 2000 71

72.

描画対象Layer設定 72

73.

手前から奥に描画 https://docs.unity3d.com/ScriptReference/Rendering.SortingCriteria.html 73

74.

ソート&フィルタリング処理 — 描画する部分を抑制する処理。 – 半透明だけ描く、不透明だけ描く。 – 特定のレイヤーは描画しない。(UIなど) – 描き方の種類を変える。(LightMode) — オブジェクトのソートの指定方法もここで行う。 – 不透明ならば手前から描く。半透明ならば奥から描く、とか。 — 独自にルールを作れる!! 74

75.

シンプルながらも 描画が出来た! 75

76.

SRPの中身を作る(拡張) 76

77.

自由に構築していい!! 77

78.

実験 縮小バッファ対応 78

80.

Camera.targetTexture LightMode=lbForward Queue→0~2500 Blit RT(A) Copy Depth LightMode=lbParticle Queue→2500~3000 RT(B) 単一のCameraで実現できる!! 80 Merge

81.

Camera.targetTextureの 縦横70%サイズのRT(A)を用意 RT(B)にLightMode=lbParticle のみ描画 RT(A)にQueue→0~GeometoryLast まで描画(要するに不透明描画) RT(A)のカラーバッファに RT(B)のカラーバッファを合成 RT(A)にポストフィルタ描画(SSAO等) RT(A)にポストフィルタ描画(ブルーム等) RT(A)の縦横1/2サイズのRT(B)を用意 Camera.targetTextureにRT(A)をコピー RT(B)のデプスバッファに RT(A)のデプスバッファをコピー World UI(体力ゲージ的なの)を描画 81

82.

SRP処理内での拡張 — カメラのデフォルトターゲットに最終的な絵が出力されれば、そ の過程はかなり自由に処理してしまって構わない。 – デフォルトターゲットとは別のRenderTextureを用意して描く。 – シャドウマップのフォーマットを別のものにする、など。 — 縮小バッファも対応できた。 – デプスバッファを縮小コピーした上でブレンドバッファ描画。 — Deferredに限らず、Forward+も実現できるかもしれない。 – Compute Shaderが動かせればチャンスあるかも。 82

83.

Unityの機能は どれくらい活用できるか? 83

84.

ReflectionProbeの適応 84

85.

ビルトインシェーダでのunity_SpecCube0利用 85

86.

unity_SpecCube0を使ってみた 86

87.

DrawingSettings.perObjectData PerObjectData.ReflectionProbes https://docs.unity3d.com/ScriptReference/Rendering.DrawingSettings.html https://docs.unity3d.com/ScriptReference/Rendering.PerObjectData.html 87

88.

設定を追加 88

89.

unity_SpecCube0が適応できた 89

90.

ReflectionProbeの適応 — シェーダ内でunity_SpecCube0を参照しても適応されない! — LWRPを調べてみると「DrawingSettings.perObjectData」に 「PerObjectData.ReflectionProbes」を設定していた。 – オブジェクト毎にどの描画設定を適応するか?の設定。 – 恐らく、SH(LightProbes)も適応できると思われる。 — ※unity_SpecCube0使用時は、「Light –Environment Reflections」の設定に気を付ける。 90

91.

PostProcessing Stack の適応 91

92.

PPS適応前 PPS適応後 ※Lee Perry-Smith の Infinite 3D Head Scan。クリエイティブ・コモンズ・ライセンス 3.0 (www.ir-ltd.net で入手可能) 92

93.

適応したPPS 93

94.

PostProcessing Stackの OnPreCull()とOnPreRender() 94

95.

SRP利用時は動作しないようになっている! 95

96.

private関数なので外から呼べない! 96

97.

PostProcessingRenderContextというのがあったので それを活用して実現 97

98.

PostProcessing Stackの利用 — どうせならPostProcessing Stackを利用したいので試みる。 – 一からポストフィルタを作りたい気持ちはあるが、エンジンの機能はやは り活用できると好ましいので。 — 本家はCameraに付与すれば良かったが動作せず。 — こちらもLWRPで調査。 — 「PostProcessingRenderContext」を活用することで解決した! 98

99.

デフォルトUIシェーダ の活用 99

100.

100

101.

ビルトインシェーダのUI/Default LightModeが存在しない!! 101

102.

LWRPのUI描画部分 SRPDefaultUnlitにすると 表示される!

103.

デフォルトUIシェーダの活用 — さすがにUIまで手を付けたくないので、既存のを使いたい。 だがデフォルトのUIシェーダはLightModeが無い! — 例によってLWRPを調査。 — どうも「SRPDefaultUnlit」というのが該当LightModeだったよう なので、それを使って対処。 103

104.

SRPの中身を作る(その先へ) 104

105.

小ネタをいくつか (※未検証のもあります) 105

106.

デフォルトシェーダの変更 106

107.

新規マテリアル生成時に 特定のシェーダを付与してくれる! https://docs.unity3d.com/ScriptReference/Rendering.RenderPipelineAsset.html 107

108.

デフォルトシェーダの変更 — 独自シェーダを構築すると、デフォルトマテリアルも変えたくなる。 そんな要望もキチッとサポートされている。 — 通常モデル、UI、パーティクルなど、種類ごとに設定可能。 — RenderPipelineAssetのプロパティをoverrideすることで対応。 108

109.

カリング方法の微調整 (※検証不足) 109

110.

カリングに負荷がかかる! ので、あえて行わないようにしたいことがある 110

111.

Cameraのカリングパラメータ cullingOptionsが怪しい? https://docs.unity3d.com/ScriptReference/Rendering.ScriptableCullingParameters.html 111

112.

ので、メンバを調査 CullingOptionsのドキュメントが無い!! https://docs.unity3d.com/ScriptReference/Rendering.ScriptableCullingParameters-cullingOptions.html 怪しいの発見 112

113.

None 結果は変わらず・・・ DisablePerObjectCulling 113

114.

カリング方法の微調整 — カメラから取得したカリングパラメータを編集することにより、カ リングの仕方を微調整できそうな印象がある。 — オブジェクトカリングを敢えてしたくない局面もあるので、それが 出来ないか試してみることに。 – カリング処理でCPU負荷がかさんでしまうため。 – 特にUIなどでは不要なので、ずっとやりたかった。 114

115.

カリング方法の微調整 — が、それっぽい「CullingOptions.DisablePerObjectCulling」を試 してもダメだった。 – ※余談ですが、「cullingPlaneCount」を変更してもダメでした。 — そもそもドキュメントに無いので、あまりオープンになっていない 機能かもしれない。 情報開示されると嬉しいです。 115

116.

まとめ & 要望 116

117.

まとめ — SRPを一から組んで、独自の描画フローを構築できた。 – 描画処理に詳しい人ほど、既存描画フローの挙動に悩まされることがある と思うので、気持ちいいことは気持ちいい。 – 他エンジンではこういった事が出来ないので、非常にポイント高い。 — 処理的にもスリム化が図れるので、描画処理が組める人は一か ら組んでも良いかもしれない。 – 非Unity系からの移植や、トゥーン系ならやりやすそう。 — Camera一つで完結するのも大きい! 117

118.

まとめ — が、エンジンの機能を享受しつつ独自フローを書くとなると、結局 調べ物が多くなる。 – 今回ならReflectionProbeなど。 – LWRPを調べつつ進めるスタンスになると思います。 — LWRPをベースに改造するスタンスも良いかと思います。 – ゲーム的に必要な機能が出てきたら改造する、的な。 — 一から組めるので、敢えて学生さんの勉強などにも良いかも。 118

119.

要望 — 要望として、LWRP自体の情報は出始めていますが、SRPを一か ら作る話をあまり見かけません。 ドキュメントも整備されていないです。 – 今回ならCullingOptionsなど。 — 細かい要望点は多いですが、とにかく情報が欲しいです。 — 今回の講演で「SRPで一から作ってみよう!」という人が増えてき て、情報が多く出てくると幸いです。 119

120.

Thank you!! Twitter:@yoshiking2000 Twitter:@logicalbeat_jp