Unity Shader:重叠两个具有相同模板值的图层

时间:2016-11-17 12:47:02

标签: user-interface shader unity5 shaderlab

我试图为团结编写一个着色器,它将删除底层对象的所有重叠片段。我找到了解决这个问题的不同解决方案,这非常有用。

对我来说,这个链接(Unity shader highlighting overlaps)是最有用的链接。

但现在我有另一个问题。在图片中,您可以看到6个按钮,这些按钮通常具有相同的尺寸和透明背景。如果其中一个按钮被选中,它会与其邻居重叠。

下图显示了自定义着色器的外观。我通过在背景上切出一个洞以显示图像来解决问题,但现在我想在这些按钮上添加文字;如果我再做同样的事情,文字看起来会很粗糙。

Menubutton correct

以下代码向您展示了如何通过在透明框中切出一个洞来解决我的问题:

    Shader "Custom/GUI/Mask" {
    Properties
    {
        _Color("Color (white = none)", COLOR) = (1,1,1,1)
        _MainTex("Texture", 2D) = "white" {}
        _CutOff("Cut off", Range(-0.001,1)) = 0.1
    }
    SubShader
    {
        Tags{ "RenderType" = "Transparent" "Queue" = "Geometry" }
        LOD 100

        Blend SrcAlpha OneMinusSrcAlpha
        ZWrite off

        Pass
        {
            Stencil
            {
                Ref 0
                Comp Equal
                Pass IncrSat
                Fail IncrSat
            }

            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

                #include "UnityCG.cginc"

                uniform sampler2D _MainTex;
                uniform float4 _MainTex_ST;
                float4 _Color;
                float _CutOff;

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

                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float2 uv : TEXCOORD0;
                };

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

                fixed4 frag(v2f i) : SV_Target
                {
                    float4 color = tex2D(_MainTex, i.uv);

                    color.rgb *= _Color.rgb;
                    color.a *= _Color.a;

                    if (color.a <= _CutOff)
                    {
                        discard;
                    }
                    return color;
                }
            ENDCG
        }

        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite off

            Stencil
            {
                Ref 1
                Comp Less
            }

            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

                #include "UnityCG.cginc"

                float4 _Color;
                uniform sampler2D _MainTex;

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

                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float uv : TEXCOORD0;
                };

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

                fixed4 frag(v2f i) : SV_Target
                {
                    fixed4 color = tex2D(_MainTex, i.uv);
                    color.a = 0;
                    return color;
                }
            ENDCG
        }

        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha

            Stencil
            {
                Ref 2
                Comp Less
            }

            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

                #include "UnityCG.cginc"

                uniform sampler2D _MainTex;
                float4 _Color;

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

                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float uv : TEXCOORD0;
                };

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

                fixed4 frag(v2f i) : SV_Target
                {
                    fixed4 color = tex2D(_MainTex, i.uv);
                    color.a = 0;
                    return color;
                }

            ENDCG
        }
    }
}

此图片显示,如果没有自定义着色器可以移除重叠部分,它会是什么样子。在这张图片中你还可以看到,透明背景的模板值通常为0,当它重叠时,值会变为1.问题是背景上的图像的模板值也是1.所以如果我将删除模板值为1的所有对象,我将删除透明背景上的所有图像。顺便说一下,图像和背景包含相同的着色器。

Current view

请不要在没有在透明盒子上钻孔的情况下帮助我解决问题?切入选项有问题,如果我有圆形图像,有一些透明像素,背景会非常明亮。

非常感谢你的帮助。

1 个答案:

答案 0 :(得分:0)

最后我自己解决了这个问题。对于那些有同样问题的人,这是解决方案。 我创建了两个不同的着色器。我为背景创建了一个,为背景前面创建了一个。

以下代码用于后台:

    Shader "Custom/GUI/Background" {
    Properties
    {
        _Color("Color (white = none)", COLOR) = (1,1,1,1)
        _MainTex("Texture", 2D) = "white" {}
        _CutOff("Cut off", Range(-0.001,1)) = 0.1
    }
    SubShader
    {
        Tags{ "RenderType" = "Transparent" "Queue" = "Geometry-100" "LightMode" = "ForwardBase" }
        LOD 100

        Blend SrcAlpha OneMinusSrcAlpha
        ZWrite off

        Pass
        {
            Stencil
            {
                Ref 0
                Comp Equal
                Pass IncrSat
                Fail IncrSat
            }

            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

                #include "UnityCG.cginc"

                uniform sampler2D _MainTex;
                uniform float4 _MainTex_ST;
                float4 _Color;
                float _CutOff;

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

                struct v2f
                {
                    float4 vertex : SV_POSITION;
                    float2 uv : TEXCOORD0;
                };

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

                fixed4 frag(v2f i) : SV_Target
                {
                    float4 color = tex2D(_MainTex, i.uv);

                    color.rgb *= _Color.rgb;
                    color.a *= _Color.a;

                    return color;
                }
            ENDCG
        }
    }
}

这是一张图片:

    Shader "Custom/GUI/ImageShader"
    {
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
        _Color("Color (white = none)", COLOR) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType" = "Transparent" }
        LOD 100

            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite off

        Pass
        {
            Stencil
            {
                Ref 0
                Comp Equal
                Pass IncrSat
                Fail IncrSat
            }

        }

        // picture layer
        Pass
        {
            Stencil
            {
                Ref 2
                Comp Equal
            }

            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                // make fog work
                #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;
                float4 _Color;

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

                fixed4 frag(v2f i) : SV_Target
                {
                    // sample the texture
                    fixed4 col = tex2D(_MainTex, i.uv);
                    col.rgb *= _Color.rgb;
                    col.a *= _Color.a;
                    // apply fog
                    UNITY_APPLY_FOG(i.fogCoord, col);
                    return col;
                }
            ENDCG
        }
    }
}

现在是层次结构:背景位于底部,然后是文本,位于图像上方。

说实话,我不确定它为什么会起作用,我知道这不是最好的答案,但我希望我可以帮助所有有相同或几乎相同问题的人。