Edited at

【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を組み込んだことによって直感的にポストエフェクトを組める環境が作れたのではないかと感じています。