Search Unity

Geometry shader with shadows not displaying shadows properly

Discussion in 'Shaders' started by harvz16, Jun 1, 2014.

  1. harvz16

    harvz16

    Joined:
    Dec 10, 2012
    Posts:
    12
    hey all,

    I've been working for a while, trying to get a geometry shader that supports lighting shadows up and running, so far I have the geometry creating a quad (this is just a place holder for later), and thanks to a few helpful posts around the place, it correctly responds to lighting and casts shadows but when it comes to 'catching' the shadows, it seems to just display the shadows from the mesh behind.

    $shadow error.png
    (the shadow drawing on top of the quad is actually its own shadow, if looked at from a steeper angle, there are no shadows on the quad itself)

    I have tried placing a cube above the quad, which has the same effect.

    Here's the shader so far:

    Code (csharp):
    1. Shader "Custom/Geo_Unlit" {
    2.     Properties {
    3.         _MainTex ("Base (RGB)", 2D) = "white" {}
    4.     }
    5.     SubShader {
    6.         Tags {"Queue" = "Geometry" "RenderType"="Opaque" }
    7.         LOD 200
    8.        
    9.         pass{
    10.             Name "ForwardBase"
    11.             Tags {"LightMode" = "ForwardBase"}
    12.            
    13.             CGPROGRAM
    14.  
    15.             sampler2D _MainTex;
    16.             #pragma target 5.0
    17.  
    18.             #pragma vertex vert
    19.             #pragma geometry geo
    20.             #pragma fragment frag
    21.             #pragma multi_compile_fwdbase
    22.  
    23.             #include "UnityCG.cginc"
    24.            
    25.            
    26.             #include "Lighting.cginc"
    27.             #include "AutoLight.cginc"
    28.            
    29.             struct vIn
    30.             {
    31.                 float4 pos : POSITION;
    32.                 float4 col : COLOR;
    33.             };
    34.            
    35.             struct gfIn
    36.             {
    37.                 float4 pos: POSITION;
    38.                 float3 norm : NORMAL;
    39.                 float4 col : COLOR;
    40.                 float3 vlight: TEXCOORD0;
    41.                 LIGHTING_COORDS(1,2)
    42.             };
    43.  
    44.             vIn vert(vIn v)
    45.             {
    46.                 vIn o;
    47.                 o.pos = v.pos;
    48.                 o.col = v.col;
    49.                 return o;
    50.             }
    51.  
    52.             [maxvertexcount(4)]
    53.             void geo(point vIn v[1], inout TriangleStream<gfIn> ts)
    54.             {
    55.                 float h = .5f;
    56.                 float4 p[4];
    57.                
    58.                 p[0] = float4(-h, 0.0f, -h, 0.0f);
    59.                 p[1] = float4(-h, 0.0f,  h, 0.0f);
    60.                 p[2] = float4( h, 0.0f, -h, 0.0f);
    61.                 p[3] = float4( h, 0.0f,  h, 0.0f);
    62.                
    63.                 for (int i = 0; i < 4; ++i)
    64.                 {
    65.                     gfIn r;
    66.                     r.norm = float3(0,1,0);
    67.                     r.col = v[0].col;
    68.                    
    69.                
    70.                     r.pos = mul( UNITY_MATRIX_MVP, v[0].pos + p[i]);
    71.                     r.vlight = normalize(ObjSpaceLightDir(v[0].pos + p[i]));
    72.                     TRANSFER_VERTEX_TO_FRAGMENT(r);
    73.                     ts.Append(r);
    74.                 }
    75.             }
    76.  
    77.             float4 frag(gfIn fin) : COLOR
    78.             {
    79.                 float4 t = fin.col;
    80.                 fin.vlight = normalize(fin.vlight);
    81.                
    82.                 fixed atten = LIGHT_ATTENUATION(fin);
    83.                 fixed diff = saturate(dot(normalize(fin.norm), normalize(fin.vlight)));
    84.                
    85.                 fixed4 c;
    86.                 c.rgb = UNITY_LIGHTMODEL_AMBIENT.rgb * 2 * t.rgb;
    87.                 c.rgb += (t.rgb * _LightColor0.rgb * diff) * (atten * 2);
    88.                 c.a = t.a + _LightColor0.a * atten;
    89.                 return c;
    90.             }
    91.  
    92.             ENDCG
    93.         }//end pass
    94.  
    95.      
    96. //////////////////////////////////////////////////////////////////////////////////////////////////////        
    97. ///////////////////////////////////Shadow Cast////////////////////////////////////////////////////////
    98. //////////////////////////////////////////////////////////////////////////////////////////////////////
    99. pass{
    100.             Name "ShadowCaster"
    101.             Tags {"LightMode" = "ShadowCaster"}
    102.            
    103.             Fog {Mode Off}
    104.             ZWrite On ZTest Less Cull Off
    105.             Offset 1, 1
    106.            
    107.             CGPROGRAM
    108.  
    109.             sampler2D _MainTex;
    110.             #pragma target 5.0
    111.  
    112.             #pragma vertex vert
    113.             #pragma geometry geo
    114.             #pragma fragment frag
    115.             #pragma multi_compile_shadowcaster
    116.             #pragma fragmentoption ARB_precision_hint_fastest
    117.             #include "UnityCG.cginc"
    118.            
    119.             struct v2f{
    120.                 V2F_SHADOW_CASTER;
    121.             };
    122.            
    123.             struct vIn
    124.             {
    125.                 float4 pos : POSITION;
    126.             };
    127.  
    128.  
    129.             v2f vert(vIn v)
    130.             {
    131.                 v2f o = (v2f)0;
    132.                 o.pos = v.pos;
    133.                 return o;
    134.             }
    135.  
    136.             [maxvertexcount(4)]
    137.             void geo(point v2f v[1], inout TriangleStream<v2f> ts)
    138.             {
    139.                 float h = .5f;
    140.                 float4 p[4];
    141.                
    142.                 p[0] = float4(-h, 0.0f, -h, 0.0f);
    143.                 p[1] = float4(-h, 0.0f,  h, 0.0f);
    144.                 p[2] = float4( h, 0.0f, -h, 0.0f);
    145.                 p[3] = float4( h, 0.0f,  h, 0.0f);
    146.                
    147.                 for (int i = 0; i < 4; ++i)
    148.                 {
    149.                
    150.                     v2f r = v[0];
    151.                     r.pos = mul( UNITY_MATRIX_MVP, v[0].pos + p[i]);
    152.                     ts.Append(r);
    153.                 }
    154.             }
    155.  
    156.             float4 frag(v2f fin) : COLOR
    157.             {
    158.                 SHADOW_CASTER_FRAGMENT(fin)
    159.             }
    160.  
    161.             ENDCG
    162.         }//end pass
    163.     }
    164. }
     
  2. metaleap

    metaleap

    Joined:
    Oct 3, 2012
    Posts:
    589
    Without ever having written a single geometry shader in my whole life, here's a hint: you have a forward pass and a shadow-caster pass but no "shadow-collector pass". I have a hunch that writing one (extremely similar to shadow-caster-pass, check out some #pragma-debug surface shader or something) could well resolve this.
     
  3. harvz16

    harvz16

    Joined:
    Dec 10, 2012
    Posts:
    12
    Thanks, that really did give me a nudge in the right direction.

    Thought I should post the working shadow collector code.
    Code (CSharp):
    1.     pass{
    2.             Name "ShadowCollector"
    3.  
    4.             Tags {"LightMode" = "ShadowCollector" }
    5.  
    6.             ZWrite On
    7.             ZTest Less
    8.  
    9.             CGPROGRAM
    10.  
    11.             #pragma target 5.0
    12.             #pragma vertex vert
    13.             #pragma geometry geo
    14.             #pragma fragment frag
    15.             #define SHADOW_COLLECTOR_PASS
    16.             #pragma fragmentoption ARB_precision_hint_fastest
    17.             #pragma multi_compile_shadowcollector
    18.          
    19.             #include "UnityCG.cginc"
    20.          
    21.  
    22.             struct appdata {
    23.  
    24.                 float4 vertex : POSITION;
    25.             };
    26.  
    27.             struct v2f {
    28.                 V2F_SHADOW_COLLECTOR;
    29.             };
    30.  
    31.             appdata vert (appdata v){
    32.             return v;
    33.             }
    34.          
    35.             [maxvertexcount(4)]  
    36.             void geo(point appdata vert[1], inout TriangleStream<v2f> ts)
    37.             {
    38.  
    39.              
    40.                 float h = .5f;
    41.                 float4 p[4];
    42.              
    43.                 //offsets slightly along the normal, due to 'shadow acne'
    44.                 p[0] = float4(-h, 0.01f, -h, 0.0f);
    45.                 p[1] = float4(-h, 0.01f,  h, 0.0f);
    46.                 p[2] = float4( h, 0.01f, -h, 0.0f);
    47.                 p[3] = float4( h, 0.01f,  h, 0.0f);
    48.              
    49.                 for (int i = 0; i < 4; ++i)
    50.                 {
    51.                     v2f o;
    52.                  
    53.                     //unity's TRANSFER_SHADOW_COLLECTOR macro insists on using 'v', not 'v[0]', as the vertex position
    54.                     appdata v;
    55.                     v.vertex = vert[0].vertex + p[i];
    56.  
    57.                     TRANSFER_SHADOW_COLLECTOR(o)
    58.                     ts.Append(o);
    59.                  
    60.                 }
    61.             }
    62.  
    63.             half4 frag (v2f i) : COLOR
    64.             {
    65.          
    66.                 SHADOW_COLLECTOR_FRAGMENT(i)
    67.             }
    68.  
    69.         ENDCG
    70.  
    71.         }//end pass