//-----------------------------------------------------------------------------------------------------------------------------------------
// * shader für edge-quad-stencil-shadows
// * unterstützt nur ungeskinnte Meshes
//-----------------------------------------------------------------------------------------------------------------------------------------

//#define SHOW_VOLUMES

float4x4 c_mWorld					: WORLD;	// muss aus irgendeinem grund dasein, da sonst die inverse matrix schrott ist :/
float4x4 c_mWorldInverse			: WORLDINVERSE;
float4x4 c_mWorldViewProjection		: WORLDVIEWPROJECTION;

float3	c_vLightDir;
	
struct VS_SHADOW_INPUT
{
	float3 vPos	: POSITION;
	float3 vNrm	: NORMAL;
};

struct VS_SHADOW_OUTPUT
{
	float4 vPos	: POSITION;
};

//-----------------------------------------------------------------------------------------------------------------------------------------

VS_SHADOW_OUTPUT
vsDynamicShadowVolumeStaticMesh(VS_SHADOW_INPUT i)
{
	VS_SHADOW_OUTPUT o;
	
	float4 vLightDirOS = mul(float4(c_vLightDir, 0), c_mWorldInverse);
	float4 vPositionOS = float4(i.vPos, 1);
	
	if (dot(i.vNrm, vLightDirOS) > 0)
	{
		vPositionOS = vLightDirOS;
	}
	
	o.vPos = mul(vPositionOS, c_mWorldViewProjection);

	return o;
}
	

//-----------------------------------------------------------------------------------------------------------------------------------------
// dynamicshadowvolume_staticmesh: für das Mesh wurden EdgeQuads generiert, Vertexshader muss displacement durchführen
technique shadowvolume_staticmesh
{
#ifndef D3DSTENCILCAPS_TWOSIDED

	pass backfaces
	{
		CullMode = cw;
		
		ZWriteenable = false;
		ZFunc = greaterequal;
	
		VertexShader = compile vs_1_1 vsDynamicShadowVolumeStaticMesh();
		PixelShader = NULL;

		ColorWriteEnable = 0;

		AlphaTestEnable = false;
		AlphaBlendEnable = false;

		StencilEnable = true;
		StencilFunc = always;
		StencilPass = decr;
	}
	
	pass frontfaces
	{
		CullMode = ccw;
		StencilPass = incr;
	}
	
#else // D3DSTENCILCAPS_TWOSIDED

	pass twosided
	{
		CullMode = none;
		
		ZWriteenable = false;
		ZFunc = greaterequal;
	
		VertexShader = compile vs_1_1 vsDynamicShadowVolumeStaticMesh();
		PixelShader = NULL;

		ColorWriteEnable = 0;

		AlphaTestEnable = false;
		AlphaBlendEnable = false;

		TwoSidedStencilMode = true;
		StencilEnable = true;
		StencilFunc = always;
		StencilPass = incr;
		CCW_StencilFunc = always;
		CCW_StencilPass = decr;
	}

#endif // D3DSTENCILCAPS_TWOSIDED



#ifdef SHOW_VOLUMES
	pass p0
	{
		cullmode = none;

		VertexShader = compile vs_1_1 vsDynamicShadowVolumeStaticMesh();
		PixelShader = NULL;
		ZFunc = less;
		
		TextureFactor = float4(0.1,0,0,1);
		ColorWriteEnable = Red;
		
		ColorOp[0] = SelectArg1;
		ColorArg1[0] = TFactor;
		
		ColorOp[1] = Disable;
		AlphaOp[0] = Disable;

		StencilEnable = false;

		AlphaBlendEnable = false;
		SrcBlend = One;
		DestBlend = One;
	}
#endif // SHOW_VOLUMES
}
//-----------------------------------------------------------------------------------------------------------------------------------------
// dynamicshadowvolume_skinnedmesh: für das Mesh wurden EdgeQuads generiert, Vertexshader muss displacement+skinning durchführen
technique shadowvolume_skinnedmesh
{
    // todo
}


//-----------------------------------------------------------------------------------------------------------------------------------------

VS_SHADOW_OUTPUT
vsStaticShadowVolumeStaticMesh(float3 vPos : POSITION0)
{
	VS_SHADOW_OUTPUT o;
	o.vPos = mul(float4(vPos, 1), c_mWorldViewProjection);
	return o;
}
	
//-----------------------------------------------------------------------------------------------------------------------------------------
// staticshadowvolume_staticmesh: Schatten wurde bereits beim Laden extrudiert
technique staticshadowvolume_staticmesh
{

#ifndef D3DSTENCILCAPS_TWOSIDED

	pass backfaces
	{
		CullMode = ccw;
		
		ZWriteenable = false;
		ZFunc = greaterequal;
	
		VertexShader = compile vs_1_1 vsStaticShadowVolumeStaticMesh();
		PixelShader = NULL;

		ColorWriteEnable = 0;

		AlphaTestEnable = false;
		AlphaBlendEnable = false;

		StencilEnable = true;
		StencilFunc = always;
		StencilPass = decr;
	}
	
	pass frontfaces
	{
		CullMode = cw;
		StencilPass = incr;
	}
	
#else // D3DSTENCILCAPS_TWOSIDED

	pass twosided
	{
		CullMode = none;
		
		ZWriteenable = false;
		ZFunc = greaterequal;
	
		VertexShader = compile vs_1_1 vsStaticShadowVolumeStaticMesh();
		PixelShader = NULL;

		ColorWriteEnable = 0;

		AlphaTestEnable = false;
		AlphaBlendEnable = false;

		TwoSidedStencilMode = true;
		StencilEnable = true;
		StencilFunc = always;
		StencilPass = decr;
		CCW_StencilFunc = always;
		CCW_StencilPass = incr;
	}

#endif // D3DSTENCILCAPS_TWOSIDED



#ifdef SHOW_VOLUMES
	pass p0
	{
		cullmode = none;

		VertexShader = compile vs_1_1 vsStaticShadowVolumeStaticMesh();
		PixelShader = NULL;
		ZFunc = less;
		
		TextureFactor = float4(0.1,0,0,1);
		ColorWriteEnable = Red;
		
		ColorOp[0] = SelectArg1;
		ColorArg1[0] = TFactor;
		
		ColorOp[1] = Disable;
		AlphaOp[0] = Disable;

		StencilEnable = false;

		AlphaBlendEnable = false;
		SrcBlend = One;
		DestBlend = One;
	}
#endif // SHOW_VOLUMES

}
//-----------------------------------------------------------------------------------------------------------------------------------------
// staticshadowvolume_skinnedmesh: für das Mesh wurden EdgeQuads generiert, Vertexshader muss displacement+skinning durchführen
technique staticshadowvolume_skinnedmesh
{
    // todo
}
//-----------------------------------------------------------------------------------------------------------------------------------------
