0

我正在尝试为统一编写一个着色器,它将删除底层对象的所有重叠片段。我为这个问题找到了不同的解决方案,这真的很有帮助。

对我来说,这个链接(Unity 着色器突出显示重叠)是最有用的。

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

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

菜单按钮正确

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

    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 的所有对象,我将删除透明背景上的所有图像。顺便说一下,图像和背景包含相同的着色器。

目前看来

你能帮我解决这个问题,而不是在透明盒子上开一个洞吗?穿透选项有问题,如果我有圆形图像,其中有一些透明像素,背景会非常明亮。

非常感谢您的帮助。

4

1 回答 1

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
        }
    }
}

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

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

于 2016-11-24T15:27:19.160 回答