Search Unity

The Shadow can be seen through the Plane

Discussion in 'Shaders' started by Keronius, Apr 29, 2018.

  1. Keronius

    Keronius

    Joined:
    May 14, 2017
    Posts:
    9

    Hi Everyone, I'm making a Geometry shader where I build a plane of a single triangle, all works nice but when I'm trying to Cast / Recieve Shadows, the shadows Generated by other objects can be seen through that plane, here's how I'm generating the lighting:

    Code (CSharp):
    1. v2g{
    2. ...
    3. SHADOW_COORDS(1)
    4. }
    5.  
    6. g2f{
    7. ...
    8. LIGHTING_COORDS(1,2)
    9. }
    10.  
    11. VertShader{
    12. ...
    13. TRANSFER_SHADOW(o);
    14. }
    15.  
    16. GeomtryShader{
    17. //Code to generate plane vertexs...
    18. TRANSFER_VERTEX_TO_FRAGMENT(o);
    19. //tristream.Append(o); ...This process with all my generated vertexs
    20. }
    21.  
    22. Fragment{
    23. // Calculate Color...
    24. half nl = max(0, dot(i.norm, _WorldSpaceLightPos0.xyz));
    25. fixed3 diff = nl * _LightColor0.rgb;
    26. fixed3 ambientL = ShadeSH9(half4(i.norm, 1));;
    27. fixed shadow = SHADOW_ATTENUATION(i);
    28. fixed3 lighting = diff * shadow + ambientL;
    29. col.rgb *= lighting;
    30. return col;
    31. }
    Another thing is that if a shadows is over the plane the plane didn't recieve the shadow.

    Thanks for any help
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
  3. Keronius

    Keronius

    Joined:
    May 14, 2017
    Posts:
    9
    I create this example to understand how this work on Geometry shaders:


    Here is the 'ShadowCaster' Pass:

    Code (CSharp):
    1.  
    2. Pass {
    3. Tags {"LightMode"="ShadowCaster"}
    4.  
    5. CGPROGRAM
    6. #pragma vertex vert
    7.             #pragma geometry geometryShader
    8. #pragma fragment frag
    9.          
    10. #include "UnityCG.cginc"
    11.  
    12. #pragma multi_compile_shadowcaster
    13.  
    14. float Size;
    15.  
    16. struct v2g {
    17.     V2F_SHADOW_CASTER;
    18.  
    19.     float3 normal: NORMAL;
    20. };
    21.  
    22. struct g2f {
    23.     V2F_SHADOW_CASTER;
    24. };
    25.  
    26. v2g vert(appdata_base v)
    27. {
    28.     v2g o;
    29.     TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    30.     o.normal = v.normal;
    31.     return o;
    32. }
    33.  
    34. [maxvertexcount(50)]
    35. void geometryShader(triangle v2g IN[3], inout TriangleStream < g2f > tristream){
    36.     float4 VertexA = IN[0].pos;
    37.     float4 VertexB = IN[1].pos;
    38.     float4 VertexC = IN[2].pos;
    39.  
    40.     float3 NormalA = IN[0].normal;
    41.     float3 NormalB = IN[1].normal;
    42.     float3 NormalC = IN[2].normal;
    43.  
    44.     g2f o = (g2f) 0;
    45.  
    46.     o.pos = VertexA;
    47.     tristream.Append(o);
    48.  
    49.     o.pos = VertexB;
    50.     tristream.Append(o);
    51.  
    52.     o.pos = VertexC;
    53.     tristream.Append(o);
    54.  
    55.     tristream.RestartStrip();
    56.  
    57.     o.pos = VertexA;
    58.     tristream.Append(o);
    59.  
    60.     o.pos = VertexB;
    61.     tristream.Append(o);
    62.  
    63.     o.pos = VertexA + float4(NormalA, 1.f) * Size;
    64.     tristream.Append(o);
    65.  
    66.     tristream.RestartStrip();
    67. }
    68.  
    69. float4 frag(g2f i) : SV_Target
    70. {
    71.     SHADOW_CASTER_FRAGMENT(i)
    72. }
    73.  
    74. ENDCG
    75.  
    76.  
    What is missing on the 'ShadowCaster' Pass?, I'm trying to learn but I didn't find a Geometry Shader Example.

    Thanks for any help.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    Maybe Cull Off? Not sure, can you post the full shader?
     
  5. Keronius

    Keronius

    Joined:
    May 14, 2017
    Posts:
    9
    Here is the full Shader:

    Code (CSharp):
    1. Shader "ShadowTest" {
    2.     Properties {
    3.  
    4.     }
    5.  
    6.     SubShader {
    7.  
    8.         Cull off
    9.  
    10.         Pass {
    11.  
    12.             Tags { "LightMode" = "ForwardBase" }
    13.  
    14.             CGPROGRAM
    15.             #pragma vertex vertex
    16.             #pragma geometry geometry
    17.             #pragma fragment fragment
    18.  
    19.             #include "AutoLight.cginc"
    20.             #include "UnityCG.cginc"
    21.             #include "Lighting.cginc"
    22.  
    23.             #pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap novertexlight
    24.  
    25.             struct v2g {
    26.                 float4 pos: POSITION;
    27.                 float3 normal: NORMAL;
    28.  
    29.                 SHADOW_COORDS(1)
    30.             };
    31.  
    32.             struct g2f {
    33.                 float4 pos: SV_POSITION;
    34.                 float3 normal: NORMAL;
    35.  
    36.                 fixed4 col: COLOR2;
    37.                 LIGHTING_COORDS(1, 2)
    38.             };
    39.  
    40.             v2g vertex(appdata_base v) {
    41.                 v2g o;
    42.                 o.pos = v.vertex;
    43.                 o.normal = v.normal;
    44.  
    45.                 TRANSFER_SHADOW(o)
    46.                 return o;
    47.             }
    48.  
    49.             [maxvertexcount(50)]
    50.             void geometry(triangle v2g IN[3], inout TriangleStream < g2f > tristream){
    51.                 float4 VertexA = IN[0].pos;
    52.                 float4 VertexB = IN[1].pos;
    53.                 float4 VertexC = IN[2].pos;
    54.  
    55.                 g2f o = (g2f) 0;
    56.  
    57.                 o.pos = UnityObjectToClipPos(VertexA);
    58.                 o.normal = IN[0].normal;
    59.                 o.col = fixed4(1.f, 0, 0, 1.f);
    60.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    61.                 tristream.Append(o);
    62.  
    63.                 o.pos = UnityObjectToClipPos(VertexB);
    64.                 o.normal = IN[1].normal;
    65.                 o.col = fixed4(0, 0, 1.f, 1.f);
    66.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    67.                 tristream.Append(o);
    68.  
    69.                 o.pos = UnityObjectToClipPos(VertexC);
    70.                 o.normal = IN[2].normal;
    71.                 o.col = fixed4(0, 1.f, 0, 1.f);
    72.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    73.                 tristream.Append(o);
    74.  
    75.                 tristream.RestartStrip();
    76.  
    77.                 o.pos = UnityObjectToClipPos(VertexA);
    78.                 o.normal = IN[0].normal;
    79.                 o.col = fixed4(1.f, 0, 0, 1.f);
    80.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    81.                 tristream.Append(o);
    82.  
    83.                 o.pos = UnityObjectToClipPos(VertexB);
    84.                 o.normal = IN[1].normal;
    85.                 o.col = fixed4(0, 0, 1.f, 1.f);
    86.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    87.                 tristream.Append(o);
    88.  
    89.                 o.pos = UnityObjectToClipPos(VertexA + float4(IN[0].normal, 1.f));
    90.                 o.normal = IN[2].normal;
    91.                 o.col = fixed4(0, 1.f, 0, 1.f);
    92.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    93.                 tristream.Append(o);
    94.  
    95.                 tristream.RestartStrip();
    96.             }
    97.  
    98.             fixed4 fragment(g2f i) : SV_Target {
    99.                 fixed4 col = i.col;
    100.                 fixed shadow = SHADOW_ATTENUATION(i);
    101.                 float3 norm = UnityObjectToWorldNormal(i.normal);
    102.  
    103.                 half nl = max(0, dot(norm, _WorldSpaceLightPos0.xyz));
    104.                 fixed3 diff = nl * _LightColor0.rgb;
    105.                 fixed3 ambientL = ShadeSH9(half4(norm, 1));
    106.  
    107.                 fixed3 lighting = diff * shadow + ambientL;
    108.  
    109.                 col.rgb *= lighting;
    110.                 return col;
    111.             }
    112.             ENDCG
    113.         }
    114.  
    115.         Pass {
    116.  
    117.             Tags { "LightMode" = "ShadowCaster" }
    118.  
    119.             CGPROGRAM
    120.             #pragma vertex vertex
    121.             #pragma geometry geometry
    122.             #pragma fragment fragment
    123.  
    124.             #include "UnityCG.cginc"
    125.  
    126.             #pragma multi_compile_shadowcaster
    127.  
    128.             struct v2g {
    129.                 V2F_SHADOW_CASTER;
    130.  
    131.                 float3 normal: NORMAL;
    132.             };
    133.  
    134.             struct g2f {
    135.                 V2F_SHADOW_CASTER;
    136.             };
    137.  
    138.             v2g vertex(appdata_base v)
    139.             {
    140.                 v2g o;
    141.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    142.                 o.normal = v.normal;
    143.                 return o;
    144.             }
    145.  
    146.             [maxvertexcount(80)]
    147.             void geometry(triangle v2g IN[3], inout TriangleStream < g2f > tristream){
    148.                 float4 VertexA = IN[0].pos;
    149.                 float4 VertexB = IN[1].pos;
    150.                 float4 VertexC = IN[2].pos;
    151.  
    152.                 g2f o = (g2f) 0;
    153.  
    154.                 o.pos = VertexA;
    155.                 tristream.Append(o);
    156.  
    157.                 o.pos = VertexB;
    158.                 tristream.Append(o);
    159.  
    160.                 o.pos = VertexC;
    161.                 tristream.Append(o);
    162.  
    163.                 tristream.RestartStrip();
    164.  
    165.                 o.pos = VertexA;
    166.                 tristream.Append(o);
    167.  
    168.                 o.pos = VertexB;
    169.                 tristream.Append(o);
    170.  
    171.                 o.pos = VertexA + float4(IN[0].normal, 1.f);
    172.                 tristream.Append(o);
    173.  
    174.                 tristream.RestartStrip();
    175.             }
    176.  
    177.             float4 fragment(g2f i) : SV_Target
    178.             {
    179.                 SHADOW_CASTER_FRAGMENT(i)
    180.             }
    181.             ENDCG
    182.         }
    183.     }
    184. }
    185.  
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    The TRANSFER_SHADOW_CASTER_NORMALOFFSET macro manipulates the vertex position and transforms it into clip space. You don't want to do this in the vertex shader since you need the object space position in the geometry shader, but you do want to call it in the geometry shader.

    The TRANSFER_SHADOW_CASTER_NORMALOFFSET macro is looking for object space variables named v.vertex and v.normal to use to transform, so I'm reusing the v2g struct which has precisely those two variables.

    Code (CSharp):
    1. Shader "ShadowTest" {
    2.     Properties {
    3.     }
    4.     SubShader {
    5.         Cull off
    6.         Pass {
    7.             Tags { "LightMode" = "ForwardBase" }
    8.             CGPROGRAM
    9.             #pragma vertex vertex
    10.             #pragma geometry geometry
    11.             #pragma fragment fragment
    12.             #include "AutoLight.cginc"
    13.             #include "UnityCG.cginc"
    14.             #include "Lighting.cginc"
    15.             #pragma multi_compile_fwdbase nolightmap nodirlightmap nodynlightmap novertexlight
    16.             struct v2g {
    17.                 float4 pos: POSITION;
    18.                 float3 normal: NORMAL;
    19.                 SHADOW_COORDS(1)
    20.             };
    21.             struct g2f {
    22.                 float4 pos: SV_POSITION;
    23.                 float3 normal: NORMAL;
    24.                 fixed4 col: COLOR2;
    25.                 LIGHTING_COORDS(1, 2)
    26.             };
    27.             v2g vertex(appdata_base v) {
    28.                 v2g o;
    29.                 o.pos = v.vertex;
    30.                 o.normal = v.normal;
    31.                 TRANSFER_SHADOW(o)
    32.                 return o;
    33.             }
    34.             [maxvertexcount(50)]
    35.             void geometry(triangle v2g IN[3], inout TriangleStream < g2f > tristream){
    36.                 float4 VertexA = IN[0].pos;
    37.                 float4 VertexB = IN[1].pos;
    38.                 float4 VertexC = IN[2].pos;
    39.                 g2f o = (g2f) 0;
    40.                 o.pos = UnityObjectToClipPos(VertexA);
    41.                 o.normal = IN[0].normal;
    42.                 o.col = fixed4(1.f, 0, 0, 1.f);
    43.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    44.                 tristream.Append(o);
    45.                 o.pos = UnityObjectToClipPos(VertexB);
    46.                 o.normal = IN[1].normal;
    47.                 o.col = fixed4(0, 0, 1.f, 1.f);
    48.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    49.                 tristream.Append(o);
    50.                 o.pos = UnityObjectToClipPos(VertexC);
    51.                 o.normal = IN[2].normal;
    52.                 o.col = fixed4(0, 1.f, 0, 1.f);
    53.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    54.                 tristream.Append(o);
    55.                 tristream.RestartStrip();
    56.                 o.pos = UnityObjectToClipPos(VertexA);
    57.                 o.normal = IN[0].normal;
    58.                 o.col = fixed4(1.f, 0, 0, 1.f);
    59.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    60.                 tristream.Append(o);
    61.                 o.pos = UnityObjectToClipPos(VertexB);
    62.                 o.normal = IN[1].normal;
    63.                 o.col = fixed4(0, 0, 1.f, 1.f);
    64.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    65.                 tristream.Append(o);
    66.                 o.pos = UnityObjectToClipPos(VertexA + float4(IN[0].normal, 1.f));
    67.                 o.normal = IN[2].normal;
    68.                 o.col = fixed4(0, 1.f, 0, 1.f);
    69.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    70.                 tristream.Append(o);
    71.                 tristream.RestartStrip();
    72.             }
    73.             fixed4 fragment(g2f i) : SV_Target {
    74.                 fixed4 col = i.col;
    75.                 fixed shadow = SHADOW_ATTENUATION(i);
    76.                 float3 norm = UnityObjectToWorldNormal(i.normal);
    77.                 half nl = max(0, dot(norm, _WorldSpaceLightPos0.xyz));
    78.                 fixed3 diff = nl * _LightColor0.rgb;
    79.                 fixed3 ambientL = ShadeSH9(half4(norm, 1));
    80.                 fixed3 lighting = diff * shadow + ambientL;
    81.                 col.rgb *= lighting;
    82.                 return col;
    83.             }
    84.             ENDCG
    85.         }
    86.         Pass {
    87.             Tags { "LightMode" = "ShadowCaster" }
    88.             CGPROGRAM
    89.             #pragma vertex vertex
    90.             #pragma geometry geometry
    91.             #pragma fragment fragment
    92.             #include "UnityCG.cginc"
    93.             #pragma multi_compile_shadowcaster
    94.             struct v2g {
    95.                 float4 vertex: POSITION;
    96.                 float3 normal: NORMAL;
    97.             };
    98.             struct g2f {
    99.                 V2F_SHADOW_CASTER;
    100.             };
    101.             v2g vertex(appdata_base v)
    102.             {
    103.                 v2g o;
    104.                 o.vertex = v.vertex;
    105.                 o.normal = v.normal;
    106.                 return o;
    107.             }
    108.             [maxvertexcount(80)]
    109.             void geometry(triangle v2g IN[3], inout TriangleStream < g2f > tristream){
    110.                 g2f o = (g2f) 0;
    111.                  v2g v = (v2g) 0;
    112.  
    113.                 v = IN[0];
    114.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
    115.                 tristream.Append(o);
    116.                 v = IN[1];
    117.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
    118.                 tristream.Append(o);
    119.                 v = IN[2];
    120.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
    121.                 tristream.Append(o);
    122.                 tristream.RestartStrip();
    123.                 v = IN[0];
    124.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
    125.                 tristream.Append(o);
    126.                 v = IN[1];
    127.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
    128.                 tristream.Append(o);
    129.                 v = IN[0];
    130.                 v.vertex += float4(v.normal, 0.f);
    131.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o);
    132.                 tristream.Append(o);
    133.                 tristream.RestartStrip();
    134.             }
    135.             float4 fragment(g2f i) : SV_Target
    136.             {
    137.                 SHADOW_CASTER_FRAGMENT(i)
    138.             }
    139.             ENDCG
    140.         }
    141.     }
    142. }
     
  7. Keronius

    Keronius

    Joined:
    May 14, 2017
    Posts:
    9
    bgolus, you are the man, thank you so much!