0
\$\begingroup\$

I've a very sipmle Unity scene.

It has two objects in it, which is Sprites, and they both use sipmle black boxes as a textures.

Here's two shaders, one should act as a mask, and second as a object, that should be rendered only in pixels, specified by that mask.

Mask shader:

Shader "Unlit/StencilUnlitShader"
{
Properties
{
    _MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
    Tags { "RenderType"="Opaque"
    "Queue" = "Geometry" }

    Pass
    {
        //AlphaTest Greater 0.5 //Only render pixels whose alpha is greater than AlphaValue.
        Stencil{
        Ref 2
        Comp Never//Never - never pass the stencil test, Always - always pass the stencil test
        Pass Replace //write Ref value into the stencil buufer
        }

        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc"

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

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

        sampler2D _MainTex;
        float4 _MainTex_ST;

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

        fixed4 frag (v2f i) : SV_Target
        {
            // sample the texture
            fixed4 col = tex2D(_MainTex, i.uv);
            //if (col.a < 0.9) discard; //discard a pixel if it's transparent and don't draw it into a buffer
            return col;
        }
        ENDCG
    }
}
}

Object shader:

Shader "Unlit/GreenUnlitShader"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
    }
        SubShader
    {
        Tags{ "RenderType" = "Opaque"
              "Queue" = "Geometry+5" //to draw after stencil object
    }

        Pass
        {
        //AlphaTest Less 0.5
        Stencil{
        Ref 1
        Comp Less //Always, Less - if ref value is greater then current value in the stencil buffer
        Pass Keep
        }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"

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

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

    sampler2D _MainTex;
    float4 _MainTex_ST;

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

    fixed4 frag(v2f i) : SV_Target
    {
        fixed4 col = tex2D(_MainTex, i.uv);//fixed4(0,1,0.5,0.6);
        //if (col.a < 0.9) discard;
        return col;
    }
ENDCG
    }
    }
}

The problem is, this doesn't seem to work, and object doesn't seems to be rendered at all (why it should in the places where mask have it's pixels)

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

In your mask shader, change comp never to comp always.

You never write to the stencil because the comp fails.

\$\endgroup\$
2
  • \$\begingroup\$ Shouldn't parameter "Pass" specify if I write or ignore writing to stencil buffer? \$\endgroup\$
    – PaulD
    Commented May 17, 2017 at 13:21
  • 1
    \$\begingroup\$ Pass only applies when the previous tests succeed. From unity's documentation: "(Pass) What to do with the contents of the buffer if the stencil test (and the depth test) passes. Default: keep." \$\endgroup\$
    – Zebraman
    Commented May 17, 2017 at 13:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .