Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Soft Clip [Free Shader] (Fade out objects when close to camera)

Discussion in 'Shaders' started by hardcorebadger, Sep 2, 2018.

  1. hardcorebadger

    hardcorebadger

    Joined:
    Nov 28, 2016
    Posts:
    31
    Hey Guys,

    Just needed to make a shader to fade out objects when they get close to / obscure the camera. As with lots of shader stuff, I couldn't find one that worked exactly, so I had to do some tinkering. I thought I'd share it for anyone who needs it.

    It's a surface shader so there's no weird side effects like self shadowing lighting being gone...

    It just works super simply!

    Set the min distance for when the object is completely faded out and the max distance for when it is completely faded in and boom there you go. Works with GPU instancing etc.

    If anyone has any questions or requests on it let me know :)

    Code (CSharp):
    1. Shader "Custom/SoftClip" {
    2.     Properties {
    3.         _MainTex ("Base (RGB)", 2D) = "white" {}
    4.         _MinDistance ("Minimum Distance", float) = 3
    5.         _MaxDistance ("Maximum Distance", float) = 100
    6.     }
    7.     SubShader {
    8.         Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    9.         LOD 200
    10.         ZWrite Off
    11.         ZTest Less
    12.         Cull Back
    13.        
    14.         CGPROGRAM
    15.         #pragma surface surf Lambert alpha
    16.        
    17.  
    18.         sampler2D _MainTex;
    19.         float _MinDistance;
    20.         float _MaxDistance;
    21.  
    22.         struct Input {
    23.             float2 uv_MainTex;
    24.             float3 worldPos;
    25.         };
    26.  
    27.         void surf (Input IN, inout SurfaceOutput o) {
    28.             half4 c = tex2D (_MainTex, IN.uv_MainTex);
    29.             o.Albedo = c;
    30.             o.Alpha = 1;
    31.             float dist = distance(IN.worldPos, _WorldSpaceCameraPos);
    32.             if (dist < _MaxDistance) {
    33.                 o.Albedo = c.rgb;
    34.                 dist = dist - _MinDistance;
    35.                 float f = _MaxDistance - _MinDistance;
    36.                 float p = dist / f;
    37.                 float cl = lerp(0, 1, p);
    38.                 cl = min(1, cl);
    39.                 cl = max(0, cl);
    40.                 o.Alpha = cl;
    41.             }
    42.         }
    43.         ENDCG
    44.     }
    45.     FallBack "Diffuse"
    46. }
     
    ekrcoaster132 likes this.
  2. KibsgaardUnityStudios

    KibsgaardUnityStudios

    Joined:
    Jul 4, 2017
    Posts:
    8
    Hi,

    Thanks for this.

    I've taken it and simplified the fading logic a bit:

    Code (CSharp):
    1. Shader "Custom/StandardFade" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    6.         _Metallic ("Metallic", Range(0,1)) = 0.0
    7.         _MinDistance ("Minimum Distance", float) = 2
    8.         _MaxDistance ("Maximum Distance", float) = 3
    9.     }
    10.     SubShader {
    11.         Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    12.         LOD 200
    13.         ZWrite Off
    14.         ZTest LEqual
    15.         Cull Back
    16.  
    17.         CGPROGRAM
    18.         // Physically based Standard lighting model, and enable shadows on all light types
    19.         #pragma surface surf Standard fullforwardshadows alpha:fade
    20.  
    21.         // Use shader model 3.0 target, to get nicer looking lighting
    22.         #pragma target 3.0
    23.  
    24.         sampler2D _MainTex;
    25.  
    26.         struct Input {
    27.             float2 uv_MainTex;
    28.             float3 worldPos;
    29.         };
    30.  
    31.         half _Glossiness;
    32.         half _Metallic;
    33.         float _MinDistance;
    34.         float _MaxDistance;
    35.         fixed4 _Color;
    36.  
    37.         // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
    38.         // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
    39.         // #pragma instancing_options assumeuniformscaling
    40.         UNITY_INSTANCING_BUFFER_START(Props)
    41.             // put more per-instance properties here
    42.         UNITY_INSTANCING_BUFFER_END(Props)
    43.  
    44.         void surf (Input IN, inout SurfaceOutputStandard o) {
    45.             // Albedo comes from a texture tinted by color
    46.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    47.             o.Albedo = c.rgb;
    48.             // Metallic and smoothness come from slider variables
    49.             o.Metallic = _Metallic;
    50.             o.Smoothness = _Glossiness;
    51.  
    52.             // Fade the pixels as they get close to the camera (Start fading at _MaxDistance and become fully transparent at _MinDistance)
    53.             float distanceFromCamera = distance(IN.worldPos, _WorldSpaceCameraPos);
    54.             float fade = saturate((distanceFromCamera - _MinDistance) / _MaxDistance);
    55.          
    56.             o.Alpha = c.a * fade;
    57.         }
    58.         ENDCG
    59.     }
    60.     FallBack "Diffuse"
    61. }
    62.  
    Just a heads-up regarding performance, using an if-statement like in the original code is often actually worse than just performing the same operations on all threads (on a GPU).
     
    Last edited: Oct 21, 2020
    stonstad and Romaleks360 like this.
  3. D-Coy

    D-Coy

    Joined:
    Jun 2, 2013
    Posts:
    16
    Hey guys, this is great!
    Exactly what I was after.
    I am curious, if there is a simple way to make this HDRP compatible? From my understanding its not a simple process.
    Thanks!
     
    Last edited: Feb 6, 2019
  4. Jick87

    Jick87

    Joined:
    Oct 21, 2015
    Posts:
    124
    D-Coy likes this.
  5. AlfEspinosaN

    AlfEspinosaN

    Joined:
    Jan 14, 2019
    Posts:
    9
    Guys, I have the following error:

    As you can see, my horse's face has this weird transparency error with the new fade material. The material works as intended, but the face and front legs act weird now.
    I'm using this exact same solution and do not know how to fix it :(
    Can anybody help me with this?
     
    Last edited: Oct 20, 2020
  6. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,399
    It's a transparency sorting issue. Because this shader is using a soft alpha it's not going to write to the screen-space depth buffer, preventing the mesh from being able to properly depth-clip polygons that should be obscured by the depth value of the lips for example.

    What you'd likely want is an opaque "dithered transparency" shader instead, allowing it to write to the depth buffer. There's many examples online, though you'd have to adapt the distance based transparency lines from the shaders here to the dithered-transparency shader examples you find.

    Some examples:

    https://ocias.com/blog/unity-stipple-transparency-shader/
    https://github.com/gkjohnson/unity-dithered-transparency-shader
     
  7. AlfEspinosaN

    AlfEspinosaN

    Joined:
    Jan 14, 2019
    Posts:
    9
    Hey, thanks on the response! I'll sure check those out.
    Apparently, this issue could also be fixed by adding an extra pass that should only write to the depth buffer: https://docs.unity3d.com/Manual/SL-CullAndDepth.html.
    @KibsgaardUnityStudios helped me with this issue too. Here's my code in the end, which solved this transparency issue:

    Code (CSharp):
    1. Shader "Custom/StandardFade" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         _MinDistance ("Minimum Distance", float) = 2
    6.         _MaxDistance ("Maximum Distance", float) = 3
    7.     }
    8.     SubShader {
    9.         Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    10.  
    11. //this is the extra pass I had to add
    12.        Pass {
    13.         ZWrite On
    14.         ColorMask 0
    15.     }
    16.    
    17.         CGPROGRAM
    18.         #pragma surface surf Lambert alpha:fade
    19.         #pragma target 3.0
    20.         sampler2D _MainTex;
    21.         struct Input {
    22.             float2 uv_MainTex;
    23.             float3 worldPos;
    24.         };
    25.         half _Glossiness;
    26.         half _Metallic;
    27.         float _MinDistance;
    28.         float _MaxDistance;
    29.         fixed4 _Color;
    30.         void surf (Input IN, inout SurfaceOutput o) {
    31.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    32.             o.Albedo = c.rgb;
    33.             float distanceFromCamera = distance(IN.worldPos, _WorldSpaceCameraPos);
    34.             float fade = saturate((distanceFromCamera - _MinDistance) / _MaxDistance);
    35.      
    36.             o.Alpha = c.a * fade;
    37.         }
    38.         ENDCG
    39.     }
    40.     FallBack "Diffuse"
    41. }
     
  8. MirkoSon

    MirkoSon

    Joined:
    Oct 14, 2015
    Posts:
    24
    Hi everyone,
    is there any way to replicate this in URP? @AlfEspinosaN solution works flawlessly with the Builtin renderer but is it possible to convert that to the new Render Pipelines?
    I've been reading about issues with OIT (Order Independent Transparency) and also found this thread:
    https://forum.unity.com/threads/transparent-depth-shader-good-for-ghosts.149511/
    which is basically similar to this one, but I can't believe there's not an easy way to do the same in URP.
    Thanks in advance.
     
  9. KibsgaardUnityStudios

    KibsgaardUnityStudios

    Joined:
    Jul 4, 2017
    Posts:
    8
    I've adapted the shader for URP. See attached files (Shader + Inspector).

    This was made in URP 7.5.1 (2019.4) and might need to be adapted for newer versions.
     

    Attached Files:

  10. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    440
    Terrific, just what I needed. Thank you!
     
  11. Geckoo

    Geckoo

    Joined:
    Dec 7, 2014
    Posts:
    112
    Hello. This is an old post, sorry but I would like to improve this material shader. In fact, it works as expected, but I noticed a little problem which I cannot fix. When two objects use two differents materials using this shader, one is visible under the second. I guess that there is something wrong with the alpha pass. Do you have an idea? Thank you for your advice ++
     
  12. colind1233

    colind1233

    Joined:
    Feb 15, 2022
    Posts:
    1

    hello i am very new to unity and i would like to add this to my project but I am not sure how? I have all the urp things installed and ready to go but i am not sure where to put these files and what i should change within them? I know this thread us a bit old but any help would be appreciated. Thank you :)
     
  13. Geckoo

    Geckoo

    Joined:
    Dec 7, 2014
    Posts:
    112
    @colind1233 Welcome to you! Respectfully, I would like to recommend you to be wise. You are a newbie today (like we were) and you have to learn the basics. Don't rush too fast! In a few weeks, you will be able to create your own projects including some external scripts or shaders, and more. Unity provides a lot of interesting tutorials so as to understand how it works. Also I would like to recommend some Udemy courses. Wait a few days for a special offer and buy one course for less than 10$. I assume that it could be useful for you. So come back here so as to ask for help. Don't be angry with me. This is just a kind advice from an experienced guy with Unity. I wish you the best ++
     
    AllofPaul likes this.