こんにちわ、Unityエンジニアのオオバです。

前回超基本編として
Universal Render Pipeline(以下:URP)
拡張方法を紹介しました。

とても簡単にわかりやすく紹介していますので、
URP拡張に興味ある方はぜひ見てください。
導入としてちょうど良いと思います
👉オススメ記事 : 【超基本編】URPに独自のパスを追加する方法

前回との違いは、
シェーダーを使っていることです。

【今回作るもの】不透明オブジェクトにシェーダーを適用するURP拡張

不透明オブジェクトにシェーダーを適用

不透明のオブジェクトだけにカラー乗算するという
URPの描画拡張を作っていきます。

今回の本質はシェーダーを使ったURPの拡張のため、
シェーダーの内容は超簡素です。

基本をおさえた上で難しいシェーダーを書いていきましょう。

📝 目次

FeatureとPassの用意

URPを拡張する上ではおなじみの手順です。

それぞれScriptableRendererFeature
ScriptableRenderPassを継承して作成します。

URP ForwardRendererの
Renderer Featuresに追加します。

URP ForwardRendererに追加した状態

【超基本編】URPの拡張にシェーダーを使う方法_56

このあたり前回記事で丁寧に紹介していますので、
そちらをご確認ください。
👉オススメ記事 : 【超基本編】URPに独自のパスを追加する方法

シェーダーの用意

💻ソースコード : HelloWorldShader.shaderの抜粋
fixed4 frag (v2f_img i) : SV_Target  
{
    return tex2D(_MainTex, i.uv) * _Color;  
}

各ピクセルを_Colorプロパティを
乗算するシンプルなシェーダーです。

シェーダーの全ソースはコチラです。
※シェーダー全文は記事末尾に公開しています

このシェーダーファイルをFeatureにセットします。

💻ソースコード : HelloWorldShaderRendererFeature.cs
[SerializeField] private Shader _shader;  

Materialを生成してPassに渡す

FeatureとPassの関係を思い出しましょう。

FeatureとPassの関係図

【超基本編】URPの拡張にシェーダーを使う方法_88

FeatureはあくまでPassの生成器。
Passは描画処理担当です。

FeatureはPassにShaderをセットした
Materialを渡します。

💻ソースコード : HelloWorldShaderRendererFeature.cs
public override void Create()  
{
    // ShaderからMaterialを生成  
    var material = CoreUtils.CreateEngineMaterial(_shader);  
    // PassにMaterialを渡す  
    _pass = new HelloWorldShaderPass(material);  
}

シェーダーからMaterialを作る時は、
CoreUtils.CreateEngineMaterialメソッドが便利。
再生終了時に自動でMaterialの破棄をしてくれます。
※動的に生成したMaterialは破棄しないとリークします

レンダーターゲットにシェーダーを適用

今回の肝、シェーダーの適用です。

描画のフローの流れ
  1. RenderTexture生成
  2. カメラ画像をRenderTextureにコピー
  3. RenderTextureをカメラ画像にコピー

2. カメラ画像をRenderTextureにコピーのタイミングで
シェーダーを適用します。

💻ソースコード : HelloWorldShaderPass.cs Executeメソッド内
// カメラ画像をRenderTextureにコピー  
commandBuffer.Blit(_currentRenderTarget, RenderTargetTexId, _material);  

CommandBuffer Blitメソッドの第3引数に
Materialを渡すことでシェーダーは適用されます。

Blitメソッドの解説

【超基本編】URPの拡張にシェーダーを使う方法_135

CommandBuffer.Blitメソッドの各引数

※第1,2引数にはRenderTextureを直接セットしません。紐づくIDを指定する仕様です。

もっとわかりやすくした図はコチラ。

【超基本編】URPの拡張にシェーダーを使う方法_145

Blitメソッドをまとめると、
元画像をコピーしてシェーダーを適用。
シェーダーを適用したデータを
書き出し画像に書き込みます。

↑これだけ覚えておきましょう。

_MainTexで元画像をシェーダーから参照

Blitメソッドの第1引数のカメラ画像は
シェーダーからどのように参照すればよいでしょうか。

答え : シェーダー内で定義した、
_MainTexという変数に格納されます。

このあたりはUnityの仕様です。

@ref:https://docs.unity3d.com/ja/2021.1/ScriptReference/Rendering.CommandBuffer.Blit.html

今回実装した画像処理を振り返ります。
該当するシェーダー処理はコチラ。

💻ソースコード : HelloWorldShader.shaderの抜粋
fixed4 frag (v2f_img i) : SV_Target  
{
    return tex2D(_MainTex, i.uv) * _Color;  
}

_MainTex(カメラ画像)の
各ピクセルを_Colorで乗算しています。

カメラに映し出された画像に
指定の色で塗られる処理になります。

処理した画像をカメラに戻す

RenderTextureをいくら加工しても
カメラ画像に戻さなければ見た目は変わりません。

シェーダー適用したRenderTextureをカメラに映し出す処理
// RenderTextureにシェーダーを適用  
commandBuffer.Blit(_currentRenderTarget, RenderTargetTexId, _material);  

// シェーダー適用したRenderTextureをカメラ画像にコピー  
commandBuffer.Blit(RenderTargetTexId, _currentRenderTarget);  

再度Blitメソッドが登場します。
処理済み画像をカメラ画像にコピーして
モニタ上の見た目を更新します。

【超基本編】URPの拡張にシェーダーを使う方法_206

このように、シェーダーを適用したURP拡張ができました!

もう少し続けます。

シェーダーのパラメータを動的に更新する方法

URP拡張にシェーダーを適用できました。
このシェーダーのパラメータを動的に変えてみようと思います。

調整したいFeatureにColorパラメータを
public変数として公開します。

public Color color;  

するとインスペクタからカラーを
変更できるようになります。

HelloWorldShaderRenderFeatureのインスペクタ

【超基本編】URPの拡張にシェーダーを使う方法_228

図にするとこんなイメージです。

【超基本編】URPの拡張にシェーダーを使う方法_232

このcolorを毎フレーム更新することで
リアルタイムに変更できます。

【超基本編】URPの拡張にシェーダーを使う方法_238

まとめ

シェーダーを使ったURPの拡張方法を紹介しました。

😺 大事なポイント

前回、今回記事を通して基本的な
URPの拡張方法を理解できたかと思います。

おつかれさまでした。

次回から、より複雑な題材をテーマに
URPの拡張をしていきたいと思います。

お楽しみに!

ソースコード全文はこちら

最後にサンプル全ソースを公開しておきます。
サンプルも内包されて分かりづらいですが、
Assets/HelloWorldRendererFeatureSampleフォルダ
今回のサンプルは入っています。

何か参考になれば幸いです。
Page not found · GitHub · GitHub

👉 オススメ記事

2021秋 Asset Refreshセール
100以上のアセットがなんと50%OFF!!オオバもいくつか買いました!
期間 : 10月2日午後3時59分まで

👩‍💻 検証環境

🙏 参考サイト