3d Outline without interior.

Hey. So I know how to do an outline shader but I would then want to remove everything except the outline. (so you can see through it). I guess you could use Clip but how. The way I do outline is that I first render a solid color that is bigger than the object in one pass. And then the object above that in the 2nd pass. Im confused how I would use Clip in this context.

Shader "Unlit/outlineShader"{
    Properties{
        _Color("Main Color", Color) = (0.5,0.5,0.5,0.75)
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _OutlineColor("Outline Color", Color) = (0,0,0,0.75)
        _OutlineWidth("Outline Width", Range(0,5)) = 1
    }

    CGINCLUDE

    #include "UnityCG.cginc"

    struct appdata
    {
        float4 vertex : POSITION;
        float3 normal : NORMAL;
    };

    struct v2f
    {
        float4 pos : POSITION;
        float3 normal : NORMAL;
    };

    float _OutlineWidth;
    float4 _OutlineColor;

    v2f vert(appdata v)
    {
        //v.vertex.xyz *= _OutlineWidth;
        v.vertex.xyz = v.vertex.xyz + v.normal* _OutlineWidth;

        v2f o;
        o.pos = UnityObjectToClipPos(v.vertex);
        return o;
    }
    ENDCG




        Subshader
    {

        Tags{ "Queue" = "Transparent" }
        LOD 200
        Pass //Rendering Outlines
        {
            Cull Off//new
            AlphaToMask On//?
            Zwrite Off
            ZTest Always//new
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            half4 frag(v2f i) : COLOR
            {

                return _OutlineColor;

            }
            ENDCG
        }

        Pass // Normal Render
        {
            ZWrite On
          
            Material
            {
                Diffuse[_Color]
                Ambient[_Color]
            }

            Lighting On

            SetTexture[_MainTex]
            {
                ConstantColor[_Color]
            }

            SetTexture[_MainTex]
            {
                Combine previous * primary DOUBLE
            }
          
        }

    }


}

Honestly I dont understand the 2nd pass. Can I do that in a normal way like suface shader or vertex and frag?
Im bad. Thx in advance.

That last pass is an old fixed function shader. Unity no longer supports fixed function shaders, so they actually treat those as vertex fragment generators, the generated code for which you can see if you select the shader in Unity and click on “Show Generated Code” in the inspector.

However for what you want, that’s not going to be useful. The above shade works by rendering the mesh once slightly expanded on the vertex normals, but with ZWrite Off. This means it doesn’t write to the depth buffer, and means the second pass just renders on top of it.

To do what you want you’d still need a two pass shader, but you’d need to render your mesh with a stencil only pass, then have the expanded outline pass exclude itself wherever the stencil has been written to.

See the depth only pass from this page, but use ZWrite Off and stencils.

2 Likes

Hey Thank you so much! I read some tutorials about stencils and such things you talked about.
But currently my stencils dont seem to do anything no matter how i change them. Should i do stencil 2 times? How can the 2nd stencil use the expanded model and check against the regular model? The code is a mess right now. I have just tried a lot of different things.

Also another questinon. Is it possible to draw pixels end then erase them in the same shader? I know about clip but I mean in a secound pass erase something from the first so you can see through it to the stuff behind the object. Trying to get a grasp on whats possible.

Shader "Unlit/alwaysVisableCone"{
    Properties{
        _Color("Main Color", Color) = (0.5,0.5,0.5,0.75)
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _OutlineColor("Outline Color", Color) = (0,0,0,0.75)
        _OutlineWidth("Outline Width", Range(0,5)) = 1
    }

    CGINCLUDE

    #include "UnityCG.cginc"

    struct appdata
    {
        float4 vertex : POSITION;
        float3 normal : NORMAL;
    };

    struct v2f
    {
        float4 pos : POSITION;
        float3 normal : NORMAL;
        float3 uv0 : TEXCOORD0;//neww
        UNITY_VERTEX_INPUT_INSTANCE_ID//neww
    };

    float _OutlineWidth;
    float4 _OutlineColor;

    ENDCG




    Subshader
    {


        Tags{ "RenderType" = "Opaque" "Queue" = "Geometry-1" /*"IgnoreProjector" = "True" */ }
        Stencil{
            Ref 3
            Comp Always
            Pass Replace
        }
        Lighting Off
        Pass{
           ZWrite On
           ZTest Always
           //ZTest LEqual
           ColorMask 0
           CGPROGRAM
           #pragma vertex vert
           #pragma fragment frag
           v2f vert(appdata v)
           {
        

               v2f o;
               o.pos = UnityObjectToClipPos(v.vertex);
               return o;

           }

           half4 frag(v2f i) : COLOR
           {

               return 0;

           }
           ENDCG
        }



        Tags{ "RenderType" = "Opaque" "Queue" = "Geometry" }
        Stencil{
            Ref 3
            Comp NotEqual

        }
        LOD 200
        Pass //Rendering Outlines
        {
            Cull Off//new
            //AlphaToMask On//?
            Zwrite On//!!!
            //ZTest LEqual
            //ZTest Always//new
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
        
            v2f vert(appdata v)
            {
                v.vertex.xyz = v.vertex.xyz + v.normal* _OutlineWidth;

                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                return o;

            }
        
            half4 frag(v2f i) : COLOR
            {

                return _OutlineColor;

            }
            ENDCG
        }

    }


}

forgot to quote

The stencil blocks should be inside the pass, otherwise they’re whole shader overrides.

Also you can only have one queue and rendertype per shader.

I see. Thx!
I found another thread where you already solved this https://discussions.unity.com/t/720428 and it works well for me.

Now the next step is that i would like it to only have the outline like that when the object is behind the character and when its in front to show itself without outline. So I need one more stencil of the character as well. Hope it will work. (But help is much appreciated as i will most likely fuck up).