見出し画像

【URP】Unityでアウトラインのカメラエフェクトを作る【ShaderGraph】

出来たもの

画像28

仕組み

カメラに写ってる画像と、その画像をほんのちょっと拡大したものを用意して、2つの画像の差分を取得することで「画像内の、色が変わる境界線」を取得します。

画像4


この画像を使って、「黒い部分は元の画像を表示し、黒くない部分はアウトラインとして塗りつぶす」って感じで作ります。

自分でも何言ってるかよくわかんないです。


準備

まず、URPプロジェクトであることを確認してください。

URPじゃないとShaderGraphを使えません。

Create>Shader>Universal RenderPipeline>Unlit Shader Graphで新規ShaderGraphを作ります。

画像5


作成したShaderGraphのアイコンの上で、Create>Materialで上記シェーダーを使った新規マテリアルを作成します。

画像6


次にCreate>Rendering>Universal Render Pipeline>Renderer Featureで新規RendererFeatureを作ります。

画像7


現在使用中のFowardRendererのAdd Renderer Featureを押して、さっき作ったRendererFeatureを貼り付けます。

画像8


【FowardRendererの場所】

画像9

Edit>Project Settingから


画像10

GrahicsのScriptable Render Pipeline Settingの中のアセットをダブルクリックして、


画像11

General>Renderer Listの中のアセットをダブルクリックすると出てきます。

フォルダの場所を覚えといたほうが後々便利です。


コードをちょっと書く

Renderer Featureのコードをこんな感じに書き換えます。

using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Serialization;

public class CameraEffectFeature : ScriptableRendererFeature
{
   [SerializeField] private Material material;

   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(string.Empty);
           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 = material;

       m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRendering + 2;
   }

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

【注意!!!】

紛らわしいのですが、デフォルトで、Create()内の

m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;

になってるところは

m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRendering + 2;

に書き換えてください。

画像12


画像13


コードを書く部分は、class CustomRenderPass内のExcute()と、Create()だけです。

コーディング部分はこれで終わりです。


画像14


コードを書いたので、さっき作ったFowardRendererに張り付けたRenderFeatureにマテリアルを参照する箇所ができているはずです。

そこにさっき作ったマテリアルを入れましょう。

画像15

SceneビューとGameビューが灰色一色になったら成功です。


ShaderGraph設定

いよいよ本題であるShaderGraphの中身を作っていきます。

作ったShaderGraphをダブルクリックして編集画面を開きます。

①左上の+ボタンを押して変数を追加します。

まずTexture 2Dを追加しましょう。

画像16


作成したTexture 2Dをクリックして、編集します。

右上のGraph Inspector>Node Setting>Referenceを「_CameraColorTexture」とします。スペルミスに注意してください。これはカメラの画を取得するものです。

ついでにExposedのチェックを外しておきましょう。チェックがついていると外部からの編集が可能になります。

画像17


②何もないところを右クリックして、Createから、Sample Texture 2Dをダブルクリックでノードを作成します。検索欄でTextureと入れるとすぐ出てきます。

画像18

出てきたSample Texture 2Dノードの左のTextureをさっきのTexture2Dとつなぎ、RGBAをFragmentにつなぎます。

画像19

左上のSave Assetを押してGameビューがカメラ画像に変化したことを確認してください。

画像20


③次はその画像を少し拡大する処理を作ります。

同じようにSample Texture 2Dノードを作成し、先ほどのTexture2Dとつなぎます。

次に、Tiling And Offsetノードを作成します。

画像21

その後Float変数を作ります。

画像22

Graph InspectorでModeをSliderに、Minを0.99にMaxを1.01にします。

画像29


次にOne MinusノードとMultiplyノードを作ります。

MultiplyノードのBの値に0.5を入れます。

One Minusノードは「1-x」をする処理のノードで、Multiplyはその名の通り掛け算処理のノードです。

以下の画像のようにノードを繋げます。

画像24


現在の全体像はこんな感じです。

画像24


今作成したSample Texture 2DノードのRGBAをFragmentにつないでみて動作を確認してみましょう。

まずSaveAssetをしましょう。しないと反映されません。以降も忘れずに。

マテリアルのインスペクタにFloatを入力できる箇所があると思います。

画像25

数値をいじってGameビューが拡大縮小してたら成功です。


④次にSubtractノードを作り、A、BにそれぞれSample Texture 2Dをつなぎます。

Subtractは引き算の処理です。

画像26


OutをFragmentにつないでみて、こんな感じの絵になっていたら成功です。

Save Assetを忘れずに。

画像27


⑤次にLengthノードを作り、InにSubstractのOutをつなぎます。

Lengthはベクトルの長さを取得するノードです。

Fragmentにつないで確認して、白黒画像になっていたら成功です。


⑥これで最後です。

ComparisonノードとBranchノードを作ります。

Comparisonノードは値を比較しbool値を出力するノードです。

Branchのノードはbool値をもとにif-else分岐をするノードです。


さっきのLengthのOutをComparisonのAにつなぎます。

Bは0.01を入力します。

画像28


BranchのPredicateにComparisonのOutをつなぎます。

BranchのTrueに、最初に作ったSample Texture 2DのRGBAをつなぎます。

Falseは(0,0,0,1)と入力します。

OutをFragmentにつないで完成です。

画像30


最終的なノード構成がこんな感じ。

画像29


BranchのTrue値がアウトラインになるので、そこをいじるとアウトラインの色を変えることもできて面白いですね。

この記事が気に入ったらサポートをしてみませんか?