Search Unity

2018.1 ベータ版 で初登場したスクリプタブルレンダーパイプライン(SRP)は、Unity でのレンダリングの設定や実行を C# スクリプトで制御できる仕組みです。カスタムのレンダリングパイプラインを書くに当たっては、まずレンダリングパイプラインとは何かを理解する必要があります。

レンダリングパイプラインとは

「レンダリングパイプライン」は、オブジェクトを画面に表示させるために使用される様々な技術を指す包括的な用語です。レンダリングパイプラインには、大まかに言うと次の要素が含まれます。

  • カリング
  • オブジェクトのレンダリング
  • ポストプロセッシング

上記の各要素は、それぞれどのような方法で実行するかによってさらに細かく分けることができます。例えば、オブジェクトのレンダリングの実行方法には以下のような選択肢があります。

  • マルチパスレンダリング
    • オブジェクトに 1 パス、ライトに 1 パス
  • シングルパスレンダリング
    • オブジェクトに 1 パス
  • デファードレンダリング
    • 面のプロパティを G バッファにレンダーし、スクリーン空間ライティングを実行する

カスタム SRP を書くに当たっては、上記のような事柄の選択を行う必要があります。それぞれの選択肢の長所と短所を考慮した上で決断することが必要となります。

デモプロジェクト

本記事で解説している機能のすべてがGitHub 上にあるデモプロジェクトに網羅されています。

レンダリングのエントリポイント

SRP を使用する際には、レンダリングを制御するクラスを定義する必要があります。これが、作成していくレンダリングパイプラインとなります。エントリポイントは「Render」の呼び出しで、これは引数としてレンダリングのコンテキスト(以下参照)と、レンダリングされるカメラのリストを取ります。

レンダリングパイプラインコンテキスト

SRP は、遅延実行という概念に基づいてレンダリングを行います。ユーザーは、コマンドのリストを構築していき、それらを実行します。このコマンドの構築に使用するオブジェクトを ScriptableRenderContext と呼びます。コンテキストに処理を追加したら、Submit を呼び出すことによって、キューに入ったすべてのドローコールをサブミットします。

そのひとつの例は、レンダーターゲットを、レンダリングコンテキストの実行するコマンドバッファを使用して消去する場合です。

あまり面白くないレンダリングパイプラインですね?

画面に描画された図形をすべて消去するレンダリングパイプラインの全体はこちらでご確認いただけます。

カリング

カリングとは、画面に何を描画するかを算出していくプロセスです。

Unity におけるカリングには以下が含まれます。

  • 【錐台カリング】カメラのニアおよびファーのクリッピング平面の間にあるオブジェクトを計算します。
  • 【オクルージョンカリング】どのオブジェクトが別のオブジェクトの影に隠れるかを計算し、それらをレンダリングの対象から除きます。詳細はオクルージョンカリングに関するドキュメントをご覧ください。

レンダリング開始時、まず最初に計算されなければならないのは、何をレンダーするかです。この計算には、カメラの取得および、そのカメラの視点でのカリング処理の実行が含まれます。カリング処理は、そのカメラから見てレンダリングする意味のあるオブジェクトおよびライトのリストを戻します。これらのオブジェクトはレンダリングパイプライン内で後に使用されます。

SRP におけるカリング

SRP では基本的に、カメラの視点からオブジェクトのレンダリングを行います。このカメラは Unity がビルトインのレンダリングで使用するカメラオブジェクトと同じものです。SRP ではカリングに使用できる API を多数提供しています。大まかな処理の流れは以下のようになります。

カリング処理の結果が格納され、そのデータを使ってレンダリングを行う準備が整いました。

描画

カリング処理の結果が揃ったので、そのデータを使って画面に描画を行うことができます。

しかし、設定可能な要素が数多くあるため、この時点ですでにいくつかの決定を行う必要があります。これらの決定の多くは以下の条件に基づいて行います。

  • レンダリングパイプラインのターゲットにするハードウェア
  • 目指すビジュアルスタイルや雰囲気
  • どんなタイプのプロジェクトを開発するか

