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.
  2. Join us on March 30, 2023, between 5 am & 1 pm EST, in the Performance Profiling Dev Blitz Day 2023 - Q&A forum and Discord where you can connect with our teams behind the Memory and CPU Profilers.
    Dismiss Notice

Transparent shader receive shadows

Discussion in 'Shaders' started by patrikspacek, May 14, 2015.

  1. patrikspacek

    patrikspacek

    Joined:
    Apr 10, 2014
    Posts:
    13
    Hi Guys,

    I am looking for Transparent shader which receives shadows! This is for Unity 5.

    I need to hide geometry, which has visible shadows from other objects.

    Thank you
     
  2. patrikspacek

    patrikspacek

    Joined:
    Apr 10, 2014
    Posts:
    13
    Oops, nobody can code shaders here? I guess wrong community o_O
     
  3. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    This should work:

    Code (CSharp):
    1. Shader "Custom/TransparentShadowCollector"
    2. {
    3.     Properties
    4.     {
    5.         _ShadowIntensity ("Shadow Intensity", Range (0, 1)) = 0.6
    6.     }
    7.  
    8.  
    9.     SubShader
    10.     {
    11.  
    12.         Tags {"Queue"="AlphaTest" }
    13.  
    14.         Pass
    15.         {
    16.             Tags {"LightMode" = "ForwardBase" }
    17.             Cull Back
    18.             Blend SrcAlpha OneMinusSrcAlpha
    19.             CGPROGRAM
    20.             #pragma vertex vert
    21.             #pragma fragment frag
    22.             #pragma multi_compile_fwdbase
    23.  
    24.             #include "UnityCG.cginc"
    25.             #include "AutoLight.cginc"
    26.             uniform float _ShadowIntensity;
    27.  
    28.             struct v2f
    29.             {
    30.                 float4 pos : SV_POSITION;
    31.                 LIGHTING_COORDS(0,1)
    32.             };
    33.             v2f vert(appdata_base v)
    34.             {
    35.                 v2f o;
    36.                 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    37.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    38.                
    39.                 return o;
    40.             }
    41.             fixed4 frag(v2f i) : COLOR
    42.             {
    43.                 float attenuation = LIGHT_ATTENUATION(i);
    44.                 return fixed4(0,0,0,(1-attenuation)*_ShadowIntensity);
    45.             }
    46.             ENDCG
    47.         }
    48.  
    49.     }
    50.     Fallback "VertexLit"
    51. }
     
  4. patrikspacek

    patrikspacek

    Joined:
    Apr 10, 2014
    Posts:
    13
    Thanks it works ... 90% .. I am just wondering, why the shadow is also on wrong side of the object. There is a light going from the left... and it shouldnt go through the whole 3d object. Also could you add main color into it?

    (the table has shadow off, because the painting has its own shadow.)

    image:
    https://dl.dropboxusercontent.com/u/39935592/Echo_shader.jpg
     
    Last edited: May 15, 2015
    sskenth likes this.
  5. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    Could that shadow be caused by that figure standing there?

    A transparent shadow receiving object can be difficult sometimes to allow for all cases.

    Here's two to try, first is the same but with a main color:

    Code (CSharp):
    1. Shader "Custom/TransparentShadowCollector"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Main Color", Color) = (1,1,1,.5)
    6.         _ShadowIntensity ("Shadow Intensity", Range (0, 1)) = 0.6
    7.     }
    8.     SubShader
    9.     {
    10.         Tags {"Queue"="AlphaTest" }
    11.         Pass
    12.         {
    13.             Tags {"LightMode" = "ForwardBase" }
    14.             Cull Back
    15.             Blend SrcAlpha OneMinusSrcAlpha
    16.             CGPROGRAM
    17.             #pragma vertex vert
    18.             #pragma fragment frag
    19.             #pragma multi_compile_fwdbase
    20.             #include "UnityCG.cginc"
    21.             #include "AutoLight.cginc"
    22.             uniform fixed4  _Color;
    23.             uniform float _ShadowIntensity;
    24.             struct v2f
    25.             {
    26.                 float4 pos : SV_POSITION;
    27.                 LIGHTING_COORDS(0,1)
    28.             };
    29.             v2f vert(appdata_base v)
    30.             {
    31.                 v2f o;
    32.                 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    33.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    34.              
    35.                 return o;
    36.             }
    37.             fixed4 frag(v2f i) : COLOR
    38.             {
    39.                 float attenuation = LIGHT_ATTENUATION(i);
    40.                 return fixed4(0,0,0,(1-attenuation)*_ShadowIntensity) * _Color;
    41.             }
    42.             ENDCG
    43.         }
    44.     }
    45.     Fallback "VertexLit"
    46. }
    This is the same but is at a different render queue which can sometimes get better transparency results, but you might have some depth sorting issues:


    Code (CSharp):
    1. Shader "Custom/TransparentShadowCollector"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Main Color", Color) = (1,1,1,.5)
    6.         _ShadowIntensity ("Shadow Intensity", Range (0, 1)) = 0.6
    7.     }
    8.  
    9.  
    10.     SubShader
    11.     {
    12.  
    13.         Tags {"Queue"="Geometry" }
    14.  
    15.         Pass
    16.         {
    17.             Tags {"LightMode" = "ForwardBase" }
    18.             Cull Back
    19.             Blend SrcAlpha OneMinusSrcAlpha
    20.             CGPROGRAM
    21.             #pragma vertex vert
    22.             #pragma fragment frag
    23.             #pragma multi_compile_fwdbase
    24.  
    25.             #include "UnityCG.cginc"
    26.             #include "AutoLight.cginc"
    27.             uniform fixed4  _Color;
    28.             uniform float _ShadowIntensity;
    29.  
    30.             struct v2f
    31.             {
    32.                 float4 pos : SV_POSITION;
    33.                 LIGHTING_COORDS(0,1)
    34.             };
    35.             v2f vert(appdata_base v)
    36.             {
    37.                 v2f o;
    38.                 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    39.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    40.              
    41.                 return o;
    42.             }
    43.             fixed4 frag(v2f i) : COLOR
    44.             {
    45.                 float attenuation = LIGHT_ATTENUATION(i);
    46.                 return fixed4(0,0,0,(1-attenuation)*_ShadowIntensity) * _Color;
    47.             }
    48.             ENDCG
    49.         }
    50.  
    51.     }
    52.     Fallback "VertexLit"
    53. }
     
    Mehrdad995, Timps, kintovt and 8 others like this.
  6. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    Eek, sorry, that should + _Color not * _Color.
     
  7. patrikspacek

    patrikspacek

    Joined:
    Apr 10, 2014
    Posts:
    13
    Thank you for the main color.

    They both does same thing... no difference here.

    Yes, the person needs to stay there to show how it works.
    The table (3D object) should block the cast shadow as well. So only visible shadow from the character should be on top of the table. Not underneath, not on the side.

    : Now we have matte shader receiving shadows, which is cool! Correct. But the shadows arent blocked by the 3d objects as well.
     
  8. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I don't understand why you don't use shadows only property of mesh renderer? Why do you need a shader?
     
  9. patrikspacek

    patrikspacek

    Joined:
    Apr 10, 2014
    Posts:
    13
    Because it cast shadows only, not receives shadows.
     
  10. patrikspacek

    patrikspacek

    Joined:
    Apr 10, 2014
    Posts:
    13
    by changing * to + all shadows and matte is gone. So I keep * (46th line)
     
  11. patrikspacek

    patrikspacek

    Joined:
    Apr 10, 2014
    Posts:
    13
    Is there a way to have that hidden geometry occlude Indy??
     
  12. Flens

    Flens

    Joined:
    Sep 18, 2013
    Posts:
    1
    For the record, it's working, you have just to set the alpha of the main color to 0.
    Wonderful shader, thank you so much Echo4papa !
     
    echo4papa likes this.
  13. echo4papa

    echo4papa

    Joined:
    Mar 26, 2015
    Posts:
    158
    No problem. :D
     
  14. Nikolay1243

    Nikolay1243

    Joined:
    Jul 2, 2013
    Posts:
    9
    @echo4papa This works with directional lights but not spot lights...do you know how I can make it work with spot lights?
     
    AlexGone likes this.
  15. nekitamotip

    nekitamotip

    Joined:
    Mar 19, 2017
    Posts:
    2
  16. Klaus-Eiperle

    Klaus-Eiperle

    Joined:
    Mar 10, 2012
    Posts:
    41
    I think the second shader from post number 5 is working best. But is there a way to add a texture color to the shadow?
     
  17. paleajed

    paleajed

    Joined:
    Aug 22, 2017
    Posts:
    1
    Hi there, I tried the two last shaders to get a working shadow catcher when using Kudan for Unity, building for the Android platform. But alas, I see no shadow in the resulting app. I do have a shadow showing in the Unity viewport.

    Any ideas?
     
  18. ivank

    ivank

    Joined:
    Nov 16, 2013
    Posts:
    96
    @echo4papa
    @paleajed
    @Klaus-Eiperle
    Hello, do I understand correctly that the subject of the question (and answers) is something in 3D graphics called as matte shadow?

    I run into great matte shader from Unity guy Keigiro Takahashi, which also allows to adjust the color and transparency of the shadows: https://github.com/keijiro/ShadowDrawer

    It has however the drawback probably common for all similar shaders - it does not work against skyboxes - only against the solid color or another object (plane - floor, wall). Unfortunately it seems to be caused by Unity design itself :-(

    Does anybody know if Unity addressed this issue in the latest versions (2017.1 or 2)?
    Such feature is imho very useful for things like product visualization or AR and I really miss it...
     
  19. ezonecom

    ezonecom

    Joined:
    Jul 23, 2013
    Posts:
    17
    Yes, it would be very useful to have a shader like this that works with skyboxes. AFAIK 2017.2 does not address this.
     
    CloudyVR likes this.
  20. JelmerV

    JelmerV

    Joined:
    Nov 29, 2012
    Posts:
    248
    Hmm so a "solution" could be to make a big inside-out sphere around your scene with the skybox on it? :p not the best though..
     
  21. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,433
    2017.3 and the new HD Render pipeline does semi-transparent shadow receiving/casting by default. Right now you have to add the scriptable render loop assets to your project though from the git.
     
    n97968 likes this.
  22. iavetoshkin

    iavetoshkin

    Joined:
    Apr 4, 2018
    Posts:
    3

    The first code doesn't work... renders just black plane, nothing more. What can be wrong?
     

    Attached Files:

    Last edited: Apr 5, 2018
  23. Aaron-Meyers

    Aaron-Meyers

    Joined:
    Dec 8, 2009
    Posts:
    301
    Working on an AR project where we want to have the floors of our scenes be semi-transparent... some parts fully opaque fade to complete video background as well. At first I was struggling to get the floor to receive shadows, but in this thread, I saw the suggestion to use the Alpha-Test queue and after setting the render queue to 2500, the mesh receives shadows!

    However, there appears to be a big difference between DirectX 11 and Metal platforms: on Metal, the alpha of the fragment appears to effect the strength of the shadow... if the alpha is zero, you won't see ANY shadow at all... if alpha is .5, you see a half-way faded shadow, etc.

    On Windows (DirectX 11) the shadows show on all fragments, which is the effect I want so that the scenery can cast shadows on the cg floor as well as the real-world surface that the scene is placed on.

    I realize its a bit hack-y that putting the transparent shader on 2500 works to begin with, but I wonder if anyone can offer any suggestions that could make the shadows work regardless of the frag's alpha on Metal?
     
    Lynxed likes this.
  24. GuruGurra

    GuruGurra

    Joined:
    Jan 18, 2018
    Posts:
    38
    I know this is an old thread, but I have problems when building for Windows.

    I have used this shader for quite some time and it works perfectly in the editor and on Android devices. But when building the same project for Windows, there are no shadows :-(

    What should I do to get this shader work in Windows?

    EDIT:
    ====
    To answer my own question : The shader works just fine if the quality settings in Unity is set to Good or above. On Android, Unity selects the default level (which is set to Good), but in Windows Unity ignores the assigned default setting and instead selects the lowest available option (Fastest) which doesn't allow shadows.

    This of course make perfect sense, who knows - the game that runs perfectly fine on an Android device may overload my Threadripper 3960x/120GB/RTX2080Ti...:confused:

    I had to disable the Fastest, Fast and Simple quality levels in order for Unity to select the Good level in Windows, and now the shadows are back. :)
     
    Last edited: Jul 12, 2021
  25. Bodin

    Bodin

    Joined:
    Apr 19, 2017
    Posts:
    37
    This works great for my project! thank you very much for sharing.
     
  26. rich-gg

    rich-gg

    Joined:
    Mar 26, 2018
    Posts:
    10
    Hi there

    @echo4papa 's shader does the job, when the transparent object is a in front of 3D object or Mesh
    But if I have a Sprite between that 3D object and my shawdow shaded one, the sprite is no longer visible.

    I didn't find an easy and cheap way to get shadows on Sprite, so I'm using a transparent shadow receiver plan in front of my sprite to display the shadow. It works in URP but I have to downgrade to builtin so...

    any idea of how to solve that ?
     
    Last edited: Jan 14, 2022
  27. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    11,995
    Unity's built in renderer does not support shadows on transparent objects. Full stop.

    The shaders in this thread hack around that by making an otherwise "opaque" surface render with a transparent blend mode, but it is in fact still an "opaque" object. That means other transparent objects, or the skybox, will not render behind it. You can work around the issue of transparent objects not appearing when behind it by changing the ZWrite to On for the forward pass, but then transparent objects will always render on top.

    The solution is to use the URP / HDRP. If you can't, then you don't get shadows on transparent objects outside of very specific hacks like the "transparent" ground the shaders in this thread are attempting.


    There is one other work around that works for a single directional light, which is to expose that light's shadow map globally using a command buffer and then using custom code to sample it. But again, this only works for a single directional light. If you want to support shadow casting point or spot lights then you're out of luck.
    https://forum.unity.com/threads/usi...ows-in-forwardbase-pass.1080503/#post-6966797
     
    Edy and markuskir like this.
  28. lishuo2021

    lishuo2021

    Joined:
    Mar 18, 2021
    Posts:
    1
    same issue,any workround?
     
  29. rekcah1986_unity

    rekcah1986_unity

    Joined:
    Mar 1, 2022
    Posts:
    1
    You can create a new camera to render lower level parts, including the skybox.