Geometry Shader Shadows

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/216276-Modifying-vertex-position-shader-in-a-Surface-shader-Shadow-problems

Shader "Custom/GS Billboard" 
{
    Properties 
	{
        _SpriteTex ("Base (RGB)", 2D) = "white" {
            }
		_Size ("Size", Range(0, 3)) = 0.5
	}

	SubShader 
	{
        Pass
		{
            Tags {
                "RenderType"="Opaque" }
			LOD 200
		
			CGPROGRAM
				#pragma target 5.0
				#pragma vertex VS_Main
				#pragma fragment FS_Main
				#pragma geometry GS_Main
				#include "UnityCG.cginc" 

				// **************************************************************
				// Data structures												*
				// **************************************************************
				struct GS_INPUT
				{
                float4	pos		: POSITION;
                float3	normal	: NORMAL;
                float2  tex0	: TEXCOORD0;
            }
;
            struct FS_INPUT
				{
                float4	pos		: POSITION;
                float2  tex0	: TEXCOORD0;
            }
;
            // **************************************************************
				// Vars															*
				// **************************************************************

				float _Size;
            float4x4 _VP;
            Texture2D _SpriteTex;
            SamplerState sampler_SpriteTex;
            // **************************************************************
				// Shader Programs												*
				// **************************************************************

				// Vertex Shader ------------------------------------------------
				GS_INPUT VS_Main(appdata_base v)
				{
                GS_INPUT output = (GS_INPUT)0;
                output.pos =  mul(_Object2World, v.vertex);
                output.normal = v.normal;
                output.tex0 = float2(0, 0);
                return output;
            }




				// Geometry Shader -----------------------------------------------------
				[maxvertexcount(4)]
				void GS_Main(point GS_INPUT p[1], inout TriangleStream<FS_INPUT> triStream)
				{
                //get up vector
					float3 up = float3(0, 1, 0);
                //get look vector
					float3 look = _WorldSpaceCameraPos - p[0].pos;
                look.y = 0;
                look = normalize(look);
                //get right vector
					float3 right = cross(up, look);
                //half the size please..
					float halfS = 0.5f * _Size;
                //offsets
					float4 v[4];
                v[0] = float4(p[0].pos + halfS * right - halfS * up, 1.0f);
                v[1] = float4(p[0].pos + halfS * right + halfS * up, 1.0f);
                v[2] = float4(p[0].pos - halfS * right - halfS * up, 1.0f);
                v[3] = float4(p[0].pos - halfS * right + halfS * up, 1.0f);
                float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
                FS_INPUT pIn;
                pIn.pos = mul(vp, v[0]);
                pIn.tex0 = float2(1.0f, 0.0f);
                triStream.Append(pIn);
                pIn.pos =  mul(vp, v[1]);
                pIn.tex0 = float2(1.0f, 1.0f);
                triStream.Append(pIn);
                pIn.pos =  mul(vp, v[2]);
                pIn.tex0 = float2(0.0f, 0.0f);
                triStream.Append(pIn);
                pIn.pos =  mul(vp, v[3]);
                pIn.tex0 = float2(0.0f, 1.0f);
                triStream.Append(pIn);
            }




				// Fragment Shader -----------------------------------------------
				float4 FS_Main(FS_INPUT input) : COLOR
				{
                return _SpriteTex.Sample(sampler_SpriteTex, input.tex0);
            }


			ENDCG
		}
		// Pass to render object as a shadow caster

		Pass {
			Name "ShadowCaster"
			Tags {"LightMode" = "ShadowCaster" }  
			Fog {Mode Off}

			ZWrite On ZTest LEqual Cull Off

			Offset 1, 1

			CGPROGRAM
			#pragma target 5.0
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_shadowcaster
			#pragma fragmentoption ARB_precision_hint_fastest
			#include "UnityCG.cginc"
			struct v2f {
				V2F_SHADOW_CASTER;
			};

			v2f vert( appdata_base v )
			{
                v2f o;
                TRANSFER_SHADOW_CASTER(o)
				return o;
            }

			float4 frag( v2f i ) : COLOR
			{
                SHADOW_CASTER_FRAGMENT(i)
			}

		ENDCG
		}
		// Pass to render object as a shadow collector
		Pass {
			Name "ShadowCollector"
			Tags {"LightMode" = "ShadowCollector" } 
			Fog {Mode Off}
			ZWrite On ZTest LEqual

			CGPROGRAM
			#pragma target 5.0
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			#pragma multi_compile_shadowcollector 
			#define SHADOW_COLLECTOR_PASS
			#include "UnityCG.cginc"

			struct appdata {
                float4 vertex : POSITION;
            };
            struct v2f {
                V2F_SHADOW_COLLECTOR;
            };
            v2f vert (appdata v){
                v2f o;
                TRANSFER_SHADOW_COLLECTOR(o)
				return o;
            }
			fixed4 frag (v2f i) : COLOR
			{
                SHADOW_COLLECTOR_FRAGMENT(i)
				}
		ENDCG
		}//end pass
	}//end subshader
	//Fallback "Diffuse"
}//end shader

