2016-11-17 2 views
0

Я пытаюсь написать шейдер для единства, который удалит все перекрывающиеся фрагменты базовых объектов. Я нашел различные решения для этой проблемы, которые были действительно полезны.Unity Shader: перекрытие двух слоев с одинаковым значением трафарета

Для меня эта ссылка (Unity shader highlighting overlaps) была самой полезной.

Но теперь у меня есть еще одна проблема. На снимках вы можете увидеть 6 кнопок, которые обычно имеют одинаковый размер и прозрачный фон. Если выбрана одна из этих кнопок, она перекрывает своих соседей.

На следующем рисунке показано, как это должно выглядеть с помощью пользовательского шейдера. Я решил проблему, разрезав отверстие через фон, чтобы показать изображение, но теперь я хочу добавить текст к этим кнопкам; если бы я сделал то же самое снова, текст выглядел бы scraggy.

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. Так что если i удалит весь объект со значением трафарета 1, я удалю все изображения на прозрачном фоне. Кстати, изображение и фон содержат один и тот же шейдер.

Current view

Можете ли вы помочь мне решить эту проблему без проделывания отверстий в прозрачной коробке? У опции разреза есть проблема, если у меня есть круглые изображения, которые имеют несколько прозрачных пикселей, фон светит очень ярким.

Большое спасибо за помощь.

ответ

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

Иерархия сейчас: фон находится на дне, то текст и выше образ.

Если честно, я не уверен, почему он работает, и я знаю, что это не лучший ответ, но я надеюсь, что смогу помочь всем людям, которые имеют одну и ту же или почти такую ​​же проблему.