例えば、モバイル 2D 横スクロールアクションゲームと、PC 向けのハイエンドの一人称視点ゲームを考えてみましょう。これらのゲームそれぞれの持つ制約は非常に異なっているため、レンダリングパイプラインもまた非常に異なるものとなります。具体的にここで決定が必要になるのは、例えば以下のような事柄です。

  • 高ダイナミックレンジ(HDR) vs 低ダイナミックレンジ(LDR)
  • リニアワークフロー vs ガンマワークフロー
  • マルチサンプルアンチエイリアシング vs ポストプロセスアンチエイリアシング
  • 物理ベースレンダリングマテリアル vs 通常のマテリアル
  • ライティングあり vs ライティングなし
  • ライティングの手法
  • シャドーイングの手法

レンダリングパイプラインを書くに当たっては、上記のような事柄を決定しておくことで、実際に作成する際にどんな制約が課せられるか把握しやすくなります。

ここでは、一部のオブジェクトを不透明に描画できる、ライトなしのシンプルなレンダラーを例に取って見てみましょう。

フィルタリング(レンダリングバケットとレイヤー)

基本的には、レンダリングするオブジェクトに特定の分類がある場合、それは不透明オブジェクトであったり、透明オブジェクトであったり、表面下オブジェクトであったり、あるいはその他多数の分類が当てはまる場合もあります。Unity ではオブジェクトがレンダーされるべきタイミングをキューの概念によって表します。このキューがバケットを形成し、その中にオブジェクトが置かれます(そのオブジェクト上のマテリアルがソースになります)。SRP からレンダリングの呼び出しがあった時に、どのレンジ(範囲)のバケットを使用するかを指定できます。

バケットの他に、Unity 標準のレイヤーもフィルタリングに使用できます。

これにより、SRP 経由でオブジェクトを描画する際に、より豊富な種類のフィルタリングを行えるようになります。

描画設定(どのように描画するか)

フィルタリングとカリングの使用により何を描画するかが設定されますが、どのように描画するかも設定する必要があります。SRP では、フィルタリングを通過したオブジェクトの描画方法を多様に設定できます。このデータの設定に使用されている構造体は「DrawRenderSettings」です。この構造体で様々な設定を行えます。

  • Sorting – オブジェクトをレンダーする順序です(背面から前面の順、前面から背面の順など)。
  • Per Renderer フラグ – どの「ビルトイン」設定を Unity からシェーダーにパスするかの設定です。これにはオブジェクト毎のライトプローブや、オブジェクト毎のライトマップなどが含まれます。
  • Rendering フラグ – バッチングの使用有無、インスタンシングの使用有無を制御するフラグです。
  • Shader Pass – 現在のドローコールにどのシェーダーパスを使用するかの設定です。

描画

これで、ドローコールを発行するために必要な 3 つの要素が揃いました。

  • カリング処理の結果
  • フィルタリングの規則
  • 描画の規則

これでドローコールを発行できます!SRP における他の要素と同様、ドローコールもコンテキスト内への呼び出しとして発行されます。SRP では通常、個々のメッシュのレンダリングを行う代わりに、一度に大量のメッシュをレンダーする 1 回のコールを発行します。これにより、スクリプトの実行オーバーヘッドが削減されるだけでなく、CPU 上でのジョブ化・実行も速くなります。

ドローコールを発行するために、これまで構築してきた関数を組み合わせます。

これにより、現在紐づけられているレンダーターゲットにオブジェクトが描画されます。コマンドバッファを使用してレンダーターゲットを切り替えることもできます。

不透明オブジェクトを描画するレンダラーをこちらのリンクから入手できます。

https://github.com/stramit/SRPBlog/blob/master/SRP-Demo/Assets/SRP-Demo/2-OpaqueAssetPipe/OpaqueAssetPipe.cs

