Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Silhouette using stencil and vertex shader

Discussion in 'Shaders' started by adamwilks, Apr 15, 2021.

  1. adamwilks

    adamwilks

    Joined:
    Apr 3, 2017
    Posts:
    27
    I am creating a simple RPG with an isometric camera view and have been looking into ways of dealing with the player character becoming obscured by the environment. Most games seem to use shaders to draw a silhouette or outline around the geometry, or make the environment turn transparent, sometimes both.

    A few details on the project setup:

    1. Unity version 2019.4.14f1
    2. Targetting PC / Mac (considering Nintendo Switch)
    3. Standard render pipeline
    4. Deferred rendering and realtime lighting
    5. GPU instancing to render modular environment assets

    Ideally I would like to upgrade to URP and Shader Graph and use a custom renderer as seen in a 2019 Brackeys tutorial which seems like a really nice solution, however with no deferred rendering support in URP yet I will have to wait for this.

    My ShaderLab / HLSL knowledge is poor but improving, and having looked at a number of examples I have come up with a solution which seems to work well but I am hoping that someone with more experience could highlight any drawbacks or potential improvements.

    The implementation works like this:

    1. Use a custom surface shader on objects requiring a silhouette (characters, items etc).
    2. Have the shader do a pass which writes into the stencil buffer disregarding depth, but also draws the object geometry normally with surface shading.
    3. Draw a plane in front of the camera with a custom vertex shader to color pixels where the stencil buffer permits it using alpha blend so that some geometry shows through (if not obscured).
    4. Enable or disable the plane to show or hide the silhouette "layer" as needed.
    5. Additional planes can be added to draw silhouettes with different stencil refs using different colors e.g. one for characters, another for items.

    Showing the silhouettes can then be done using player input or a raycast to detect camera obscurity. Alternatively the stencil writer can do "ZTest Greater" to avoid the raycast.

    Shader code attached, write for the object and read for the plane. Everything else in the scene is rendered by the standard shader and a single texture atlas.

    Would really appreciate any feedback on the approach or suggestions for a better method which will work with deferred / instancing / standard pipeline and be achievable for someone with my level of knowledge.
     

    Attached Files:

    Last edited: Apr 15, 2021