Okay I kinda got shadows - Kinda irks me I need to do the whole geometry shader business again.
Surely, there’s a better way?

Shader "Custom/billboard2" 
{
    Properties 
	{
        _SpriteTex ("Base (RGB)", 2D) = "white" {
            }
		_Size ("Size", Range(0, 3)) = 0.5
	}

	SubShader 
	{
        Pass
		{
            Tags {
                "RenderType"="Opaque" }
			LOD 200
		
			CGPROGRAM
				#pragma target 5.0
				#pragma vertex VS_Main
				#pragma fragment FS_Main
				#pragma geometry GS_Main
				#include "UnityCG.cginc" 

			// **************************************************************
			// Data structures												*
			// **************************************************************
			struct GS_INPUT
			{
                float4	pos		: POSITION;
                float3	normal	: NORMAL;
                float2  tex0	: TEXCOORD0;
            }
;
            struct FS_INPUT
				{
                float4	pos		: POSITION;
                float2  tex0	: TEXCOORD0;
            }
;
            // **************************************************************
			// Vars															*
			// **************************************************************

				float _Size;
            float4x4 _VP;
            Texture2D _SpriteTex;
            SamplerState sampler_SpriteTex;
            // **************************************************************
			// Shader Programs												*
			// **************************************************************

			// Vertex Shader ------------------------------------------------
			GS_INPUT VS_Main(appdata_base v)
			{
                GS_INPUT output = (GS_INPUT)0;
                output.pos =  mul(_Object2World, v.vertex);
                output.normal = v.normal;
                output.tex0 = float2(0, 0);
                return output;
            }
			// Geometry Shader -----------------------------------------------------
			[maxvertexcount(4)]
			void GS_Main(point GS_INPUT p[1], inout TriangleStream<FS_INPUT> triStream)
			{
            //get up vector
				float3 up = UNITY_MATRIX_IT_MV[1].xyz;//float3(0, 1, 0);
            //get look vector
				float3 look = _WorldSpaceCameraPos - p[0].pos;
                //look.y = 0;
                look = normalize(look);
            //get right vector
				float3 right = cross(up, look);
            //half the size please..
				float halfS = 0.5f * _Size;
            //offsets
				float4 v[4];
                v[0] = float4(p[0].pos + halfS * right - halfS * up, 1.0f);
                v[1] = float4(p[0].pos + halfS * right + halfS * up, 1.0f);
                v[2] = float4(p[0].pos - halfS * right - halfS * up, 1.0f);
                v[3] = float4(p[0].pos - halfS * right + halfS * up, 1.0f);
                float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
                FS_INPUT pIn;
                pIn.pos = mul(vp, v[0]);
                pIn.tex0 = float2(1.0f, 0.0f);
                triStream.Append(pIn);
                pIn.pos =  mul(vp, v[1]);
                pIn.tex0 = float2(1.0f, 1.0f);
                triStream.Append(pIn);
                pIn.pos =  mul(vp, v[2]);
                pIn.tex0 = float2(0.0f, 0.0f);
                triStream.Append(pIn);
                pIn.pos =  mul(vp, v[3]);
                pIn.tex0 = float2(0.0f, 1.0f);
                triStream.Append(pIn);
            }




				// Fragment Shader -----------------------------------------------
				float4 FS_Main(FS_INPUT input) : COLOR
				{
                return _SpriteTex.Sample(sampler_SpriteTex, input.tex0);
            }


			ENDCG
		}
		// Pass to render object as a shadow caster

		Pass {
			Name "ShadowCaster"
			Tags {"LightMode" = "ShadowCaster" }  
			Fog {Mode Off}

			ZWrite On ZTest LEqual Cull Off

			Offset 1, 1

			CGPROGRAM
			#pragma target 5.0
			#pragma vertex SHADOW_VS_Main
			#pragma fragment SHADOW_FS_Main
			#pragma geometry SHADOW_GS_Main
			#pragma multi_compile_shadowcaster
			#pragma fragmentoption ARB_precision_hint_fastest
			#include "UnityCG.cginc"


			// **************************************************************
			// Data structures												*
			// **************************************************************
			struct SHADOW_GS_INPUT
			{
                V2F_SHADOW_CASTER;
            };
            struct SHADOW_FS_INPUT
			{
				V2F_SHADOW_CASTER;
            };
            // **************************************************************
			// Vars															*
			// **************************************************************

			float _Size;
            float4x4 _VP;
            // **************************************************************
			// Shader Programs												*
			// **************************************************************

			// Vertex Shader ------------------------------------------------
			SHADOW_GS_INPUT SHADOW_VS_Main(appdata_base v)
			{
                SHADOW_GS_INPUT output = (SHADOW_GS_INPUT)0;
                output.pos =  mul(_Object2World, v.vertex);
                //TRANSFER_SHADOW_CASTER(output)
                return output;
            }
			// Geometry Shader -----------------------------------------------------
			[maxvertexcount(4)]
			void SHADOW_GS_Main(point SHADOW_GS_INPUT p[1], inout TriangleStream<SHADOW_FS_INPUT> triStream)
			{
                //get up vector
				float3 up = UNITY_MATRIX_IT_MV[1].xyz;
                //get look vector
				float3 look = _WorldSpaceCameraPos - p[0].pos;
                //look.y = 0;
                look = normalize(look);
                //get right vector
				float3 right = cross(up, look);
                //half the size please..
				float halfS = 0.5f * _Size;
                //offsets
				float4 v[4];
                v[0] = float4(p[0].pos + halfS * right - halfS * up, 1.0f);
                v[1] = float4(p[0].pos + halfS * right + halfS * up, 1.0f);
                v[2] = float4(p[0].pos - halfS * right - halfS * up, 1.0f);
                v[3] = float4(p[0].pos - halfS * right + halfS * up, 1.0f);
                float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);

                SHADOW_FS_INPUT pIn=p[0];
				//TRANSFER_SHADOW_CASTER(pIn)
                pIn.pos = mul(vp, v[0]);
                triStream.Append(pIn);
				//TRANSFER_SHADOW_CASTER(pIn)
                pIn.pos =  mul(vp, v[1]);
                triStream.Append(pIn);
				//TRANSFER_SHADOW_CASTER(pIn)
                pIn.pos =  mul(vp, v[2]);
                triStream.Append(pIn);
				//TRANSFER_SHADOW_CASTER(pIn)
                pIn.pos =  mul(vp, v[3]);
                triStream.Append(pIn);
				//TRANSFER_SHADOW_CASTER(pIn)
            }
			// Fragment Shader -----------------------------------------------
			float4 SHADOW_FS_Main(SHADOW_FS_INPUT input) : COLOR
			{
				SHADOW_CASTER_FRAGMENT(input)
                //return _SpriteTex.Sample(sampler_SpriteTex, input.tex0);
            }
		ENDCG
		}
		// Pass to render object as a shadow collector
		Pass {
			Name "ShadowCollector"
			Tags {"LightMode" = "ShadowCollector" } 
			Fog {Mode Off}
			ZWrite On ZTest LEqual

			CGPROGRAM
			#pragma target 5.0
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			#pragma multi_compile_shadowcollector 
			#define SHADOW_COLLECTOR_PASS
			#include "UnityCG.cginc"

			struct appdata {
                float4 vertex : POSITION;
            };
            struct v2f {
                V2F_SHADOW_COLLECTOR;
            };
            v2f vert (appdata v){
                v2f o;
                TRANSFER_SHADOW_COLLECTOR(o)
				return o;
            }
			fixed4 frag (v2f i) : COLOR
			{
				SHADOW_COLLECTOR_FRAGMENT(i)
			}
		ENDCG
		}//end pass
	}//end subshader
	//Fallback "Diffuse"
}//end shader

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!

    void OnRenderObject()
    {
        //Vector3 campos = Camera.current.transform.position;
        //renderer.material.SetVector("_WorldSpaceCameraPos", new Vector4(campos.x, campos.y, campos.z, 0));
        renderer.material.SetPass(0);
        Graphics.DrawProcedural(MeshTopology.Points, pointCount, 1);
        if (renderer.material.SetPass(1)) //second pass should draw shadows.
        {
            //Debug.Log("Drawing second pass");
            Graphics.DrawProcedural(MeshTopology.Triangles, pointCount, 1);
            
        }
    }

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:

