Search Unity

Question Stencil mask issues

Discussion in 'High Definition Render Pipeline' started by Armageddon104, Nov 2, 2020.

  1. Armageddon104

    Armageddon104

    Joined:
    Sep 14, 2014
    Posts:
    23
    Hello, I'm making a 2.5D game and I'm trying to make a system where rooms will individually become visible when you enter them while the rest of the world is faded out/black.

    My first idea was to give each room a simple mesh overlapping the entire room, and then dither fade-in their materials when the player enters the room and render the mesh in a Custom Pass to replace the depth buffer, so only objects within the stencil of the mesh and with a further away Z-value would be drawn. I was trying to use HDRP's Custom Passes for this so I wouldn't have to markup or replace any materials in my scene; just put a simple mesh in a WorldMask layer and a trigger to fade in its material.
    This didn't work though because the color buffer obviously doesn't have the color behind a wall once you do replace the depth mask. I also couldn't figure how to write the depth back to the scene anyways. I tried to do a DrawRenderers replacement shader too that would only affect depth, it would take a sample from my custom depth pass and a sample from the regular default depth and lerp the color as visible or not based on which was closer, this didn't seem to do anything though.

    So now I'm going with good ol' stencil masks. I followed this solution: https://stackoverflow.com/a/64352913 But the issue is that the mask has to be in-front of whatever it's clipping to work, and I want it so that whatever is above the mask is clipped, and whatever is behind is visible.

    Then I tried this which looks like exactly what I need:



    I made a shader for the mask and a shader for the world as shown and put them in a Custom Pass like so:

    Screenshot (8114).png

    Here are the shaders:

    Code (CSharp):
    1. Shader "Stencil Mask"
    2. {
    3.     SubShader {
    4.         ColorMask 0
    5.         ZWrite On
    6.  
    7.         Stencil {
    8.             Ref 1
    9.             Comp Always
    10.             Pass Replace
    11.         }
    12.  
    13.         Pass {}
    14.     }
    15. }
    16.  
    17. Shader "Stencil World"
    18. {
    19.     SubShader {
    20.         ColorMask 0
    21.         ZWrite On
    22.  
    23.         Stencil {
    24.             Ref 1
    25.             Comp LEqual
    26.         }
    27.  
    28.         Pass {}
    29.     }
    30. }
    I changed the world shader from NotEqual to LEqual, it was flipped otherwise. But as you can see in the picture there's a lot of flickering happening and sorting issues. My guess is it's because the color buffer gets written to twice and it's conflicting? The wall and the mask both have HDRP/Lit materials set to Transparent (setup like the stack overflow answer), and it seems like making all my world materials render in the Transparent pass so that this Custom Pass works doesn't seem like the best course of action?

    Custom Passes seems extremely powerful I'm just not experienced enough in HDRP's pipeline or shaders to know what's wrong. I've spent the past week combing the Custom Pass examples on GitHub, but haven't found much to do with something like this. Since surf is no longer supported it'd be nice if there was a way to make custom shaders with HDRP/Lit without Shader Graph, or if ShaderGraph supported depth/stencil stuff like this.

    I'm using HDRP 8.2.0 by the way. The new Compositor looks good but I'm not sure if that can solve this issue.

    I figure once I get this working I can make a FullScreen pass that'll black out anything not in the WorldMask layer's stencil.


    Thanks!
     
    octav88 and Crucifer-UA like this.