Search Unity

Transparent Shader that Recieves Shadow (Kinda works already...)

Discussion in 'Shaders' started by Crueltiesladle, Apr 20, 2016.

  1. Crueltiesladle

    Crueltiesladle

    Joined:
    Jun 19, 2013
    Posts:
    15
    Hey, i found a transparent shader that recieves shadows and it seems to be working perfectly well but ONLY in the Editor...

    In the editor the color of the object is correct, which is the skybox
    In the game, the color of the object is the background color of the camera!
    Theres something going on here but i dont know what...

    Top is editor (desired result) Bottom is gameplay (undesired)


    And here's the code:


    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 "Diffuse"
    53. }
    54.  
    What's going on here? It feels so close yet out of reach :(
     
  2. Crueltiesladle

    Crueltiesladle

    Joined:
    Jun 19, 2013
    Posts:
    15
    I have a feeling it has soemthing to do with the LIGHTING_COORDS function but i can't find any documentation on that dang thing!

    Can anyone please help me out here, i don't understand why it'd be working on one and not the other.

    Is it possible to pull the skybox in specifically into the shader and then map the transparency as what the skybox output would be? Would that even work for what i'm trying to do?

    Btw if this doesnt make sense what im doing, i'm trying to fake lighting onto a photo realistic skybox and it seems to be working on the editor but not the gameplay, the outputs are weird...
     
  3. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    1,347
    The magic keyword is "Matte Shadow"... ;)
     
    Crueltiesladle likes this.
  4. Crueltiesladle

    Crueltiesladle

    Joined:
    Jun 19, 2013
    Posts:
    15
    I found one that seems to be for exact purpose that i'm using it for.

    But the same dang issue! I have no idea whats wrong...

    Why does it work perfectly in the editor and just use the damn background clear color for the camera in the game view..

    Here's the shader i found for it, it does exactly the same thing that the other one did... Just with a bit more control on the tranparency of the shadow

    Code (CSharp):
    1. Shader "FX/Matte Shadow" {
    2. Properties {
    3.     _Color ("Main Color", Color) = (1,1,1,1)
    4.     _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    5.     _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    6. }
    7. SubShader {
    8.     Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
    9.     LOD 200
    10. Blend Zero SrcColor
    11. CGPROGRAM
    12. #pragma surface surf ShadowOnly alphatest:_Cutoff
    13. fixed4 _Color;
    14. struct Input {
    15.     float2 uv_MainTex;
    16. } ;
    17. inline fixed4 LightingShadowOnly (SurfaceOutput s, fixed3 lightDir, fixed atten)
    18. {
    19.     fixed4 c;
    20.     c.rgb = s.Albedo*atten;
    21.     c.a = s.Alpha;
    22.     return c;
    23. }
    24. void surf (Input IN, inout SurfaceOutput o) {
    25.     fixed4 c = _Color;
    26.     o.Albedo = c.rgb;
    27.     o.Alpha = 1;
    28. }
    29. ENDCG
    30. }
    31. Fallback "Transparent/Cutout/VertexLit"
    32. }
    I also found this one that also does the exact same thing
    https://github.com/keijiro/ShadowDrawer/blob/master/Assets/ShadowDrawer.shader
    I tried this on multiple projects of different versions (5.1.1f and 5.3.3f1)

    This is so annoying, could someone check this and see if it isnt just me?
     
  5. bart_the_13th

    bart_the_13th

    Joined:
    Jan 16, 2012
    Posts:
    498
    The editor shows everything regardless of occlusion or draw order or everything else.
    You should check the camera preview, it represents exactly what the actual game view.

    Your shader(1st one) is rendered at geometry queue and it writes into zbuffer. Transparent objects usually rendered at Transparent queue and didnt write to zbuffer...
     
    Crueltiesladle likes this.
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    The skybox seems to draw differently between the scene view and game view. Mainly the skybox is drawn first in the scene view and everything else draws on top of it, but in the game view the skybox is "composited" into the scene after all opaque geometry is rendered. Specifically it appears the skybox gets rendered into the distance and gets z depth rejected by hardware. The problem is most of the matte shaders use Zwrite, which means the skybox won't show up behind it. They don't actually need Zwrite to be on, just the shadow caster pass needs to Zwrite, but they do need to be part of the opaque queues (2499 and below, which includes AlphaTest which is 2450) for shadow receiving to work.
     
    Crueltiesladle likes this.
  7. Crueltiesladle

    Crueltiesladle

    Joined:
    Jun 19, 2013
    Posts:
    15
    Oh my bgolus, we have progress it seems!



    I thought it's just rendering the box within the shadows, but maybe i messed up somewhere cause of some tests i did proved that to be wrong: (This is kinda big, uncompressed gif)
    https://dl.dropboxusercontent.com/u/109146535/LARGE/MatteShaderBug.gif

    I followed your instructions and this is what I did to the script:

    Code (CSharp):
    1. Shader "Custom/ShadowDrawer"
    2. {
    3.     Properties
    4.     {
    5.         _Color("Shadow Color", Color) = (0, 0, 0, 0.6)
    6.     }
    7.  
    8.         CGINCLUDE
    9.  
    10. #include "UnityCG.cginc"
    11. #include "AutoLight.cginc"
    12.  
    13.     struct v2f_shadow {
    14.         float4 pos : SV_POSITION;
    15.         LIGHTING_COORDS(0, 1)
    16.     };
    17.  
    18.     half4 _Color;
    19.  
    20.     v2f_shadow vert_shadow(appdata_full v)
    21.     {
    22.         v2f_shadow o;
    23.         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    24.         TRANSFER_VERTEX_TO_FRAGMENT(o);
    25.         return o;
    26.     }
    27.  
    28.     half4 frag_shadow(v2f_shadow IN) : SV_Target
    29.     {
    30.         half atten = LIGHT_ATTENUATION(IN);
    31.     return half4(_Color.rgb, lerp(_Color.a, 0, atten));
    32.     }
    33.  
    34.         ENDCG
    35.  
    36.         SubShader
    37.     {
    38.         Tags{ "Queue" = "AlphaTest+49" }
    39.             // Depth fill pass
    40.             ZWrite Off //<------------------------ Turned off ZWriting initially
    41.             Pass
    42.         {
    43.             ColorMask 0
    44.             CGPROGRAM
    45.  
    46. #pragma vertex vert
    47. #pragma fragment frag
    48.  
    49.         struct v2f {
    50.             float4 pos : SV_POSITION;
    51.         };
    52.  
    53.         v2f vert(appdata_full v)
    54.         {
    55.             v2f o;
    56.             o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    57.             return o;
    58.         }
    59.  
    60.         half4 frag(v2f IN) : SV_Target
    61.         {
    62.             return (half4)0;
    63.         }
    64.  
    65.             ENDCG
    66.         }
    67.  
    68.             // Forward base pass
    69.             Pass
    70.         {
    71.             Tags{ "LightMode" = "ForwardBase" }
    72.             Blend SrcAlpha OneMinusSrcAlpha
    73.             CGPROGRAM
    74.          
    75. #pragma vertex vert_shadow
    76. #pragma fragment frag_shadow
    77. #pragma multi_compile_fwdbase
    78.             ENDCG
    79.         }
    80.  
    81.             // Forward add pass
    82.             Pass
    83.         {
    84.             Tags{ "LightMode" = "ForwardAdd" }
    85.             Blend SrcAlpha OneMinusSrcAlpha
    86.             ZWrite On //<--------------------------------Seems like this was where shadows were being rendered, so i renabled it here
    87.             CGPROGRAM
    88. #pragma vertex vert_shadow
    89. #pragma fragment frag_shadow
    90. #pragma multi_compile_fwdbase
    91.             ENDCG
    92.         }
    93.     }
    94.     FallBack "Mobile/VertexLit"
    95. }
    What did i do wrong?
     
  8. Cascho01

    Cascho01

    Joined:
    Mar 19, 2010
    Posts:
    1,347
    Maybe this works:

    Code (CSharp):
    1. Shader "Custom/Matte Shadow" {
    2. Properties {
    3. _Color ("Main Color", Color) = (1,1,1,1)
    4. _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    5. _Cutoff ("Alpha Cutoff", Range(0,1)) = 0.5
    6. }
    7. SubShader {
    8. Tags {"Queue" = "Geometry-10" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
    9. LOD 200
    10. Blend Zero SrcColor
    11. Lighting Off
    12. ZTest LEqual
    13. ZWrite On
    14. ColorMask 0
    15. Pass {}
    16. CGPROGRAM
    17. #pragma surface surf ShadowOnly alphatest:_Cutoff
    18. fixed4 _Color;
    19. struct Input {
    20. float2 uv_MainTex;
    21. };
    22. inline fixed4 LightingShadowOnly (SurfaceOutput s, fixed3 lightDir, fixed atten)
    23. {
    24. fixed4 c;
    25. c.rgb = s.Albedo*atten;
    26. c.a = s.Alpha;
    27. return c;
    28. }
    29. void surf (Input IN, inout SurfaceOutput o) {
    30. fixed4 c = _Color;
    31. o.Albedo = c.rgb;
    32. o.Alpha = 1;
    33. }
    34. ENDCG
    35. }
    36. Fallback "Transparent/Cutout/VertexLit"
    37. }
     
    Crueltiesladle likes this.
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    If you're using a directional light in your scene it should be as simple as this:
    Code (CSharp):
    1. Shader "Custom/MatteShadow"
    2. {
    3. Properties
    4. {
    5.      _ShadowStrength ("Shadow Strength", Range (0, 1)) = 1
    6. }
    7. SubShader
    8. {
    9.     Tags
    10.     {
    11.         "Queue"="AlphaTest+49"
    12.         "IgnoreProjector"="True"
    13.         "RenderType"="Transparent"
    14.     }
    15.     Pass
    16.     {
    17.         Blend SrcAlpha OneMinusSrcAlpha
    18.         Tags {"LightMode" = "ForwardBase"}
    19.         ZWrite Off
    20.  
    21.         CGPROGRAM
    22.         #pragma vertex vert
    23.         #pragma fragment frag
    24.         #pragma multi_compile_fwdbase
    25.        
    26.         #include "UnityCG.cginc"
    27.         #include "AutoLight.cginc"
    28.         struct v2f
    29.         {
    30.             float4 pos : SV_POSITION;
    31.             SHADOW_COORDS(0)
    32.         };
    33.        
    34.         fixed _ShadowStrength;
    35.         v2f vert (appdata_img v)
    36.         {
    37.             v2f o;
    38.             o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    39.             TRANSFER_SHADOW(o);
    40.             return o;
    41.         }
    42.         fixed4 frag (v2f i) : COLOR
    43.         {
    44.             fixed shadow = SHADOW_ATTENUATION(i);
    45.             fixed shadowalpha = (1.0 - shadow) * _ShadowStrength;
    46.             return fixed4(0.0, 0.0, 0.0, shadowalpha);
    47.         }
    48.         ENDCG
    49.     }
    50.     Pass
    51.     {
    52.         Tags {"LightMode"="ShadowCaster"}
    53.  
    54.         CGPROGRAM
    55.         #pragma vertex vert
    56.         #pragma fragment frag
    57.         #pragma multi_compile_shadowcaster
    58.         #include "UnityCG.cginc"
    59.  
    60.         struct v2f {
    61.             V2F_SHADOW_CASTER;
    62.         };
    63.  
    64.         v2f vert(appdata_base v)
    65.         {
    66.             v2f o;
    67.             TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    68.             return o;
    69.         }
    70.  
    71.         float4 frag(v2f i) : SV_Target
    72.         {
    73.             SHADOW_CASTER_FRAGMENT(i)
    74.         }
    75.         ENDCG
    76.     }
    77. }
    78. }
    79.  
    If you're trying to get the shadow from a point, spot, or secondary directional light it gets a little more interesting.
     
    Crueltiesladle likes this.
  10. Crueltiesladle

    Crueltiesladle

    Joined:
    Jun 19, 2013
    Posts:
    15
    This one doesn't seem to work in either view, makes a weird tinted spot but thats about it


    This one produces this result:

    Can see the skybox in the gameview, but no shadows...
     
  11. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    Right ... because the skybox overwrites anything w/o zwrite. Fark, forgot about that.

    Code (CSharp):
    1. Shader "Custom/MatteShadow"
    2. {
    3. Properties
    4. {
    5.      _ShadowStrength ("Shadow Strength", Range (0, 1)) = 1
    6. }
    7. SubShader
    8. {
    9.     Tags
    10.     {
    11.         "Queue"="AlphaTest+49"
    12.         "IgnoreProjector"="True"
    13.         "RenderType"="Transparent"
    14.     }
    15.     Pass
    16.     {
    17.         Tags {"LightMode" = "ForwardBase"}
    18.         ZWrite On
    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.         struct v2f
    27.         {
    28.             float4 pos : SV_POSITION;
    29.             SHADOW_COORDS(0)
    30.         };
    31.      
    32.         fixed _ShadowStrength;
    33.         v2f vert (appdata_img v)
    34.         {
    35.             v2f o;
    36.             o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    37.             TRANSFER_SHADOW(o);
    38.             return o;
    39.         }
    40.         fixed4 frag (v2f i) : COLOR
    41.         {
    42.             fixed shadow = SHADOW_ATTENUATION(i);
    43.             fixed shadowalpha = (1.0 - shadow) * _ShadowStrength;
    44.             clip(shadowalpha - 0.5);
    45.             return fixed4(0.0, 0.0, 0.0, 1.0);
    46.         }
    47.         ENDCG
    48.     }
    49.     Pass
    50.     {
    51.         Tags {"LightMode"="ShadowCaster"}
    52.         CGPROGRAM
    53.         #pragma vertex vert
    54.         #pragma fragment frag
    55.         #pragma multi_compile_shadowcaster
    56.         #include "UnityCG.cginc"
    57.         struct v2f {
    58.             V2F_SHADOW_CASTER;
    59.         };
    60.         v2f vert(appdata_base v)
    61.         {
    62.             v2f o;
    63.             TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    64.             return o;
    65.         }
    66.         float4 frag(v2f i) : SV_Target
    67.         {
    68.             SHADOW_CASTER_FRAGMENT(i)
    69.         }
    70.         ENDCG
    71.     }
    72. }
    73. }
    74.  
    That will work, but it'll be a little ugly. The shadows have to be black and have to be hard edged. The only way around this is to not use the sky and render the background as an object in the scene (could be the same cubemap used by the skybox, it just can't be a skybox shader).
     
  12. Crueltiesladle

    Crueltiesladle

    Joined:
    Jun 19, 2013
    Posts:
    15
    Yes!!!! Thats awesome it works really well.

    You actually helped me more by giving my the idea to render the skybox as a seperate object. Now all the other matte shaders work flawlessly.

    Thanks a lot everyone! Especially you Bgolus :D
     
  13. nugao

    nugao

    Joined:
    Nov 17, 2011
    Posts:
    20
    Nice.....Thank you very much.
     
  14. rob_ice

    rob_ice

    Joined:
    Nov 11, 2016
    Posts:
    112
    Any update on this shader to receive shadows from a point light?
     
  15. threeguysgamestudio

    threeguysgamestudio

    Joined:
    Dec 1, 2017
    Posts:
    25
    Hi bgolus,

    I'm wondering if there is now a way around only using black pixels to draw the shadows on transparent surfaces to get a nicer looking shadow?
     
  16. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    Yes and no. The upcoming HD pipeline comes with built in support for shadows on transparent objects. The Lightweight pipeline initially had support for this, then pulled it, but may add it again at some future date. (edit: looks like it's working again in 2.0.3, not sure when they added it back in.)

    For the built in forward rendering path nothing has changed. If you don't use Unity's skybox you can fake it by making an opaque object use a blend, otherwise hard shadows is the only answer.
     
    Last edited: Jun 27, 2018
  17. Ikarus123

    Ikarus123

    Joined:
    Jan 12, 2019
    Posts:
    2
    This may seem like a silly question with an obvious answer, but how do you apply this? I'm a newbie and I was hoping I could simply render objects with cast shadows in fully HDRi scenes.
     
  18. CedricMorelFrancoz

    CedricMorelFrancoz

    Joined:
    May 9, 2019
    Posts:
    5
    HI,

    with the first version of the MatteShadow shader, I have this result :

    A.png
    so strenght of the shadow is adjustable but it's doesn't work in the game view.


    With the second version of the MatteShadow shader , i have this result :

    B.png
    it's now working in the game view but the shadows are not adjustable (their aspect are totally black or invisible).

    Is there an ultimate solution with adjustable shadow that's works in the game view with a skybox ?

    Thank you
     
  19. CedricMorelFrancoz

    CedricMorelFrancoz

    Joined:
    May 9, 2019
    Posts:
    5
    I note that behind an object which has this shader, all non opaque objects (for example which has a unity standard shader but with its rendering mode set to transparent) are invisible.
    Any idea about this "phenomenom" ?
     
  20. tbgames3000

    tbgames3000

    Joined:
    Mar 3, 2017
    Posts:
    3
    This works perfectly when I run it in the editor but when I test it on Oculus Quest 2, there are no shadows. Does anyone know why?