Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
34
Help us understand the problem. What is going on with this article?
@r-ngtm

【Universal Render Pipeline】ShaderGraphをポストエフェクトとして使ってみる

はじめに

Universal Render PipelineのForwardRendererDataやScriptableRendererFeatureを利用すると、
レンダリングパイプラインに独自の処理(レンダリングパス)を追加することができます。

今回はレンダリングパイプラインの最後にシェーダーグラフを突っ込み、フォグ風の表現を実現するポストエフェクトを作ってみました。
before_after_merge.png

作成したレンダリングパイプラインはCameraコンポーネントのプルダウン上から簡単に切り替えることができてお手軽です。
change_renderer.gif

フォグ風ポストエフェクトの実装について

カメラのデプス値(深度情報)を利用して二つの色をLerpで合成し、それを画面に表示させています。

色の計算式
画面に出力する色 = Lerp(カラーA, カラーB, デプス値)

環境

【Unityバージョン】
Unity2020.1.0a3

【パッケージ】
Universal Render Pipeline - Version 7.1.2

デプスバッファを使うための設定

パイプラインアセットの Depth Texture のチェックを入れ、シェーダーグラフ上でデプスバッファが取れるようにします。

image.png

STEP1 : マテリアルの準備

STEP1.1 : シェーダーグラフ作成

ProjectビューのメニューからCreate/Shader/Unlit Graph を選択し、Unlitのシェーダーグラフを作成します。
image.png

今回はRenderDepthSimpleという名前にしてみました。

STEP1.2 : シェーダーグラフ編集

シェーダーグラフにTexture2Dプロパティを定義し、名前を _CameraDepthTexture にすると、カメラのデプスバッファ(深度情報)が取得できます。
このデプスバッファを利用して、二つの色をLerpノードで合成し、Unlit Masterノードに出力します。
image.png

_CameraDepthTextureのExposedのチェックはOFFにしておきます
image.png

以上でシェーダーグラフは完成です。

STEP1.3 : マテリアルを作成

シェーダーグラフを右クリックし、マテリアルを作成します。
image.png

Shader Graphs_RenderDepthSimpleという名前のマテリアルが作成されます。
作成されたマテリアルのシェーダーには先ほどのShaderGraphが設定されていることが確認できます。
image.png

STEP1.4 : マテリアルをResources以下に配置

Assets/Resources/Materials フォルダを作成し、その中にマテリアルを移動させます。
マテリアルの名前は RenderDepth にします。
image.png

以上でマテリアルの準備は完了です。

STEP2 : Rendererアセットの作成・カメラへの登録

Rendererアセットを作成し、これをカメラに登録することでレンダリングパイプラインに独自の処理を差し込むことができます。
今回はレンダリングの最後にシェーダーグラフを実行させるようなレンダリングパイプラインを構築します。

STEP2.1 : Rendererアセットの作成

Projectビューから
Create/Rendering/Universal Render Pipeline/Forward Renderer を選択して
ForwardRendererアセットを作成します。
今回はRenderDepth と名付けました。
image.png

STEP2.2 : Rendererアセットをリストへ登録

自作のRendererアセットはパイプラインアセットのRendererListへ登録すると

CameraコンポーネントのRendererのところから選べるようになります。
image.png

image.png

カメラのRendererを切り替えることで、レンダリングパイプラインを切り替えることができます。

STEP2.3 : Renderer Featureを作成する

作成したRendererに自作レンダリングパスを追加するためには、Renderer Featureを作成する必要があります。

Projectビューのメニューから
Create/Rendering/Universal Render Pipeline/Renderer Feature を選択すると
Renderer Featureが作成されます。

今回はRenderDepthFeatureという名前にしました。(RenderDepthFeature.csが作成されます)

image.png

STEP2.4 Renderer Featureを書き換える

作成したRenderDepthFeature.csを以下のように書き換えます。

STEP1のRenderDepthマテリアルをロードし、カメラの描画をマテリアルで上書きする処理になっています。

RenderDepthFeature.cs
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class RenderDepthFeature : ScriptableRendererFeature
{
    class CustomRenderPass : ScriptableRenderPass
    {
        public Material material; // レンダリングに使用するマテリアル

        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            if (material == null) return;

            var camera = renderingData.cameraData.camera; // 現在レンダリングを行っているカメラ
            var cmd = CommandBufferPool.Get("RenderDepth"); // 適当なコマンドバッファをとってくる
            cmd.Blit(Texture2D.whiteTexture, camera.activeTexture, material); // カメラにマテリアルを適用

            context.ExecuteCommandBuffer(cmd); // コマンドバッファ実行
            context.Submit();
        }
    }

    CustomRenderPass m_ScriptablePass;

    public override void Create()
    {
        m_ScriptablePass = new CustomRenderPass();
        m_ScriptablePass.material = Resources.Load<Material>("Materials/RenderDepth"); // Resources/Materials/RenderDepth.matをロードする
        m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRendering; // レンダリングが終わった後にレンダリングパスを実行
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderer.EnqueuePass(m_ScriptablePass);
    }
}

STEP2.5 Renderer FeatureをForward Rendererアセットに登録

STEP2.1で作成したForwardRendererアセットにSTEP2.3で作成したRenderer Depth Featureを登録します。

image.png

image.png

STEP2.6 レンダリングパイプライン完成

ヒエラルキーにあるCameraコンポーネント上のRendererから RenderDepthを選択すると、画面の表示が変化します。
camera_select.gif

レンダリングの終了タイミングでシェーダーグラフが実行され、画面に反映されるようなレンダリングパイプラインの完成です。

STEP2.7 色を変えてみる

マテリアルのパラメータを変更すると、即座に画面にも反映されます。
change_color.gif

まとめ

今回、ShaderGraphをポストエフェクトとして利用するようなレンダリングパイプラインを簡単に実装することができました。

直感的にシェーダーを組めるのがShaderGraphの強みですが、
レンダリングパイプラインにShaderGraphを組み込んだことによって直感的にポストエフェクトを組める環境が作れたのではないかと感じています。

追記 : Unity2019.4LTS でやりたい場合

Unity2019.4 だと RenderPassEvent.AfterRendering+1FinalPostProcessPassFinal Blit Pass が入るため、
今回追加したポストプロセスPassが握りつぶされてしまいます。

これはRenderDepthFeature.csCreateメソッドを以下のように書くことで回避できます。

RenderDepthFeature.cs
public override void Create()
{
    m_ScriptablePass = new CustomRenderPass();
    m_ScriptablePass.material = Resources.Load<Material>("Materials/RenderDepth"); // Resources/Materials/RenderDepth.matをロードする
    m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRendering + 2; 
}
34
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
r-ngtm

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
34
Help us understand the problem. What is going on with this article?