Trying to create stencil mask on a specific uv area

Hi There!

following the headline, my goal is to create in a specific area of my UV, stencil mask that will be applied.
but, to the rest of my uv I wish to display the MainTexture as is.

I tried to accomplish it with 2 Passes, the first with a texture mask to specify the area for the stencil to rendered, this seem to work properly, I can see through the area the objects that applied to this stencil ref.

the second pass, I tried to render the main texture to the object. but nothing is being rendered, that object seems transparent (except any objects the camera detect through the stencil mask).

what am I doing wrong? is this even possible to achieve? would appreciate any support.

added an image to show the result as for now, and the script passed I wrote.
first pass:

Pass
        {
            Name "StencilCircle"
            Tags { "RenderType"="Opaque"}
            Cull Back
            ColorMask 0     // Only write to stencil, not color
            ZWrite Off
            ZTest Always

            Stencil
            {
                Ref 1
                Comp Always
                Pass Replace
            }

            CGPROGRAM
            #pragma vertex vertMask
            #pragma fragment fragMask
            #include "UnityCG.cginc"

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

            sampler2D _CircleMask;
            float4    _CircleMask_ST;

            v2f vertMask(appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv  = TRANSFORM_TEX(v.uv, _CircleMask);
                return o;
            }

            fixed4 fragMask(v2f i) : SV_Target
            {
                fixed4 maskColor = tex2D(_CircleMask, i.uv);
                // White circle => maskColor.r ~1, black outside => ~0
                // We keep the white circle to set stencil=1, discard black region
                if (maskColor.r < 0.5)
                    discard;

                // That circle region => stencil=1
                return fixed4(1,1,1,1);
            }
            ENDCG
        }

second pass:

Pass
        {
            Name "RenderOutside"
            Tags { "RenderType"="Opaque"}
            Cull Back
            ZWrite On
            ZTest LEqual

            Stencil
            {
                Ref 1
                Comp NotEqual  // Draw outside circle (stencil != 1)
                Pass Keep
            }

            CGPROGRAM
            #pragma vertex vertMain
            #pragma fragment fragMain
            #include "UnityCG.cginc"

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

            sampler2D _MainTex;
            float4    _MainTex_ST;

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

            fixed4 fragMain(v2f i) : SV_Target
            {
                // Force alpha = 1 for fully opaque outside
                fixed4 col = tex2D(_MainTex, i.uv);
                return float4(col.rgb, 1.0);
            }
            ENDCG
        }

Is it URP? Not sure about Unity 6, but earlier versions don’t support multipass shaders in URP and draw only first pass, which would explain why you see transparent image. You’d need to either attach 2 materials to the mesh with separate “shader-per-pass” or write custom renderer feature that would call each pass manually.

1 Like

Thank you, didnt know that URP dont support multipass shaders.
i’ve attached 2 materials to the mesh as you suggested, that’s solved it :slight_smile: