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

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

    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:
    105
    @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. John1515

    John1515

    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,539
    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:
    305
    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:
    12,321
    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
     
    kankane, Edy and markuskir like this.
  28. lishuo2021

    lishuo2021

    Joined:
    Mar 18, 2021
    Posts:
    2
    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.
     
  30. StripeGuy

    StripeGuy

    Joined:
    Dec 30, 2016
    Posts:
    52

    I know this is an old thread that's been resurrected a few times, but anybody know of a way to make this shader work with URP (Universal Render Pipeline)?
     
  31. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,539
    transparent URP lit shaders already receive shadows, so you shouldn't need this custom shader. Make it fully transparent and set smoothness to 0.
     
    Last edited: Mar 30, 2023
  32. _deej

    _deej

    Joined:
    Aug 31, 2014
    Posts:
    2
    I know this is an old thread, but I just wanted to chime in and say that this worked PERFECTLY for my needs. Thank you SO much!

    I needed to receive shadows on a mesh that should otherwise be invisible, in order to fake shadows on an identical mesh that was rendering visibly on another camera via a separate layer (since shadows don't cast across layers). This fixed me up very well!
     
  33. StripeGuy

    StripeGuy

    Joined:
    Dec 30, 2016
    Posts:
    52
    No, this does NOT work for anyone coming in hoping this will work. And secondly, "transparent" doesn't make the material completely invisible like "fade" does in the Built-in RP, you can still see it slightly.
     
  34. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,539
    You can use this modified version of the shader from here: https://forum.unity.com/threads/wat...al-render-pipeline-order.748142/#post-5518747

    Code (CSharp):
    1. Shader "URP Transparent Shadow Receiver"
    2. {
    3.     Properties
    4.     {
    5.         _ShadowColor ("Shadow Color", Color) = (0.35,0.4,0.45,1.0)
    6.     }
    7.     SubShader
    8.     {
    9.         Tags
    10.         {
    11.             "RenderPipeline"="UniversalPipeline"
    12.             "RenderType"="Transparent"
    13.             "Queue"="Transparent-1"
    14.         }
    15.         Pass
    16.         {
    17.             Name "ForwardLit"
    18.             Tags { "LightMode" = "UniversalForward" }
    19.             Blend DstColor Zero, Zero One
    20.             Cull Back
    21.             ZTest LEqual
    22.             ZWrite Off
    23.  
    24.             HLSLPROGRAM
    25.             #pragma vertex vert
    26.             #pragma fragment frag
    27.             #pragma prefer_hlslcc gles
    28.             #pragma exclude_renderers d3d11_9x
    29.             #pragma target 2.0
    30.             #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
    31.             #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
    32.             #pragma multi_compile _ _SHADOWS_SOFT
    33.             #pragma multi_compile_fog
    34.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    35.             CBUFFER_START(UnityPerMaterial)
    36.             float4 _ShadowColor;
    37.             CBUFFER_END
    38.             struct Attributes
    39.             {
    40.                 float4 positionOS : POSITION;
    41.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    42.             };
    43.             struct Varyings
    44.             {
    45.                 float4 positionCS               : SV_POSITION;
    46.                 float3 positionWS               : TEXCOORD0;
    47.                 float fogCoord                  : TEXCOORD1;
    48.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    49.                 UNITY_VERTEX_OUTPUT_STEREO
    50.             };
    51.             Varyings vert (Attributes input)
    52.             {
    53.                 Varyings output = (Varyings)0;
    54.                 UNITY_SETUP_INSTANCE_ID(input);
    55.                 UNITY_TRANSFER_INSTANCE_ID(input, output);
    56.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
    57.                 VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
    58.                 output.positionCS = vertexInput.positionCS;
    59.                 output.positionWS = vertexInput.positionWS;
    60.                 output.fogCoord = ComputeFogFactor(vertexInput.positionCS.z);
    61.                 return output;
    62.             }
    63.             half4 frag (Varyings input) : SV_Target
    64.             {
    65.                 UNITY_SETUP_INSTANCE_ID(input);
    66.                 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
    67.                 half4 color = half4(1,1,1,1);
    68.             #if defined(_MAIN_LIGHT_SHADOWS) || defined(_MAIN_LIGHT_SHADOWS_CASCADE)
    69.                 VertexPositionInputs vertexInput = (VertexPositionInputs)0;
    70.                 vertexInput.positionWS = input.positionWS;
    71.                 float4 shadowCoord = GetShadowCoord(vertexInput);
    72.                 half shadowAttenutation = MainLightRealtimeShadow(shadowCoord);
    73.                 color = lerp(half4(1,1,1,1), _ShadowColor, (1.0 - shadowAttenutation) * _ShadowColor.a);
    74.                 color.rgb = MixFogColor(color.rgb, half3(1,1,1), input.fogCoord);
    75.            #endif
    76.                 return color;
    77.             }
    78.             ENDHLSL
    79.         }
    80.     }
    81. }
    Though this will only capture the main light shadows. If you want to get more advanced, you can play around with the ShaderGraph nodes from here: https://github.com/Cyanilux/URP_ShaderGraphCustomLighting
    to make an Unlit Shadergraph that samples all the Shadow sources.