Shader "DX11/VertexCubeShader" {
	Properties 
	{
		_Size ("Size", Range(0.01, 1.0)) = 1.0
	}
SubShader {

Pass 
{
Tags { "RenderType"="Opaque" }
LOD 200

CGPROGRAM
#pragma target 5.0
#pragma vertex vert
#pragma geometry geom
#pragma fragment frag
#include "UnityCG.cginc"

uniform float _Size;


// **************************************************************
// Data structures												*
// **************************************************************
struct gs_input
{
    float4 position : SV_POSITION;
    float4 col : COLOR;
};
struct ps_input {
    float4 position : SV_POSITION;
    float4 col : COLOR;
};

// **************************************************************
// Vars															*
// **************************************************************
gs_input vert (appdata_base v)
{
	gs_input output = (gs_input)0;
    output.position =  mul(_Object2World, v.vertex);
    return output;
}

// Geometry Shader -----------------------------------------------------
[maxvertexcount(24)]
void geom (point gs_input inp[1], inout TriangleStream<ps_input> triStream)
{
	float halfS = 0.5f * _Size;
			
	//offsets
	float4 v[8];
	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);//
	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);//
	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);//
	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);//
	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);//
	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);//
	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);//
	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);//

	float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
	ps_input pIn;
	//back
	pIn.position = mul(vp, v[0]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[2]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[1]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[3]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	triStream.RestartStrip();
	//front
	pIn.position = mul(vp, v[4]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[5]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[6]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[7]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);
	
	triStream.RestartStrip();

		//right
	pIn.position = mul(vp, v[0]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[1]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[4]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[5]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);
	
	triStream.RestartStrip();
			//left
	pIn.position = mul(vp, v[6]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[7]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[2]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[3]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);
	
	triStream.RestartStrip();

			//top
	pIn.position = mul(vp, v[0]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[4]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[2]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[6]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);
	
	triStream.RestartStrip();
			//bottom
	pIn.position = mul(vp, v[5]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[1]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[7]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);

	pIn.position =  mul(vp, v[3]);
	pIn.col = inp[0].col;
	triStream.Append(pIn);
	
	triStream.RestartStrip();
	
}

