UnityのPostProcessingでこの自作のポストエフェクトを作るとき、RenderTextureを使いたかったので
今はURPの自作PostProcessingは公式の方法がないらしいのでビルトイン版でのやり方を書いていきます(URPでも同じような感じでできましたが)
とりあえずこんな感じのを作ります
シェーダーを作成する
ポストエフェクトに使うためのシェーダーを作成します。
今回は適当にこんな感じにします。ここはカメラに写ってるものを表示する用(_MainTex)と、RenderTextureのものを表示する用の2つのTextureを用意しておけばなんでもいいです。
Shader "Hidden/RenderTexTestShader"
{
Properties
{
_Slice("slice",Range(-1, 1))=0
_MainTex ("Texture", 2D) = "white" {}
_RenderTex ("Texture",2D) = "black" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
sampler2D _MainTex;
//float4 _MainTex_ST;
sampler2D _RenderTex;
float _Slice;
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
if(i.uv.x-i.uv.y>_Slice){
col = tex2D(_RenderTex, i.uv);
}
return col;
}
ENDCG
}
}
}
PostProcessEffectSettingsを書く
PostProcessingにエフェクトを追加するためのクラスを書きます。
ここでインスペクターから値を編集できるようにするのですが、〇〇Parameterというものでインスペクターから変更できる数値などの変数を作ってあげる必要があります。
が、用意されている〇〇ParameterはFloatやVector2などの基本的なものしかなく、RenderTextureはどうやって受け付ければ良いんだ…で少し悩んでました
ParameterOverrideを継承すれば用意されてないものもできるよ!とのことでしたがアセットを指定するだけならParameterOverride<T>を使えばいけました。値によって処理を分けをする場合は継承する必要があるようですが
using System;
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
[Serializable]
[PostProcess(typeof(RenderTexSampleRenderer), PostProcessEvent.AfterStack, "Custom/RenderSample", false)]
public class RenderTexSample : PostProcessEffectSettings
{
[Range(-1, 1)] public FloatParameter slice = new FloatParameter() { value = 0.0f };
public ParameterOverride<RenderTexture> renderTexture = new ParameterOverride<RenderTexture>();
}
PostProcessEffectRendererを書く
先程作ったPostProcessEffectSettingsから設定した値をシェーダーに渡してレンダリングするためのクラスを書きます。
RenderTextureはTexture2Dに変換しなくてもSetTextureで直接指定できるようです。
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
public class RenderTexSampleRenderer : PostProcessEffectRenderer<RenderTexSample>
{
public override void Render(PostProcessRenderContext context)
{
//マテリアルの作成
var material = new Material(Shader.Find("Hidden/RenderTexTestShader"));
material.SetFloat("_Slice", settings.slice.value);
//シェーダーの_RenderTexにRenderTextureを設定
//_MainTexは何もしなくてもカメラに写っているものが設定される
material.SetTexture("_RenderTex", settings.renderTexture.value);
//作ったマテリアルでレンダリング
context.command.Blit(context.source, context.destination, material);
}
}
PostProcessingで使う
あとは使うだけです。なのですがRenderTextureを設定したカメラが作成した先程作成したポストエフェクトの影響を受けてしまうと上手くレンダリングされない場合があるのでPostProcessはIsGrobalのチェックを外してLocalで使用する必要があります(Localにするとそれぞれのカメラで別のポストエフェクトをかけるなどもできますし)
あとは普通にPostProcessのエフェクトとして使えます
ページめくりシェーダーはゲームで使いやすいようにもう少し整えてから配布したい
参考