🎨

CustomRenderTextureで前回パスの結果を取得する

2025/01/16に公開

概要

CustomRenderTexture(以降CRTと呼ぶ)ではDouble Bufferを使用することで前回フレームの結果を_SelfTexture2Dとして取得することができます。これと同じように、1フレームの間で、前回パスの結果を_SelfTexture2Dとして取得する方法を紹介します。

環境

  • Unity 2022.3.22f1

サンプルケース

今回はCRTで

  1. Pass1で赤色のテクスチャを取得
  2. Pass2でPass1の結果に緑色を加算 → 黄色になる
  3. Pass3でPass2の結果に青色を加算 → 白色になる

という3パスに渡った処理を行ってみます。Pass2とPass3で前回パスの結果を_SelfTexture2Dとして利用しています。

CRT用のShader

Shader "CustomRenderTextureTest"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Pass
        {
            Name "Pass1"

            CGPROGRAM       
            #include "UnityCustomRenderTexture.cginc"
            #pragma vertex CustomRenderTextureVertexShader
            #pragma fragment frag

            sampler2D _MainTex;

            float4 frag(v2f_customrendertexture i) : SV_Target
            {
                float2 iuv = i.globalTexcoord;
                float4 col = tex2D(_MainTex, iuv); // 赤色のテクスチャを取得
                return col;
            }
            ENDCG
        }

        Pass
        {
            Name "Pass2"

            CGPROGRAM       
            #include "UnityCustomRenderTexture.cginc"
            #pragma vertex CustomRenderTextureVertexShader
            #pragma fragment frag

            float4 frag(v2f_customrendertexture i) : SV_Target
            {
                float2 iuv = i.globalTexcoord;
                float4 col = tex2D(_SelfTexture2D, iuv); // 前回パスの結果を取得
                return col + float4(0.0, 1.0, 0.0, 0.0); // 前回パスの結果に緑色を加算
            }
            ENDCG
        }

        Pass
        {
            Name "Pass3"

            CGPROGRAM       
            #include "UnityCustomRenderTexture.cginc"
            #pragma vertex CustomRenderTextureVertexShader
            #pragma fragment frag

            float4 frag(v2f_customrendertexture i) : SV_Target
            {
                float2 iuv = i.globalTexcoord;
                float4 col = tex2D(_SelfTexture2D, iuv); // 前回パスの結果を取得
                return col + float4(0.0, 0.0, 1.0, 0.0); // 前回パスの結果に青色を加算
            }
            ENDCG
        }
    }
}

CRTの設定

CRT用のMaterialで1Pass目で使う赤色のテクスチャをアタッチしています。

また、理由はわかりませんがDouble Bufferedの他にWrap Update Zonesのチェックも必要でした。公式ドキュメントを見ると「部分的な更新ゾーンがテクスチャの境界線の周りを包むようにできます。」と書いてありましたが意味がよくわかりませんでした...

Update ZonesにはそれぞれPass1, Pass2, Pass3を追加していき、前回パスの結果を_SelfTexture2Dとして利用したいPass2, Pass3ではSwap(Double Buffer)にチェックを入れます。

描画結果

Pass1で赤色に→Pass2で緑色を加算して黄色に→Pass3で青色を加算して最終的に白色になります。

完成品 (UnityPackage)

CRTは設定がややこしいため完成品を配布します。インポート後PrefabをHierarchyにドラッグ&ドロップすれば、本記事の状態を再現できるはずです。

ライセンスはCC0 (クリエイティブ・コモンズ・ゼロ)とします。いかなる権利も保有しません。
https://drive.google.com/file/d/1BwkwLh_sEWtoRiGnN9VQQqMZbe4yUQQQ/view?usp=sharing

参考

https://docs.unity3d.com/ja/2022.3/Manual/class-CustomRenderTexture.html

Discussion