2

我有一个里面有多个通道的着色器,其中两个是轮廓通道和模糊通道。我正在尝试创建一个轮廓,然后将其模糊。如何使模糊通道接受轮廓通道的输出以进行模糊?

大纲通行证:

Pass{
        Name "OUTLINE"
        Cull Off
        ZWrite Off
        ZTest Always
        Blend SrcAlpha OneMinusSrcAlpha
    CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile_fog

    fixed4 frag(v2f IN) : SV_Target
    {
        fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;

        if (c.a > _Cutoff) {
            float totalAlpha = 1.0;

            [unroll(16)]
            for (int i = 1; i < _OutlineSize + 1; i++) {
                fixed4 pixelUp = tex2D(_MainTex, IN.texcoord + fixed2(0, i * _MainTex_TexelSize.y));
                fixed4 pixelDown = tex2D(_MainTex, IN.texcoord - fixed2(0, i *  _MainTex_TexelSize.y));
                fixed4 pixelRight = tex2D(_MainTex, IN.texcoord + fixed2(i * _MainTex_TexelSize.x, 0));
                fixed4 pixelLeft = tex2D(_MainTex, IN.texcoord - fixed2(i * _MainTex_TexelSize.x, 0));

                totalAlpha = totalAlpha * pixelUp.a * pixelDown.a * pixelRight.a * pixelLeft.a;
            }

            if (totalAlpha == 0) {
                c.rgba = fixed4(0.4, 1, 1, 1);
            }
            else
                c.rgba = fixed4(0.5, 0.5, 0.5, .5);
        }

        c.rgb *= c.a;
        return c;
    }

    ENDCG
    }

模糊通行证:

Pass{
        Name "BLUR"
        Cull Off
        ZWrite Off
        ZTest Always
        Blend SrcAlpha OneMinusSrcAlpha
        CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile_fog

        fixed4 frag(v2f IN) : SV_Target
    {
        fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;

        if (c.a > _Cutoff) {
            fixed4 pixelUp = tex2D(_MainTex, IN.texcoord + fixed2(0, _MainTex_TexelSize.y));
            fixed4 pixelDown = tex2D(_MainTex, IN.texcoord - fixed2(0,  _MainTex_TexelSize.y));
            fixed4 pixelRight = tex2D(_MainTex, IN.texcoord + fixed2(_MainTex_TexelSize.x, 0));
            fixed4 pixelLeft = tex2D(_MainTex, IN.texcoord - fixed2(_MainTex_TexelSize.x, 0));
            fixed4 pixelUp2 = tex2D(_MainTex, IN.texcoord + fixed2(0, 2 * _MainTex_TexelSize.y));
            fixed4 pixelDown2 = tex2D(_MainTex, IN.texcoord - fixed2(0, 2 * _MainTex_TexelSize.y));
            fixed4 pixelRight2 = tex2D(_MainTex, IN.texcoord + fixed2(2 * _MainTex_TexelSize.x, 0));
            fixed4 pixelLeft2 = tex2D(_MainTex, IN.texcoord - fixed2(2 * _MainTex_TexelSize.x, 0));
            fixed4 pixelUp3 = tex2D(_MainTex, IN.texcoord + fixed2(0, 3 * _MainTex_TexelSize.y));
            fixed4 pixelDown3 = tex2D(_MainTex, IN.texcoord - fixed2(0, 3 * _MainTex_TexelSize.y));
            fixed4 pixelRight3 = tex2D(_MainTex, IN.texcoord + fixed2(3 * _MainTex_TexelSize.x, 0));
            fixed4 pixelLeft3 = tex2D(_MainTex, IN.texcoord - fixed2(3 * _MainTex_TexelSize.x, 0));

            c = c * 0.18
                + 0.15 * (pixelUp + pixelDown + pixelRight + pixelLeft)
                + 0.12 * (pixelUp2 + pixelDown2 + pixelRight2 + pixelLeft2);
                + 0.09 * (pixelUp3 + pixelDown3 + pixelRight3 + pixelLeft3);
        }

        c.rgb *= c.a;
        return c;
    }

        ENDCG
    }

我是着色器的新手,所以如果有任何建议将不胜感激。

4

1 回答 1

4

使用Grab pass,您可以获取到目前为止生成的屏幕并在另一个 pass 中从中采样。

在您的情况下,将其放在轮廓通道之后,并从模糊通道中的结果纹理而不是原始纹理中采样。

Pass{
    // ...
    // no change
    // ...
}

GrabPass { "_GrabTexture" }        

Pass{ 
    // Note the changes from calling tex2D with _MainTex to _GrabTexture, 
    // matching the string in the GrabPass directive above 

    // ...
    // use a vertex shader to get the uvs of the screen grab

    struct v2f {
        float4 grabPos : TEXCOORD0;
        float4 pos : SV_POSITION;
    };

    v2f vert(appdata_base v) {
        v2f o;
        // use UnityObjectToClipPos from UnityCG.cginc to calculate 
        // the clip-space of the vertex
        o.pos = UnityObjectToClipPos(v.vertex);
        // use ComputeGrabScreenPos function from UnityCG.cginc
        // to get the correct texture coordinate
        o.grabPos = ComputeGrabScreenPos(o.pos);
        return o;
    }

    // Note the changes from calling tex2D with _MainTex to _GrabTexture, 
    // matching the string in the GrabPass directive above 
    // as well as IN.grabPos instead of IN.texcoord
    // and tex2Dproj instead of tex2D

    fixed4 frag(v2f IN) : SV_Target {
        fixed4 c = tex2Dproj(_GrabTexture, IN.grabPos) * IN.color; 

        if (c.a > _Cutoff) {
            fixed4 pixelUp = tex2Dproj(_GrabTexture, IN.grabPos+ fixed2(0, _MainTex_TexelSize.y));
            fixed4 pixelDown = tex2Dproj(_GrabTexture, IN.grabPos - fixed2(0,  _MainTex_TexelSize.y));
            fixed4 pixelRight = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(_MainTex_TexelSize.x, 0));
            fixed4 pixelLeft = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(_MainTex_TexelSize.x, 0));
            fixed4 pixelUp2 = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(0, 2 * _MainTex_TexelSize.y));
            fixed4 pixelDown2 = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(0, 2 * _MainTex_TexelSize.y));
            fixed4 pixelRight2 = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(2 * _MainTex_TexelSize.x, 0));
            fixed4 pixelLeft2 = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(2 * _MainTex_TexelSize.x, 0));
            fixed4 pixelUp3 = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(0, 3 * _MainTex_TexelSize.y));
            fixed4 pixelDown3 = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(0, 3 * _MainTex_TexelSize.y));
            fixed4 pixelRight3 = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(3 * _MainTex_TexelSize.x, 0));
            fixed4 pixelLeft3 = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(3 * _MainTex_TexelSize.x, 0));

            c = c * 0.18
                + 0.15 * (pixelUp + pixelDown + pixelRight + pixelLeft)
                + 0.12 * (pixelUp2 + pixelDown2 + pixelRight2 + pixelLeft2);
                + 0.09 * (pixelUp3 + pixelDown3 + pixelRight3 + pixelLeft3);
        }

        c.rgb *= c.a;
        return c;
    }

        ENDCG
    }
于 2018-10-05T04:24:56.050 回答