3
votes

Does anybody know of a free Unity/ShaderLAB that is just the default sprite shader but when you walk behind something and can no longer see the player, or just a part of it, it displays a completely opaque, one color silhouette that draws over everything.

It should look something like this: http://i.stack.imgur.com/iByV7.png (From Titan Souls)

1
Does your game 1) have transparency and 2) use the Sprite's "Order in Layer" feature? The default Sprite shader has transparency, so you can't just change the shader and make everything work (at least not at my skill level)user3814958
Seem to be like the objects that are "in front" of the player act as a mask. With that mask you render a transparent; black tinted sprite on top of everything. When the player moves around and is not having a sprite on top; the mask would be empty as there are no object for masking. And in turn, no overlayed sprite would be rendered. I will give it some thought and see if I can come back with an answer :-)Zerratar
Darnit! I can't think of a graceful way of doing it; In my head you would need a overlay sprite that is always on top of your player sprite. This overlay should also have as high z-index / sprite layer order as possible to ensure it being on top of all other images. Then check everytime the player moves if there are objects (other sprites) inside the bounds of the player sprite. And then apply a mask on each individual object together with your player sprite and have that shown as the overlay with a color of choice. There must be a better way using shaders.Zerratar

1 Answers

1
votes

You can apply this shader to your player object. It will mark the stencil flag with a 1, for each pixel it draws.

Shader "Custom/StencilHole" { //also used for silhouetted objects
Properties {}
SubShader {
    // Write the value 1 to the stencil buffer
    Stencil
    {
        Ref 1
        Comp Always
        Pass Replace
    }
    Tags { "Queue" = "Geometry-1" }  // Write to the stencil buffer before drawing any geometry to the screen
    ColorMask 0 // Don't write to any colour channels
    ZWrite Off // Don't write to the Depth buffer
    Pass {}
} 
FallBack "Diffuse"
}

Then you can use the below shader on the "tinted glass". It checks the stencil value for each pixel: if equal to 1 is uses the silhouette color(black in your sample), otherwise a combination of the main color(grey in your sample) and a texture (none in your sample). Note: only objects that have the ABOVE shader applied to them will be silhouetted - so you could choose to make the glass color transparent and allow, say.. the ground flowers, to show through.

Shader "GUI/silhouetteStencil" 
{

    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Color", Color) = (1,1,1,1)
        _silhouetteColor ("silhouette Color", Color) = (0,1,0,1)
    }

    SubShader {
        Tags { "Queue"="Transparent-1" "IgnoreProjector"="True" "RenderType"="Transparent" }
        Lighting On Cull back ZWrite Off Fog { Mode Off }
        Blend SrcAlpha OneMinusSrcAlpha

        Pass 
        {
            // Only render texture & color into pixels when value in the stencil buffer is not equal to 1.
            Stencil 
            {
                Ref 1
                Comp NotEqual
            }
            ColorMaterial AmbientAndDiffuse
            SetTexture [_MainTex] 
            {
                constantColor [_Color]
                combine texture * constant
            }
        }

        Pass
        {
            // pixels whose value in the stencil buffer equals 1 should be drawn as _silhouetteColor
            Stencil {
              Ref 1
              Comp Equal
            }
            SetTexture [_MainTex] 
            {
                constantColor [_silhouetteColor]
                combine constant
            }

        }
    }
}