LoginSignup
32
33

More than 5 years have passed since last update.

【Unity】マルチパスシェーダーのやり方(フラグメントシェーダーの場合)

Posted at

マルチパスシェーダーは、複数の描画結果を使って、最終的に作りたい出力結果を導き出すのに便利です。やろうと思えば、1パスでも行けるのですが。。。
例えば、1パス目で、キーボードの入力情報を持つテクスチャを生成し、2パス目で、1パス目の描画結果を元に、何かの最終出力を出すなどです。
以下は、フラグメントシェーダーを使ったやり方になります。

Shader "Custom/TestMultiShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        // 1パス目
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                col.r = 0.5;
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }

        // 1パス目の描画結果をテクスチャとして渡す
        GrabPass{}

        // 2パス目の最終出力
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _GrabTexture;
            float4 _GrabTexture_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _GrabTexture);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                i.uv.x += sin(i.uv.y*_Time.w)*0.1;
                fixed4 col = tex2D(_GrabTexture, i.uv);
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

1パス目で、テクスチャの色味を変えて、2パス目で、1パス目の描画結果に対して、sin関数で、uv座標を、y軸に向かって、揺らしています。
「GrabPass{}」というのを使うと、1パス目の結果を2パス目に、渡すことができます。2パス目の描画結果は、_GrabTextureに格納され、このテクスチャを使って、最終目的の表示に、調整していくだけです。
※「GrabPass」を記述しなかった場合は、最後に記載されている、2パス目のシェーダーが適用されます。

コード例だと、少しごちゃごちゃしてますが、簡単には、以下のような感じです。

Pass{1パス目のシェーダーの記述} // 1パス目
GrabPass{} // 1パスの結果を渡す
Pass{2パス目のシェーダーの記述} // 2パス目
32
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
33