Search Unity

Need help with my outline shader's visibility behind walls

Discussion in 'Shaders' started by stefanplc, Jul 29, 2019.

  1. stefanplc

    stefanplc

    Joined:
    Feb 21, 2015
    Posts:
    66
    Hi there,

    I'd like to start off by saying that my shader coding knowledge is pretty limited. I know the basics and I can eventually understand how a shader works, but that's about it. I've made a simpler scene and updated my original question to better explain the problem that I'm having.

    Please take a look at the following image:


    I have 4 objects in the scene above. The ground (beige), one red cube on the left side that's above the ground, one red cube on the right side that's half above and half under the ground and a blue wall in front of the 2 cubes. The red cubes render only if they're behind the wall so if I was to delete the wall they would become invisible.

    What I would like to achieve is to have the red cubes be visible when behind the wall, but not the area that's under ground. So the right cube should only be rendering the top red part and not the bottom beige part as well.

    Here are the 3 shaders that I'm using:
    Cubes: https://pastebin.com/msuyi1zj
    Ground: https://pastebin.com/ttL45Gjm
    Wall: https://pastebin.com/QcL0uY8j

    To gives you a scenario where I would be using something like this, imagine an RTS game where you want units behind walls or other objects to be visible so the cube shader would be like an outline or silhouette shader. Now imagine that you also want these units to hide by going underground. Currently, if they were to go underground but were also behind a wall, they would be visible.

    Thank you very much in advance!
     
    Last edited: Jul 30, 2019
  2. stefanplc

    stefanplc

    Joined:
    Feb 21, 2015
    Posts:
    66
    One idea could be to compare the output color and if it's not red then don't output anything, but I'm not too sure how to write that so it works :(. If you look at http://www.pulciu.com/screenshot.jpg the right cube which is half above the ground and half under, prints the top part as red and that's all that I would like to keep.
     
  3. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    171
    Something like this ?

    upload_2019-7-31_16-47-0.png

    Code (CSharp):
    1. Shader "ZTest Shaders/Cube"
    2. {
    3.     Properties
    4.     {
    5.         ObjectColor("Object Color", Color) = (1, 1, 1, 1)
    6.     }
    7.     SubShader
    8.     {
    9.         Tags {
    10.             "Queue" = "Transparent+10"
    11.         }
    12.  
    13.         Pass
    14.         {
    15.        
    16.             ZWrite On
    17.             ZTest Greater
    18.  
    19.             CGPROGRAM
    20.             #pragma vertex vert
    21.             #pragma fragment frag
    22.            
    23.             #include "UnityCG.cginc"
    24.  
    25.             struct appdata
    26.             {
    27.                 float4 vertex : POSITION;
    28.             };
    29.  
    30.             struct v2f
    31.             {
    32.                 fixed4 color : COLOR;
    33.                 float4 vertex : SV_POSITION;
    34.                 float3 worldPos : TEXCOORD0;
    35.             };
    36.            
    37.             uniform fixed4 ObjectColor;
    38.  
    39.             v2f vert (appdata v)
    40.             {
    41.                 v2f o;
    42.                 o.vertex = UnityObjectToClipPos(v.vertex);
    43.                 o.color = ObjectColor;
    44.                 o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
    45.                 return o;
    46.             }
    47.            
    48.             fixed4 frag (v2f i) : SV_Target
    49.             {
    50.                 if (i.worldPos.y < 0.0) discard;
    51.                 return i.color;
    52.             }
    53.             ENDCG
    54.         }
    55.     }
    56. }
     
    stefanplc likes this.
  4. stefanplc

    stefanplc

    Joined:
    Feb 21, 2015
    Posts:
    66

    Holly... I don't even know what to say, thank you so much man! I've been trying literally all that I could find and think of for the past couple of days but because my shader knowledge isn't that great I just couldn't get it to work. This is perfect, thank you! thank you! thank you!
     
  5. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    171
    My approach is based on testing, if coordinates of cube in world space are located under certain vertical value (in my example: i.worldPos.y < 0.0) , I disable output the result of the current pixel. Of course, you can create various conditions to decide which pixels discards. For example you can use 3D Signed Distance Fields to define "cutoff" shapes.
     
  6. stefanplc

    stefanplc

    Joined:
    Feb 21, 2015
    Posts:
    66
    I think the easiest for me would probably be to just update the y value via a script.
     
  7. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    171
    Yes.

    So, in this example everything with Cube material and located under 0.0 world space position is invisible, so I set ground plane to Y=0.0 to visually compose scene:
    upload_2019-7-31_17-8-42.png

    Now something more advanced:

    Code (CSharp):
    1. float Box (float3 p, float3 c, float3 s)
    2. {
    3.     float x = max(p.x - c.x - float3(s.x / 2., 0, 0), c.x - p.x - float3(s.x / 2., 0, 0));
    4.     float y = max(p.y - c.y - float3(s.y / 2., 0, 0), c.y - p.y - float3(s.y / 2., 0, 0));  
    5.     float z = max(p.z - c.z - float3(s.z / 2., 0, 0), c.z - p.z - float3(s.z / 2., 0, 0));
    6.     float d = x;
    7.     d = max(d,y);
    8.     d = max(d,z);
    9.     return d;
    10. }
    11.  
    12. ...
    13. float d = Box (worldPos, float3(10,5,20), float3(3,2,2));
    14. if (d<0.0) discard;
    It discards pixels located inside cube, where cube center is (10,5,20) and cube size is (3,2,2).
     
  8. stefanplc

    stefanplc

    Joined:
    Feb 21, 2015
    Posts:
    66
    This is really cool! I didn't use anything like this before but now seeing your examples there are definitely many awesome effects that could be achieved with this. Thanks again, really appreciate it!