下記リンクの例をさらに拡張して透明オブジェクトのレンダリングを加えることも可能です。

https://github.com/stramit/SRPBlog/blob/master/SRP-Demo/Assets/SRP-Demo/3-TransparentAssetPipe/TransparentAssetPipe.cs

透明オブジェクトをレンダリングする際は、レンダリングの順序は背面から前面の順に変更されるということにご注意ください。

本記事が、皆様がカスタム SRP の作成を始めるに当たっての足掛かりとなれば嬉しく思います。早速 2018.1 ベータ版 をダウンロード して作成を始めてみてください。そして、こちらのフォーラムのスレッドに是非ご意見をお寄せください!

23 コメント

コメントの配信登録

返信する

これらの HTML タグや属性を使用できます: <a href=""> <b> <code> <pre>

  1. Is it possible somehow to get the data from a RT in the CPU or copy it directly from VRAM to RAM?
    I need to access the content in the CPU per frame.

  2. Great job. A good render, I learned a lot of useful things.
    192.168.l.l

  3. Objects with Standard Shader are not rendering in Opaque and Transparent Asset Pipes, do I need a special material or other setting up to perform?

  4. Looks really good so far, now we just need some intermediate pipelines to learn from:)
    While the Basic is very easy to understand and get along, the HD seems like a complete framework of it’s own and too much to grasp without very thorough study…
    Are there any intermediate pipelines out there or used internally, like Deferred only with basic feature support (shadows, lightmapping, …), to learn from?

  5. Thanks for the much needed introduction!

    I use these extensively:

    Camera.AddCommandBuffer( CameraEvent evt, CommandBuffer buffer )
    Light.AddCommandBuffer( LightEvent evt, CommandBuffer buffer )

    How do they work in SRP? How are the buffers picked up and how are CameraEvent and LightEvent handled?

  6. I suspect that Unity actually has two goals here:

    (1) Make a scriptable render pipeline, which brings great opportunities, and is pretty much required for AAA development studios to consider the platform. Oh, and it’s technically awesome.
    (2) Make two new “standard” render pipelines targeting core markets of mass-market mobile and PC/Console gamedev.

    The fact that the business goal of (2) can be implemented in terms of the technical goal (1) is a nice bonus.

    The existing render pipelines are not feature competitive with modern AAA titles, and they’re too fill rate intensive to use for a mass-market mobile title. So Unity has a market need for this change to make render pipelines for those targets because that’s what their customers want. Making the pipeline scriptable at the same time is a bonus, but opens up a world of divergence that could make code-based assetstore assets even more impossible to rely on than they already are.

    The end results of this change will see a massively improved Unity and are undoubtedly the right thing to do. But I’d caution that this is a hard change to make (it took EA and the Frostbite team a long time and they had the advantages of full source code and everyone being part of the same company…) I am greatly concerned about whether the wider Unity (including their customers with existing games, and the asset store vendors) will be able to support each other through this transition.

    I struggle to look at the recent history of “open” Unity systems (Navmesh Components, UNET HLAPI, and Unity.UI’s definition of “open source” is interesting…) and believe that that model will transition well to supporting an “open” renderer. But of course, maybe that is not a required goal. Maybe the goal is really the two new LW and HD pipelines, plus the self-documenting benefits of having the C# source act as the documentation, and that alone does seem a great step forward.

    A Unity world where render algorithms are highly customizable but where artist workflow X only works with pipeline Y assuming you’re using asset store customizations Z but not W (and assets built assuming the previous assumptions) may not drive higher quality visuals overall.

    1. I am afraid until people “play” “games” on their phones this is the only way to go forward. Your scenario is likely, but my point is that it is unavoidable.

    2. As an asset publisher that has been involved in the ongoing talks in the forums about this very topic…there are some reasons to be worried indeed.

      SRPs are not cross compatible and asset vendors will need to give explicit support to each one of them (both the standard unity ones and any popular custom ones) if we want users to be able to use our assets.
      We have been told this won’t be mandatory, which means that not every developer will port their assets to every SRP and thus some assets won’t be available in some SRPs.

      Furthermore, if you write your very own SRP you will be left without any compatible assets unless you take the extra care to write all the handlers, importers and compatibility fixes by yourself or find a very good asset vendor willing to spend his/her time helping you port their assets to your own SRP.

      SRPs are a very good idea indeed, but it has been a worry so far (due to this feature being in a VERY early state and with almost no information available to asset creators ) that they will end up splitting most of the Asset Store community of both customers and vendors. Our main worry is the compatibility and support nightmare that it will unleash over all asset creators by giving them at least 3 times more work to support their assets as well as the added difficulties for new users who may end up with little to no assets compatible with the SRP of their choice or demanding asset providers to support a never ending stream of new custom SRPs without understanding the technical limitations behind each and every port.

      But it is indeed an interesting topic and very probably a needed step, just a very risky one. We’ll need to follow it to see how it goes

  7. Sergey Klimenko

    2月 2, 2018 10:25 pm 返信

    Very nice!

  8. Just out of curiosity: Does SRP allow to share the culling result of one camera with others? Think of mirrors for a vehicle. In a car you have typically 3 mirrors looking into the same direction. All three render from a slightly different position and different parts of the rendered result are obstructed by the car geometry itself but in fact all three cameras do the same culling operations. If it would be possible to use the culling result of one camera for the other two aswell could save some performance in vehicle simulations imho.
    Despite of this maybe stupid question this stuff sounds exciting :-)

    1. Seems you have two options, either use the culling result from the main camera for all three or build up your own matrices and populate the ScriptableCullingParameters manually:) Do need some modifications to the SRP though, identifying the three cameras you want to share your culling with and handle that in the camera render loop.

      1. Thanks for the clarification :-)

  9. As a long time mobile dev, with minimal experience in how graphics engines actually work, this was an extremely helpful article.

    I kept reading about the “Scriptable Rendering Pipeline” and thought: “That sounds great! …I think? Too bad it probably won’t be useful to us.”

    As it turns out, I think we have an actual use for it in our current project.

  10. Great article!

  11. Well done unity Team

  12. this image could be rendered in unity 2.6, use the translucent mushroom that this French guy showed on twitter

  13. Excellent info. While I love unity managing all this for me in most cases, I can think of a few projects where I would love to customize a SRP to make novel visual styles. I look forward to playing with all of this soon!

  14. Thanks for the information, Tim. I appreciate these docs (hoping these blogs will make their way to the actual docs too).

    Also, can people not be rude and splat their wishlists on every blog posting. You guys realise that will never work, right?

  15. Dead excited for this. Well done unity team!

    You usually find me on the forums complaining about stuff that the Unity team has promised for a while but not delivered on (with good reason, there are a few things missing for a while that hold me and many off from subscribing!).

    So I am very very happy to see that for once you are prioritizing the importance of the engines fundamentals in a release, instead of adding lots of extra but crappy services and unfinished systems.

    BUT PLEASE:

    FINISH NESTED PREFABS

    UPDATE TERRAIN SYSTEM

    ADD SMARTSPRITE

    FIX AND DOCUMENT PROPERLY TIMELINE

    These 3 things have really been too long waited for now, its sort of a necessity for an engine with over 50% of all developers in the world using it to have an up to date terrain and spline based 2D terrain system.

    Keep up the good work!

    1. I am with you, man. I am really mad about core engine features being outdated and literally crappy. SRP looks like a real step forward, and I hope they will fix other systems in 2018 as well. Because Unity should be on a high level not just partially.

    2. I will join you too :) Pls, don’t forget about 2d animation (like builtIn anima2d).

      1. But Anima2D is a part of Unity now, like Cinemachine or TextMeshPro…

    3. PLEASE STOP