Search Unity

Geometry Shader Shadows

Discussion in 'Shaders' started by Torigas, Feb 24, 2014.

  1. Torigas

    Torigas

    Joined:
    Jan 1, 2014
    Posts:
    63
    Hi!

    I'm drawing point clouds as a huge bunch of cubes using a fancy geometry shader and kind of can't figure out how to properly use the generated cubes as shadow casters.

    I already found out I have to define shadow passes myself but I'm not sure whether I have to do all the geometry generation again in the following passes or whether I can somehow transfer the whole ordeal.

    I'd really appreciate any hints as I'm really no expert at shader programming and don't quite get what the shadow passes do (couldn't find proper documentation neither).

    As a minimal example which shows billboards at the vertex positions but draws the shadow of the underlying mesh.
    Billboard shader from:
    http://forum.unity3d.com/threads/169415-Billboard-Geometry-Shader

    Shadow code from:
    http://forum.unity3d.com/threads/21...on-shader-in-a-Surface-shader-Shadow-problems


    Code (csharp):
    1. Shader "Custom/GS Billboard"
    2. {
    3.     Properties
    4.     {
    5.         _SpriteTex ("Base (RGB)", 2D) = "white" {
    6.             }
    7.         _Size ("Size", Range(0, 3)) = 0.5
    8.     }
    9.  
    10.     SubShader
    11.     {
    12.         Pass
    13.         {
    14.             Tags {
    15.                 "RenderType"="Opaque" }
    16.             LOD 200
    17.        
    18.             CGPROGRAM
    19.                 #pragma target 5.0
    20.                 #pragma vertex VS_Main
    21.                 #pragma fragment FS_Main
    22.                 #pragma geometry GS_Main
    23.                 #include "UnityCG.cginc"
    24.  
    25.                 // **************************************************************
    26.                 // Data structures                                              *
    27.                 // **************************************************************
    28.                 struct GS_INPUT
    29.                 {
    30.                 float4  pos     : POSITION;
    31.                 float3  normal  : NORMAL;
    32.                 float2  tex0    : TEXCOORD0;
    33.             }
    34. ;
    35.             struct FS_INPUT
    36.                 {
    37.                 float4  pos     : POSITION;
    38.                 float2  tex0    : TEXCOORD0;
    39.             }
    40. ;
    41.             // **************************************************************
    42.                 // Vars                                                         *
    43.                 // **************************************************************
    44.  
    45.                 float _Size;
    46.             float4x4 _VP;
    47.             Texture2D _SpriteTex;
    48.             SamplerState sampler_SpriteTex;
    49.             // **************************************************************
    50.                 // Shader Programs                                              *
    51.                 // **************************************************************
    52.  
    53.                 // Vertex Shader ------------------------------------------------
    54.                 GS_INPUT VS_Main(appdata_base v)
    55.                 {
    56.                 GS_INPUT output = (GS_INPUT)0;
    57.                 output.pos =  mul(_Object2World, v.vertex);
    58.                 output.normal = v.normal;
    59.                 output.tex0 = float2(0, 0);
    60.                 return output;
    61.             }
    62.  
    63.  
    64.  
    65.  
    66.                 // Geometry Shader -----------------------------------------------------
    67.                 [maxvertexcount(4)]
    68.                 void GS_Main(point GS_INPUT p[1], inout TriangleStream<FS_INPUT> triStream)
    69.                 {
    70.                 //get up vector
    71.                     float3 up = float3(0, 1, 0);
    72.                 //get look vector
    73.                     float3 look = _WorldSpaceCameraPos - p[0].pos;
    74.                 look.y = 0;
    75.                 look = normalize(look);
    76.                 //get right vector
    77.                     float3 right = cross(up, look);
    78.                 //half the size please..
    79.                     float halfS = 0.5f * _Size;
    80.                 //offsets
    81.                     float4 v[4];
    82.                 v[0] = float4(p[0].pos + halfS * right - halfS * up, 1.0f);
    83.                 v[1] = float4(p[0].pos + halfS * right + halfS * up, 1.0f);
    84.                 v[2] = float4(p[0].pos - halfS * right - halfS * up, 1.0f);
    85.                 v[3] = float4(p[0].pos - halfS * right + halfS * up, 1.0f);
    86.                 float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
    87.                 FS_INPUT pIn;
    88.                 pIn.pos = mul(vp, v[0]);
    89.                 pIn.tex0 = float2(1.0f, 0.0f);
    90.                 triStream.Append(pIn);
    91.                 pIn.pos =  mul(vp, v[1]);
    92.                 pIn.tex0 = float2(1.0f, 1.0f);
    93.                 triStream.Append(pIn);
    94.                 pIn.pos =  mul(vp, v[2]);
    95.                 pIn.tex0 = float2(0.0f, 0.0f);
    96.                 triStream.Append(pIn);
    97.                 pIn.pos =  mul(vp, v[3]);
    98.                 pIn.tex0 = float2(0.0f, 1.0f);
    99.                 triStream.Append(pIn);
    100.             }
    101.  
    102.  
    103.  
    104.  
    105.                 // Fragment Shader -----------------------------------------------
    106.                 float4 FS_Main(FS_INPUT input) : COLOR
    107.                 {
    108.                 return _SpriteTex.Sample(sampler_SpriteTex, input.tex0);
    109.             }
    110.  
    111.  
    112.             ENDCG
    113.         }
    114.         // Pass to render object as a shadow caster
    115.  
    116.         Pass {
    117.             Name "ShadowCaster"
    118.             Tags {"LightMode" = "ShadowCaster" }  
    119.             Fog {Mode Off}
    120.  
    121.             ZWrite On ZTest LEqual Cull Off
    122.  
    123.             Offset 1, 1
    124.  
    125.             CGPROGRAM
    126.             #pragma target 5.0
    127.             #pragma vertex vert
    128.             #pragma fragment frag
    129.             #pragma multi_compile_shadowcaster
    130.             #pragma fragmentoption ARB_precision_hint_fastest
    131.             #include "UnityCG.cginc"
    132.             struct v2f {
    133.                 V2F_SHADOW_CASTER;
    134.             };
    135.  
    136.             v2f vert( appdata_base v )
    137.             {
    138.                 v2f o;
    139.                 TRANSFER_SHADOW_CASTER(o)
    140.                 return o;
    141.             }
    142.  
    143.             float4 frag( v2f i ) : COLOR
    144.             {
    145.                 SHADOW_CASTER_FRAGMENT(i)
    146.             }
    147.  
    148.         ENDCG
    149.         }
    150.         // Pass to render object as a shadow collector
    151.         Pass {
    152.             Name "ShadowCollector"
    153.             Tags {"LightMode" = "ShadowCollector" }
    154.             Fog {Mode Off}
    155.             ZWrite On ZTest LEqual
    156.  
    157.             CGPROGRAM
    158.             #pragma target 5.0
    159.             #pragma vertex vert
    160.             #pragma fragment frag
    161.             #pragma fragmentoption ARB_precision_hint_fastest
    162.             #pragma multi_compile_shadowcollector
    163.             #define SHADOW_COLLECTOR_PASS
    164.             #include "UnityCG.cginc"
    165.  
    166.             struct appdata {
    167.                 float4 vertex : POSITION;
    168.             };
    169.             struct v2f {
    170.                 V2F_SHADOW_COLLECTOR;
    171.             };
    172.             v2f vert (appdata v){
    173.                 v2f o;
    174.                 TRANSFER_SHADOW_COLLECTOR(o)
    175.                 return o;
    176.             }
    177.             fixed4 frag (v2f i) : COLOR
    178.             {
    179.                 SHADOW_COLLECTOR_FRAGMENT(i)
    180.                 }
    181.         ENDCG
    182.         }//end pass
    183.     }//end subshader
    184.     //Fallback "Diffuse"
    185. }//end shader
    186.  
     
  2. Torigas

    Torigas

    Joined:
    Jan 1, 2014
    Posts:
    63
    Okay I kinda got shadows - Kinda irks me I need to do the whole geometry shader business again.
    Surely, there's a better way?

    Code (csharp):
    1. Shader "Custom/billboard2"
    2. {
    3.     Properties
    4.     {
    5.         _SpriteTex ("Base (RGB)", 2D) = "white" {
    6.             }
    7.         _Size ("Size", Range(0, 3)) = 0.5
    8.     }
    9.  
    10.     SubShader
    11.     {
    12.         Pass
    13.         {
    14.             Tags {
    15.                 "RenderType"="Opaque" }
    16.             LOD 200
    17.        
    18.             CGPROGRAM
    19.                 #pragma target 5.0
    20.                 #pragma vertex VS_Main
    21.                 #pragma fragment FS_Main
    22.                 #pragma geometry GS_Main
    23.                 #include "UnityCG.cginc"
    24.  
    25.             // **************************************************************
    26.             // Data structures                                              *
    27.             // **************************************************************
    28.             struct GS_INPUT
    29.             {
    30.                 float4  pos     : POSITION;
    31.                 float3  normal  : NORMAL;
    32.                 float2  tex0    : TEXCOORD0;
    33.             }
    34. ;
    35.             struct FS_INPUT
    36.                 {
    37.                 float4  pos     : POSITION;
    38.                 float2  tex0    : TEXCOORD0;
    39.             }
    40. ;
    41.             // **************************************************************
    42.             // Vars                                                         *
    43.             // **************************************************************
    44.  
    45.                 float _Size;
    46.             float4x4 _VP;
    47.             Texture2D _SpriteTex;
    48.             SamplerState sampler_SpriteTex;
    49.             // **************************************************************
    50.             // Shader Programs                                              *
    51.             // **************************************************************
    52.  
    53.             // Vertex Shader ------------------------------------------------
    54.             GS_INPUT VS_Main(appdata_base v)
    55.             {
    56.                 GS_INPUT output = (GS_INPUT)0;
    57.                 output.pos =  mul(_Object2World, v.vertex);
    58.                 output.normal = v.normal;
    59.                 output.tex0 = float2(0, 0);
    60.                 return output;
    61.             }
    62.             // Geometry Shader -----------------------------------------------------
    63.             [maxvertexcount(4)]
    64.             void GS_Main(point GS_INPUT p[1], inout TriangleStream<FS_INPUT> triStream)
    65.             {
    66.             //get up vector
    67.                 float3 up = UNITY_MATRIX_IT_MV[1].xyz;//float3(0, 1, 0);
    68.             //get look vector
    69.                 float3 look = _WorldSpaceCameraPos - p[0].pos;
    70.                 //look.y = 0;
    71.                 look = normalize(look);
    72.             //get right vector
    73.                 float3 right = cross(up, look);
    74.             //half the size please..
    75.                 float halfS = 0.5f * _Size;
    76.             //offsets
    77.                 float4 v[4];
    78.                 v[0] = float4(p[0].pos + halfS * right - halfS * up, 1.0f);
    79.                 v[1] = float4(p[0].pos + halfS * right + halfS * up, 1.0f);
    80.                 v[2] = float4(p[0].pos - halfS * right - halfS * up, 1.0f);
    81.                 v[3] = float4(p[0].pos - halfS * right + halfS * up, 1.0f);
    82.                 float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
    83.                 FS_INPUT pIn;
    84.                 pIn.pos = mul(vp, v[0]);
    85.                 pIn.tex0 = float2(1.0f, 0.0f);
    86.                 triStream.Append(pIn);
    87.                 pIn.pos =  mul(vp, v[1]);
    88.                 pIn.tex0 = float2(1.0f, 1.0f);
    89.                 triStream.Append(pIn);
    90.                 pIn.pos =  mul(vp, v[2]);
    91.                 pIn.tex0 = float2(0.0f, 0.0f);
    92.                 triStream.Append(pIn);
    93.                 pIn.pos =  mul(vp, v[3]);
    94.                 pIn.tex0 = float2(0.0f, 1.0f);
    95.                 triStream.Append(pIn);
    96.             }
    97.  
    98.  
    99.  
    100.  
    101.                 // Fragment Shader -----------------------------------------------
    102.                 float4 FS_Main(FS_INPUT input) : COLOR
    103.                 {
    104.                 return _SpriteTex.Sample(sampler_SpriteTex, input.tex0);
    105.             }
    106.  
    107.  
    108.             ENDCG
    109.         }
    110.         // Pass to render object as a shadow caster
    111.  
    112.         Pass {
    113.             Name "ShadowCaster"
    114.             Tags {"LightMode" = "ShadowCaster" }  
    115.             Fog {Mode Off}
    116.  
    117.             ZWrite On ZTest LEqual Cull Off
    118.  
    119.             Offset 1, 1
    120.  
    121.             CGPROGRAM
    122.             #pragma target 5.0
    123.             #pragma vertex SHADOW_VS_Main
    124.             #pragma fragment SHADOW_FS_Main
    125.             #pragma geometry SHADOW_GS_Main
    126.             #pragma multi_compile_shadowcaster
    127.             #pragma fragmentoption ARB_precision_hint_fastest
    128.             #include "UnityCG.cginc"
    129.  
    130.  
    131.             // **************************************************************
    132.             // Data structures                                              *
    133.             // **************************************************************
    134.             struct SHADOW_GS_INPUT
    135.             {
    136.                 V2F_SHADOW_CASTER;
    137.             };
    138.             struct SHADOW_FS_INPUT
    139.             {
    140.                 V2F_SHADOW_CASTER;
    141.             };
    142.             // **************************************************************
    143.             // Vars                                                         *
    144.             // **************************************************************
    145.  
    146.             float _Size;
    147.             float4x4 _VP;
    148.             // **************************************************************
    149.             // Shader Programs                                              *
    150.             // **************************************************************
    151.  
    152.             // Vertex Shader ------------------------------------------------
    153.             SHADOW_GS_INPUT SHADOW_VS_Main(appdata_base v)
    154.             {
    155.                 SHADOW_GS_INPUT output = (SHADOW_GS_INPUT)0;
    156.                 output.pos =  mul(_Object2World, v.vertex);
    157.                 //TRANSFER_SHADOW_CASTER(output)
    158.                 return output;
    159.             }
    160.             // Geometry Shader -----------------------------------------------------
    161.             [maxvertexcount(4)]
    162.             void SHADOW_GS_Main(point SHADOW_GS_INPUT p[1], inout TriangleStream<SHADOW_FS_INPUT> triStream)
    163.             {
    164.                 //get up vector
    165.                 float3 up = UNITY_MATRIX_IT_MV[1].xyz;
    166.                 //get look vector
    167.                 float3 look = _WorldSpaceCameraPos - p[0].pos;
    168.                 //look.y = 0;
    169.                 look = normalize(look);
    170.                 //get right vector
    171.                 float3 right = cross(up, look);
    172.                 //half the size please..
    173.                 float halfS = 0.5f * _Size;
    174.                 //offsets
    175.                 float4 v[4];
    176.                 v[0] = float4(p[0].pos + halfS * right - halfS * up, 1.0f);
    177.                 v[1] = float4(p[0].pos + halfS * right + halfS * up, 1.0f);
    178.                 v[2] = float4(p[0].pos - halfS * right - halfS * up, 1.0f);
    179.                 v[3] = float4(p[0].pos - halfS * right + halfS * up, 1.0f);
    180.                 float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
    181.  
    182.                 SHADOW_FS_INPUT pIn=p[0];
    183.                 //TRANSFER_SHADOW_CASTER(pIn)
    184.                 pIn.pos = mul(vp, v[0]);
    185.                 triStream.Append(pIn);
    186.                 //TRANSFER_SHADOW_CASTER(pIn)
    187.                 pIn.pos =  mul(vp, v[1]);
    188.                 triStream.Append(pIn);
    189.                 //TRANSFER_SHADOW_CASTER(pIn)
    190.                 pIn.pos =  mul(vp, v[2]);
    191.                 triStream.Append(pIn);
    192.                 //TRANSFER_SHADOW_CASTER(pIn)
    193.                 pIn.pos =  mul(vp, v[3]);
    194.                 triStream.Append(pIn);
    195.                 //TRANSFER_SHADOW_CASTER(pIn)
    196.             }
    197.             // Fragment Shader -----------------------------------------------
    198.             float4 SHADOW_FS_Main(SHADOW_FS_INPUT input) : COLOR
    199.             {
    200.                 SHADOW_CASTER_FRAGMENT(input)
    201.                 //return _SpriteTex.Sample(sampler_SpriteTex, input.tex0);
    202.             }
    203.         ENDCG
    204.         }
    205.         // Pass to render object as a shadow collector
    206.         Pass {
    207.             Name "ShadowCollector"
    208.             Tags {"LightMode" = "ShadowCollector" }
    209.             Fog {Mode Off}
    210.             ZWrite On ZTest LEqual
    211.  
    212.             CGPROGRAM
    213.             #pragma target 5.0
    214.             #pragma vertex vert
    215.             #pragma fragment frag
    216.             #pragma fragmentoption ARB_precision_hint_fastest
    217.             #pragma multi_compile_shadowcollector
    218.             #define SHADOW_COLLECTOR_PASS
    219.             #include "UnityCG.cginc"
    220.  
    221.             struct appdata {
    222.                 float4 vertex : POSITION;
    223.             };
    224.             struct v2f {
    225.                 V2F_SHADOW_COLLECTOR;
    226.             };
    227.             v2f vert (appdata v){
    228.                 v2f o;
    229.                 TRANSFER_SHADOW_COLLECTOR(o)
    230.                 return o;
    231.             }
    232.             fixed4 frag (v2f i) : COLOR
    233.             {
    234.                 SHADOW_COLLECTOR_FRAGMENT(i)
    235.             }
    236.         ENDCG
    237.         }//end pass
    238.     }//end subshader
    239.     //Fallback "Diffuse"
    240. }//end shader
    241.  
     
  3. Torigas

    Torigas

    Joined:
    Jan 1, 2014
    Posts:
    63
    Unfortunately, I can't quite seem to get my objects to throw shadows when I render them procedurally in the OnRenderObject Method.
    Does anyone have any clue how to get shadows with procedural objects drawn in "OnRenderObject()"?
    Would be really appreciated!

    Code (csharp):
    1.     void OnRenderObject()
    2.     {
    3.         //Vector3 campos = Camera.current.transform.position;
    4.         //renderer.material.SetVector("_WorldSpaceCameraPos", new Vector4(campos.x, campos.y, campos.z, 0));
    5.         renderer.material.SetPass(0);
    6.         Graphics.DrawProcedural(MeshTopology.Points, pointCount, 1);
    7.         if (renderer.material.SetPass(1)) //second pass should draw shadows.
    8.         {
    9.             //Debug.Log("Drawing second pass");
    10.             Graphics.DrawProcedural(MeshTopology.Triangles, pointCount, 1);
    11.            
    12.         }
    13.     }
    Basically when I use this following shader on a normal mesh I get a cube per vertex and each throws a shadow - I guess that means the shader is correct:

    Code (csharp):
    1. Shader "DX11/VertexCubeShader" {
    2.     Properties
    3.     {
    4.         _Size ("Size", Range(0.01, 1.0)) = 1.0
    5.     }
    6. SubShader {
    7.  
    8. Pass
    9. {
    10. Tags { "RenderType"="Opaque" }
    11. LOD 200
    12.  
    13. CGPROGRAM
    14. #pragma target 5.0
    15. #pragma vertex vert
    16. #pragma geometry geom
    17. #pragma fragment frag
    18. #include "UnityCG.cginc"
    19.  
    20. uniform float _Size;
    21.  
    22.  
    23. // **************************************************************
    24. // Data structures                                              *
    25. // **************************************************************
    26. struct gs_input
    27. {
    28.     float4 position : SV_POSITION;
    29.     float4 col : COLOR;
    30. };
    31. struct ps_input {
    32.     float4 position : SV_POSITION;
    33.     float4 col : COLOR;
    34. };
    35.  
    36. // **************************************************************
    37. // Vars                                                         *
    38. // **************************************************************
    39. gs_input vert (appdata_base v)
    40. {
    41.     gs_input output = (gs_input)0;
    42.     output.position =  mul(_Object2World, v.vertex);
    43.     return output;
    44. }
    45.  
    46. // Geometry Shader -----------------------------------------------------
    47. [maxvertexcount(24)]
    48. void geom (point gs_input inp[1], inout TriangleStream<ps_input> triStream)
    49. {
    50.     float halfS = 0.5f * _Size;
    51.            
    52.     //offsets
    53.     float4 v[8];
    54.     v[0] = float4(inp[0].position.x + halfS, inp[0].position.y + halfS, inp[0].position.z + halfS,1.0f);//float4(1,2,3,4);//
    55.     v[1] = float4(inp[0].position.x + halfS, inp[0].position.y - halfS, inp[0].position.z + halfS,1.0f);//float4(1,2,3,4);//
    56.     v[2] = float4(inp[0].position.x - halfS, inp[0].position.y + halfS, inp[0].position.z + halfS,1.0f);//float4(1,2,3,4);//
    57.     v[3] = float4(inp[0].position.x - halfS, inp[0].position.y - halfS, inp[0].position.z + halfS,1.0f);//float4(1,2,3,4);//
    58.     v[4] = float4(inp[0].position.x + halfS, inp[0].position.y + halfS, inp[0].position.z - halfS,1.0f);//float4(1,2,3,4);//
    59.     v[5] = float4(inp[0].position.x + halfS, inp[0].position.y - halfS, inp[0].position.z - halfS,1.0f);//float4(1,2,3,4);//
    60.     v[6] = float4(inp[0].position.x - halfS, inp[0].position.y + halfS, inp[0].position.z - halfS,1.0f);//float4(1,2,3,4);//
    61.     v[7] = float4(inp[0].position.x - halfS, inp[0].position.y - halfS, inp[0].position.z - halfS,1.0f);//float4(1,2,3,4);//
    62.  
    63.     float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
    64.     ps_input pIn;
    65.     //back
    66.     pIn.position = mul(vp, v[0]);
    67.     pIn.col = inp[0].col;
    68.     triStream.Append(pIn);
    69.  
    70.     pIn.position =  mul(vp, v[2]);
    71.     pIn.col = inp[0].col;
    72.     triStream.Append(pIn);
    73.  
    74.     pIn.position =  mul(vp, v[1]);
    75.     pIn.col = inp[0].col;
    76.     triStream.Append(pIn);
    77.  
    78.     pIn.position =  mul(vp, v[3]);
    79.     pIn.col = inp[0].col;
    80.     triStream.Append(pIn);
    81.  
    82.     triStream.RestartStrip();
    83.     //front
    84.     pIn.position = mul(vp, v[4]);
    85.     pIn.col = inp[0].col;
    86.     triStream.Append(pIn);
    87.  
    88.     pIn.position =  mul(vp, v[5]);
    89.     pIn.col = inp[0].col;
    90.     triStream.Append(pIn);
    91.  
    92.     pIn.position =  mul(vp, v[6]);
    93.     pIn.col = inp[0].col;
    94.     triStream.Append(pIn);
    95.  
    96.     pIn.position =  mul(vp, v[7]);
    97.     pIn.col = inp[0].col;
    98.     triStream.Append(pIn);
    99.    
    100.     triStream.RestartStrip();
    101.  
    102.         //right
    103.     pIn.position = mul(vp, v[0]);
    104.     pIn.col = inp[0].col;
    105.     triStream.Append(pIn);
    106.  
    107.     pIn.position =  mul(vp, v[1]);
    108.     pIn.col = inp[0].col;
    109.     triStream.Append(pIn);
    110.  
    111.     pIn.position =  mul(vp, v[4]);
    112.     pIn.col = inp[0].col;
    113.     triStream.Append(pIn);
    114.  
    115.     pIn.position =  mul(vp, v[5]);
    116.     pIn.col = inp[0].col;
    117.     triStream.Append(pIn);
    118.    
    119.     triStream.RestartStrip();
    120.             //left
    121.     pIn.position = mul(vp, v[6]);
    122.     pIn.col = inp[0].col;
    123.     triStream.Append(pIn);
    124.  
    125.     pIn.position =  mul(vp, v[7]);
    126.     pIn.col = inp[0].col;
    127.     triStream.Append(pIn);
    128.  
    129.     pIn.position =  mul(vp, v[2]);
    130.     pIn.col = inp[0].col;
    131.     triStream.Append(pIn);
    132.  
    133.     pIn.position =  mul(vp, v[3]);
    134.     pIn.col = inp[0].col;
    135.     triStream.Append(pIn);
    136.    
    137.     triStream.RestartStrip();
    138.  
    139.             //top
    140.     pIn.position = mul(vp, v[0]);
    141.     pIn.col = inp[0].col;
    142.     triStream.Append(pIn);
    143.  
    144.     pIn.position =  mul(vp, v[4]);
    145.     pIn.col = inp[0].col;
    146.     triStream.Append(pIn);
    147.  
    148.     pIn.position =  mul(vp, v[2]);
    149.     pIn.col = inp[0].col;
    150.     triStream.Append(pIn);
    151.  
    152.     pIn.position =  mul(vp, v[6]);
    153.     pIn.col = inp[0].col;
    154.     triStream.Append(pIn);
    155.    
    156.     triStream.RestartStrip();
    157.             //bottom
    158.     pIn.position = mul(vp, v[5]);
    159.     pIn.col = inp[0].col;
    160.     triStream.Append(pIn);
    161.  
    162.     pIn.position =  mul(vp, v[1]);
    163.     pIn.col = inp[0].col;
    164.     triStream.Append(pIn);
    165.  
    166.     pIn.position =  mul(vp, v[7]);
    167.     pIn.col = inp[0].col;
    168.     triStream.Append(pIn);
    169.  
    170.     pIn.position =  mul(vp, v[3]);
    171.     pIn.col = inp[0].col;
    172.     triStream.Append(pIn);
    173.    
    174.     triStream.RestartStrip();
    175.    
    176. }
    177.  
    178. float4 frag (ps_input i) : COLOR
    179. {
    180.     return i.col;
    181. }
    182.  
    183. ENDCG
    184. }//end pass 1
    185.  
    186. // Pass to render object as a shadow caster
    187.         Pass {
    188.             Name "ShadowCaster"
    189.             Tags {"LightMode" = "ShadowCaster" }  
    190.             Fog {Mode Off}
    191.  
    192.             ZWrite On ZTest LEqual Cull Off
    193.  
    194.             Offset 1, 1
    195.  
    196.             CGPROGRAM
    197.             #pragma target 5.0
    198.             #pragma vertex SHADOW_VS_Main
    199.             #pragma fragment SHADOW_FS_Main
    200.             #pragma geometry SHADOW_GS_Main
    201.             #pragma multi_compile_shadowcaster
    202.             #pragma fragmentoption ARB_precision_hint_fastest
    203.             #include "UnityCG.cginc"
    204.  
    205.  
    206.             // **************************************************************
    207.             // Data structures                                              *
    208.             // **************************************************************
    209.             struct SHADOW_GS_INPUT
    210.             {
    211.                 V2F_SHADOW_CASTER;
    212.             };
    213.             struct SHADOW_FS_INPUT
    214.             {
    215.                 V2F_SHADOW_CASTER;
    216.             };
    217.             // **************************************************************
    218.             // Vars                                                         *
    219.             // **************************************************************
    220.  
    221.             float _Size;
    222.             float4x4 _VP;
    223.  
    224.             // **************************************************************
    225.             // Shader Programs                                              *
    226.             // **************************************************************
    227.  
    228.             // Vertex Shader ------------------------------------------------
    229.             SHADOW_GS_INPUT SHADOW_VS_Main(appdata_base v)
    230.             {
    231.                 SHADOW_GS_INPUT output = (SHADOW_GS_INPUT)0;
    232.                 output.pos =  mul(_Object2World, v.vertex);
    233.                 return output;
    234.             }
    235.             // Geometry Shader -----------------------------------------------------
    236.             [maxvertexcount(24)]
    237.             void SHADOW_GS_Main(point SHADOW_GS_INPUT p[1], inout TriangleStream<SHADOW_FS_INPUT> triStream)
    238.             {
    239.                 float halfS = 0.5f * _Size;
    240.            
    241.                 //offsets
    242.                 float4 v[8];
    243.                 v[0] = float4(p[0].pos.x + halfS, p[0].pos.y + halfS, p[0].pos.z + halfS , 1.0f);//float4(1,2,3,4);//
    244.                 v[1] = float4(p[0].pos.x + halfS, p[0].pos.y - halfS, p[0].pos.z + halfS , 1.0f);//float4(1,2,3,4);//
    245.                 v[2] = float4(p[0].pos.x - halfS, p[0].pos.y + halfS, p[0].pos.z + halfS , 1.0f);//float4(1,2,3,4);//
    246.                 v[3] = float4(p[0].pos.x - halfS, p[0].pos.y - halfS, p[0].pos.z + halfS , 1.0f);//float4(1,2,3,4);//
    247.                 v[4] = float4(p[0].pos.x + halfS, p[0].pos.y + halfS, p[0].pos.z - halfS , 1.0f);//float4(1,2,3,4);//
    248.                 v[5] = float4(p[0].pos.x + halfS, p[0].pos.y - halfS, p[0].pos.z - halfS , 1.0f);//float4(1,2,3,4);//
    249.                 v[6] = float4(p[0].pos.x - halfS, p[0].pos.y + halfS, p[0].pos.z - halfS , 1.0f);//float4(1,2,3,4);//
    250.                 v[7] = float4(p[0].pos.x - halfS, p[0].pos.y - halfS, p[0].pos.z - halfS , 1.0f);//float4(1,2,3,4);//
    251.  
    252.                 float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
    253.                
    254.                 SHADOW_FS_INPUT pIn=p[0];
    255.                 //back
    256.                 pIn.pos = mul(vp, v[0]);
    257.                 triStream.Append(pIn);
    258.  
    259.                 pIn.pos = mul(vp, v[2]);
    260.                 triStream.Append(pIn);
    261.  
    262.                 pIn.pos = mul(vp, v[1]);
    263.                 triStream.Append(pIn);
    264.  
    265.                 pIn.pos = mul(vp, v[3]);
    266.                 triStream.Append(pIn);
    267.  
    268.                 triStream.RestartStrip();
    269.                 //front
    270.                 pIn.pos = mul(vp, v[4]);
    271.                 triStream.Append(pIn);
    272.  
    273.                 pIn.pos =  mul(vp, v[5]);
    274.                 triStream.Append(pIn);
    275.  
    276.                 pIn.pos =  mul(vp, v[6]);
    277.                 triStream.Append(pIn);
    278.  
    279.                 pIn.pos =  mul(vp, v[7]);
    280.                 triStream.Append(pIn);
    281.    
    282.                 triStream.RestartStrip();
    283.  
    284.                     //right
    285.                 pIn.pos = mul(vp, v[0]);
    286.                 triStream.Append(pIn);
    287.  
    288.                 pIn.pos =  mul(vp, v[1]);
    289.                 triStream.Append(pIn);
    290.  
    291.                 pIn.pos =  mul(vp, v[4]);
    292.                 triStream.Append(pIn);
    293.  
    294.                 pIn.pos =  mul(vp, v[5]);
    295.                 triStream.Append(pIn);
    296.    
    297.                 triStream.RestartStrip();
    298.                         //left
    299.                 pIn.pos = mul(vp, v[6]);
    300.                 triStream.Append(pIn);
    301.  
    302.                 pIn.pos =  mul(vp, v[7]);
    303.                 triStream.Append(pIn);
    304.  
    305.                 pIn.pos =  mul(vp, v[2]);
    306.                 triStream.Append(pIn);
    307.  
    308.                 pIn.pos =  mul(vp, v[3]);
    309.                 triStream.Append(pIn);
    310.    
    311.                 triStream.RestartStrip();
    312.  
    313.                         //top
    314.                 pIn.pos = mul(vp, v[0]);
    315.                 triStream.Append(pIn);
    316.  
    317.                 pIn.pos =  mul(vp, v[4]);
    318.                 triStream.Append(pIn);
    319.  
    320.                 pIn.pos =  mul(vp, v[2]);
    321.                 triStream.Append(pIn);
    322.  
    323.                 pIn.pos =  mul(vp, v[6]);
    324.                 triStream.Append(pIn);
    325.    
    326.                 triStream.RestartStrip();
    327.                         //bottom
    328.                 pIn.pos = mul(vp, v[5]);
    329.                 triStream.Append(pIn);
    330.  
    331.                 pIn.pos =  mul(vp, v[1]);
    332.                 triStream.Append(pIn);
    333.  
    334.                 pIn.pos =  mul(vp, v[7]);
    335.                 triStream.Append(pIn);
    336.  
    337.                 pIn.pos =  mul(vp, v[3]);
    338.                 triStream.Append(pIn);
    339.    
    340.                 triStream.RestartStrip();
    341.             }
    342.             // Fragment Shader -----------------------------------------------
    343.             float4 SHADOW_FS_Main(SHADOW_FS_INPUT input) : COLOR
    344.             {
    345.                 SHADOW_CASTER_FRAGMENT(input)
    346.             }
    347.         ENDCG
    348.         }
    349. }
    350.  
    351. Fallback Off
    352. }
    353.  
    The same version drawn in the OnRenderObject function doesn't work. In fact, it simply draws black cubes ontop of the original ones.

    I assume it's due to the render queue being screwed when the "OnRenderObject" function is called compared to normal object rendering.