Unity2017から追加されたCustom Render Textureを簡単に使ってみました。
Custom Render Texture?
Custom Render Textureとは、機能が拡張されたRender Textureで、以下のような特徴があります。
- 描画に使うマテリアルをインスペクタから設定できる
- 簡単で自由度の高い更新処理ができる
- 部分的な更新処理ができる
- 前回更新時のテクスチャを取得できる
うーん・・実際使ってみるのが早そうです。
作成する
Custom Render TextureはProjectビューで右クリック > Create > Custom Render Textureで作れます。
真っ黒なのが出来上がればOK。
更新する
まずこのテクスチャを更新するシェーダを書いてみます。
Shader "CRTUpdate" { SubShader { Cull Off ZWrite Off ZTest Always Pass { // インスペクタに表示したときにわかりやすいように名前を付けておく Name "Update" CGPROGRAM // UnityCustomRenderTexture.cgincをインクルードする #include "UnityCustomRenderTexture.cginc" // 頂点シェーダは決まったものを使う #pragma vertex CustomRenderTextureVertexShader #pragma fragment frag // v2f構造体は決まったものを使う half4 frag(v2f_customrendertexture i) : SV_Target { return half4(_SinTime.z * 0.5 + 0.5, _CosTime.w * 0.5 + 0.5, _SinTime.w * 0.5 + 0.5, 1); } ENDCG } } }
Custom Render Texture用のシェーダは書き方に決まりがあるため、コメントに説明を書いています。
このシェーダを割り当てたマテリアルをCustom Render Textureのマテリアルとしてアサインし、パス名にUPDATEを指定します。
Update ModeをRealtimeにして再生すると1frameごとにテクスチャが先ほどのシェーダによって更新されていくのが確認できます。
また、Update Modeの下のPeriodフィールドに秒数を入れると更新間隔を設定できます(0を入れると毎フレーム更新)。
更新をスクリプトで制御する
Update ModeをOn Demandにしたうえで、下記のようなスクリプトをかけばスクリプトで更新タイミングを制御することもできます。
using UnityEngine; public class CustomRenderTextureSample : MonoBehaviour { [SerializeField] CustomRenderTexture _texture; void Update() { // 1フレームに5回更新 _texture.Update(5); } }
一部分だけ更新する
次にUpdateZoneをこんな感じの設定にすると・・
テクスチャの一部分だけを更新することができます。
前フレームの結果を使う
シェーダ内で前フレームのテクスチャを取るためにはまずDouble Burfferedにチェックを入れます。
そして更新用シェーダでこのように記述します。
Shader "CRTUpdate" { SubShader { Cull Off ZWrite Off ZTest Always Pass { Name "Update" CGPROGRAM #include "UnityCustomRenderTexture.cginc" #pragma vertex CustomRenderTextureVertexShader #pragma fragment frag half4 frag(v2f_customrendertexture i) : SV_Target { float tw = 1 / _CustomRenderTextureWidth; // UVはこのように取得する float2 uv = i.globalTexcoord; // _SelfTexture2Dで前フレームの結果を取得する return tex2D(_SelfTexture2D, uv + half2(tw, 0) * 10); } ENDCG } } }
前フレームの情報を使うということは最初のフレームのために初期化が必要になります。
Initialization ModeをOn Loadに設定することで初期化時の設定ができます。
今回はTextureに適当なテクスチャをアサインしてください。
Wrap ModeをRepeatにして再生すると、
前フレームの結果を使って少しずつずらすことができました。
ただしDoubleBufferedは今のところまだパフォーマンスがよくないようです(マニュアル参照)。
初期化用シェーダを書く
初期化には独自のマテリアルを使うこともできます。
この場合のシェーダも更新時と同じようにCustom Render Textureならではの書き方があるので注意してください。
Shader "CRTInitialization" { SubShader { Cull Off ZWrite Off ZTest Always Pass { Name "Initialize" CGPROGRAM // UnityCustomRenderTexture.cgincをインクルードする #include "UnityCustomRenderTexture.cginc" // 頂点シェーダは決まったものを使う #pragma vertex InitCustomRenderTextureVertexShader #pragma fragment frag // v2f構造体は決まったものを使う half4 frag(v2f_init_customrendertexture i) : SV_Target { return 1.0 - step(0.1, distance(0.5, i.texcoord)); } ENDCG } } }
注意点はコメントの通りです。
処理はただ白い丸を書いているだけです。
再生すると次のような結果が得られます。