float4 frag (ps_input i) : COLOR
{
	return i.col;
}

ENDCG
}//end pass 1

// Pass to render object as a shadow caster
		Pass {
			Name "ShadowCaster"
			Tags {"LightMode" = "ShadowCaster" }  
			Fog {Mode Off}

			ZWrite On ZTest LEqual Cull Off

			Offset 1, 1

			CGPROGRAM
			#pragma target 5.0
			#pragma vertex SHADOW_VS_Main
			#pragma fragment SHADOW_FS_Main
			#pragma geometry SHADOW_GS_Main
			#pragma multi_compile_shadowcaster
			#pragma fragmentoption ARB_precision_hint_fastest
			#include "UnityCG.cginc"


			// **************************************************************
			// Data structures												*
			// **************************************************************
			struct SHADOW_GS_INPUT
			{
                V2F_SHADOW_CASTER;
            };
            struct SHADOW_FS_INPUT
			{
				V2F_SHADOW_CASTER;
            };
            // **************************************************************
			// Vars															*
			// **************************************************************

			float _Size;
			float4x4 _VP;

            // **************************************************************
			// Shader Programs												*
			// **************************************************************

			// Vertex Shader ------------------------------------------------
			SHADOW_GS_INPUT SHADOW_VS_Main(appdata_base v)
			{
                SHADOW_GS_INPUT output = (SHADOW_GS_INPUT)0;
				output.pos =  mul(_Object2World, v.vertex);
                return output;
            }
			// Geometry Shader -----------------------------------------------------
			[maxvertexcount(24)]
			void SHADOW_GS_Main(point SHADOW_GS_INPUT p[1], inout TriangleStream<SHADOW_FS_INPUT> triStream)
			{
				float halfS = 0.5f * _Size;
			
				//offsets
				float4 v[8];
				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);//
				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);//
				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);//
				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);//
				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);//
				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);//
				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);//
				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);//

				float4x4 vp = mul(UNITY_MATRIX_MVP, _World2Object);
				
                SHADOW_FS_INPUT pIn=p[0];
				//back
				pIn.pos = mul(vp, v[0]);
				triStream.Append(pIn);

				pIn.pos = mul(vp, v[2]);
				triStream.Append(pIn);

				pIn.pos = mul(vp, v[1]);
				triStream.Append(pIn);

				pIn.pos = mul(vp, v[3]);
				triStream.Append(pIn);

				triStream.RestartStrip();
				//front
				pIn.pos = mul(vp, v[4]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[5]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[6]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[7]);
				triStream.Append(pIn);
	
				triStream.RestartStrip();

					//right
				pIn.pos = mul(vp, v[0]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[1]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[4]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[5]);
				triStream.Append(pIn);
	
				triStream.RestartStrip();
						//left
				pIn.pos = mul(vp, v[6]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[7]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[2]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[3]);
				triStream.Append(pIn);
	
				triStream.RestartStrip();

						//top
				pIn.pos = mul(vp, v[0]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[4]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[2]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[6]);
				triStream.Append(pIn);
	
				triStream.RestartStrip();
						//bottom
				pIn.pos = mul(vp, v[5]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[1]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[7]);
				triStream.Append(pIn);

				pIn.pos =  mul(vp, v[3]);
				triStream.Append(pIn);
	
				triStream.RestartStrip();
            }
			// Fragment Shader -----------------------------------------------
			float4 SHADOW_FS_Main(SHADOW_FS_INPUT input) : COLOR
			{
				SHADOW_CASTER_FRAGMENT(input)
            }
		ENDCG
		}
}

Fallback Off
}

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.