float3 g_LightDir;
float4x4 g_matInvViewProj;
float4x4 g_matInvView;
float4x4 g_matView;
float4x4 g_matInvProj;
float g_ShadowConfT;
float g_iPass;
float g_MaxPasses;
float g_ConfScale;
float2 g_RTSize;

float g_ExactFilterSize = 3; //exact filtering for oversampling, 1 = take all samples under 1 screenspace fragement

const float g_DotLNHide = 0.1f; //offset to hide projective aliasing

#include "ShadowMapping.fx"
#include "WPT.fx"

texture g_texDiffuse;
sampler2D g_sDiffuse = sampler_state
{
    Texture = <g_texDiffuse>;
    AddressU = Clamp;
    AddressV = Clamp;
    MipFilter = NONE;
    MagFilter = POINT;
    MinFilter = POINT;
};

texture g_texNormal;
sampler2D g_sNormal = sampler_state
{
    Texture = <g_texNormal>;
    AddressU = Clamp;
    AddressV = Clamp;
    MipFilter = NONE;
    MagFilter = POINT;
    MinFilter = POINT;
};

texture g_texOptConf;
sampler2D g_sOptConf = sampler_state
{
    Texture = <g_texOptConf>;
    AddressU = Clamp;
    AddressV = Clamp;
    MipFilter = NONE;
    MagFilter = POINT;
    MinFilter = POINT;
};

texture g_texID;
sampler2D g_sID = sampler_state
{
    Texture = <g_texID>;
    AddressU = Clamp;
    AddressV = Clamp;
    MipFilter = NONE;
    MagFilter = POINT;
    MinFilter = POINT;
};

struct SHADOW_OUT
{
	float4 Shadow : COLOR0;
	float Z : DEPTH;
	//float4 SPass : COLOR1;
};

//old method: splats quads with conf < ConfT
SHADOW_OUT PSShadowSimple(float2 ScreenCoord:TEXCOORD0, uniform bool pretest, uniform int wpt, uniform bool id, uniform bool filter)
{
	SHADOW_OUT o;

	float3 wpos = GetFragmentWorldPos(ScreenCoord, wpt);
	
	float2 NXY = tex2D(g_sNormal, ScreenCoord);
	float3 Normal = float3(NXY, sqrt(1 - NXY.x*NXY.x - NXY.y*NXY.y));
	float4 Diffuse = tex2D(g_sDiffuse, ScreenCoord);
	Normal.z *= Diffuse.a * 2 - 1;

	float slope = (1-dot(Normal, -g_LightDir));
    float bias = slope * SM_SlopeBias + SM_DetphBias;
	//bias *= (1 + (vcam.z/2000)*20);
	float4 swpos = float4(wpos + bias * -g_LightDir, 1);
	//float4 swpos = wpos;

	float2 ShadowDepth = CalcDepth(swpos);
	float shdepth = ShadowDepth.x/ShadowDepth.y;
	float4 SMTexC = CalcSMTexC(swpos);

	float2 tc = SMTexC.xy/SMTexC.w;

	if(pretest)
	{
		float rcpSMSize = 1.f / SM_ShadowMapSize;
		//float rcpSMSize = SM_rcpShadowMapSize;

		float2 tcpcf = tc - 0.5f * rcpSMSize;
		//make pcf pre-test
		float4 sourcevals;
		sourcevals.x = (tex2D( SM_SShadowMap, tcpcf ).r + SHADOW_EPSILON < shdepth)? 1.0f: 0.0f;  
		sourcevals.y = (tex2D( SM_SShadowMap, tcpcf + float2(rcpSMSize, 0) ).r + SHADOW_EPSILON < shdepth)? 1.0f: 0.0f;  
		sourcevals.z = (tex2D( SM_SShadowMap, tcpcf + float2(0, rcpSMSize) ).r + SHADOW_EPSILON < shdepth)? 1.0f: 0.0f;  
		sourcevals.w = (tex2D( SM_SShadowMap, tcpcf + float2(rcpSMSize, rcpSMSize) ).r + SHADOW_EPSILON < shdepth)? 1.0f: 0.0f;  

		if(all(sourcevals))// || all(1-sourcevals))
		{
			o.Shadow = float4(sourcevals.x, g_iPass/g_MaxPasses, 1, 0);
			o.Z = 1;

			return o;
		}
	}
	
	float2 samplepos = frac(tc * SM_ShadowMapSize);
	float conf = 1 - max(abs(samplepos.x - 0.5f), abs(samplepos.y - 0.5f)) * 2;

	if(conf - g_ShadowConfT >= 0)
	{
		float sh = CalcShadow_Simple(SMTexC, shdepth, id ? tex2D(g_sID, ScreenCoord).r : 0);
		o.Shadow = float4(sh, g_iPass/g_MaxPasses, conf, filter ? conf * conf : 0);
		if(o.Shadow.x > 0)
			o.Z = 0.5f;
		else
			o.Z = 0;
		//o.Z = conf;
	}
	else
	{
		o.Shadow = 0;
		o.Z = 0;
	}

	return o;
}

//new method: blends fragments with highest confidence to framebuffer

SHADOW_OUT PSShadowAdapted(float2 ScreenCoord:TEXCOORD0, uniform bool pretest, uniform bool bclip, uniform int wpt, uniform bool id)
{
	SHADOW_OUT o;

	float3 wpos = GetFragmentWorldPos(ScreenCoord, wpt);
	
	float2 NXY = tex2D(g_sNormal, ScreenCoord);
	float3 Normal = float3(NXY, sqrt(1 - NXY.x*NXY.x - NXY.y*NXY.y));
	float4 Diffuse = tex2D(g_sDiffuse, ScreenCoord);
	Normal.z *= Diffuse.a * 2 - 1;

	float slope = (1-saturate(dot(Normal, -g_LightDir)));
    float bias = slope * SM_SlopeBias + SM_DetphBias;
	bias *= 1 / g_ConfScale;
	//bias *= (1 + (vcam.z/2000)*20);
	float4 swpos = float4(wpos + bias * -g_LightDir, 1);
	//float4 swpos = wpos;

	float2 ShadowDepth = CalcDepth(swpos);
	float SDepth = ShadowDepth.x/ShadowDepth.y;
	float4 SMTexC = CalcSMTexC(swpos);

	float2 tc = SMTexC.xy/SMTexC.w;

	float2 rsdepthproj = CalcDepth(float4(wpos, 1));
	float rsdepth = rsdepthproj.x / rsdepthproj.y;

	if (bclip)
	{
		//ShadowDepth is from biased world so its not exactly 1 and 0
		float2 ShadowDepthUnbiased = CalcDepth(float4(wpos, 1));
		float shdepthunbiased = ShadowDepthUnbiased.x/ShadowDepthUnbiased.y;
		if(shdepthunbiased <= 0 || shdepthunbiased >= 1)
			clip(-1);

		//clip if outside shadow map
		float4 vclip = float4(tc, 1-tc);
		clip(vclip);
	}

	if(pretest)
	{
		float rcpSMSize = 1/SM_ShadowMapSize;
		//float rcpSMSize = SM_rcpShadowMapSize;

		float2 tcpcf = tc - 0.5f * rcpSMSize;
		//make pcf pre-test
		float4 sourcevals;
		sourcevals.x = (tex2D( SM_SShadowMap, tcpcf ).r + SHADOW_EPSILON < SDepth)? 1.0f: 0.0f;  
		sourcevals.y = (tex2D( SM_SShadowMap, tcpcf + float2(rcpSMSize, 0) ).r + SHADOW_EPSILON < SDepth)? 1.0f: 0.0f;  
		sourcevals.z = (tex2D( SM_SShadowMap, tcpcf + float2(0, rcpSMSize) ).r + SHADOW_EPSILON < SDepth)? 1.0f: 0.0f;  
		sourcevals.w = (tex2D( SM_SShadowMap, tcpcf + float2(rcpSMSize, rcpSMSize) ).r + SHADOW_EPSILON < SDepth)? 1.0f: 0.0f;  

		if(all(sourcevals) || all(1-sourcevals))
		{
			o.Shadow = float4(sourcevals.x, g_iPass/g_MaxPasses, 1, 0);
			o.Z = 1;

			return o;
		}
	}
	
	float2 samplepos = frac(tc * SM_ShadowMapSize);
	float conf = 1 - max(abs(samplepos.x - 0.5f), abs(samplepos.y - 0.5f))*2;

	conf = 1 - (1 - conf) / g_ConfScale;

	float confopt = saturate(tex2D(g_sOptConf, ScreenCoord));

	//o.Shadow = confopt;
	//o.Z = 1;
	//return o;

	//if smslope == 1, definitely in shadow
	if(slope >= (1 - g_DotLNHide))
	{
		o.Shadow = float4(1, g_iPass/g_MaxPasses, 1, 0);
		o.Z = 1;
	}
	else
	{
		float sh = CalcShadow_Simple(SMTexC, SDepth, id ? tex2D(g_sID, ScreenCoord).r : 0);
		//float sh = CalcShadow_9xGaussPCF(SMTexC, SDepth);
		//float currconf = saturate(conf + (1-confopt) * g_ConfScale);
		//float currconf = saturate(conf + (1 - g_ShadowConfT));
		//float currconf = saturate(conf + (1 - g_ShadowConfT) + (1 - confopt));
		float currconf = saturate(conf + (1 - g_ShadowConfT) + (1 - confopt));
		//float currconf = conf + 1 - confopt;
		o.Shadow = float4(sh, g_iPass/g_MaxPasses, currconf, 0);
		//o.Z = saturate(conf + (1-ShadowConfT));// because 0 is init
		o.Z = currconf;
		/*if (sh == 1)
		{
			o.Z = currconf;
		}
		else
		{
			o.Z = 0;
		}*/
		//o.Z = saturate(conf + (1-confopt));
		//o.Z = saturate(conf);
		
		/*if(conf > ShadowConfT)
		{
			o.Shadow = float4(sh, iPass/256, conf, 0);
			o.Z = 1;
			// stencil gets increased
		}
		else
		{
			clip(-1);
		}*/
	}	
	return o;
}

SHADOW_OUT PSShadowAccumulate(float2 ScreenCoord:TEXCOORD0, uniform bool bclip, uniform int wpt, uniform bool id)
{
	SHADOW_OUT o;

	float3 wpos = GetFragmentWorldPos(ScreenCoord, wpt);
	
	float2 NXY = tex2D(g_sNormal, ScreenCoord);
	float3 Normal = float3(NXY, sqrt(1 - NXY.x*NXY.x - NXY.y*NXY.y));
	float4 Diffuse = tex2D(g_sDiffuse, ScreenCoord);
	Normal.z *= Diffuse.a * 2 - 1;

	float slope = (1-saturate(dot(Normal, -g_LightDir)));
    float bias = slope * SM_SlopeBias + SM_DetphBias;
	//bias *= (1 + (vcam.z/2000)*20);
	float4 swpos = float4(wpos + bias * -g_LightDir, 1);
	//float4 swpos = wpos;

	float2 ShadowDepth = CalcDepth(swpos);
	float SDepth = ShadowDepth.x/ShadowDepth.y;
	float4 SMTexC = CalcSMTexC(swpos);

	float2 tc = SMTexC.xy/SMTexC.w;

	float2 rsdepthproj = CalcDepth(float4(wpos, 1));
	float rsdepth = rsdepthproj.x / rsdepthproj.y;

	if (bclip)
	{
		//ShadowDepth is from biased world so its not exactly 1 and 0
		float2 ShadowDepthUnbiased = CalcDepth(float4(wpos, 1));
		float shdepthunbiased = ShadowDepthUnbiased.x/ShadowDepthUnbiased.y;
		if(shdepthunbiased <= 0 || shdepthunbiased >= 1)
			clip(-1);

		//clip if outside shadow map
		float4 vclip = float4(tc, 1-tc);
		clip(vclip);
	}
	
	float2 samplepos = frac(tc * SM_ShadowMapSize);
	float conf = 1 - max(abs(samplepos.x - 0.5f), abs(samplepos.y - 0.5f))*2;

	conf = 1 - (1-conf) * g_ConfScale;

	float confopt = saturate(tex2D(g_sOptConf, ScreenCoord));

	//if smslope == 1, definitely in shadow
	if(slope >= (1 - g_DotLNHide))
	{
		o.Shadow = float4(1, g_iPass/g_MaxPasses, 1, 0);
		o.Z = 1;
	}
	else
	{
		float sh = CalcShadow_Simple(SMTexC, SDepth, id ? tex2D(g_sID, ScreenCoord).r : 0);
		//float currconf = saturate(conf + (1-confopt) * g_ConfScale);
		//float currconf = saturate(conf + (1 - g_ShadowConfT));
		float currconf = saturate(conf + (1 - g_ShadowConfT) + (1 - confopt));
		//float currconf = conf + 1 - confopt;
		o.Shadow = float4(sh, g_iPass/g_MaxPasses, conf, currconf * currconf * currconf * currconf);
		//o.Z = saturate(conf + (1-ShadowConfT));// because 0 is init
		o.Z = currconf;
	}	
	return o;
}

float g_TileNear;
float g_TileFar;
float g_BiasScale = 1;

float4 PSShadowTile(float2 ScreenCoord:TEXCOORD0, uniform int wpt, uniform bool id, uniform bool filter, uniform bool selecttile, uniform bool exactfilter) : COLOR
{
	SHADOW_OUT o;

	float3 wpos = GetFragmentWorldPos(ScreenCoord, wpt);
	
	float2 NXY = tex2D(g_sNormal, ScreenCoord);
	float3 Normal = float3(NXY, sqrt(1 - NXY.x*NXY.x - NXY.y*NXY.y));
	float4 Diffuse = tex2D(g_sDiffuse, ScreenCoord);
	Normal.z *= Diffuse.a * 2 - 1;

	float slope = (1-saturate(dot(Normal, -g_LightDir)));
    float bias = slope * SM_SlopeBias + SM_DetphBias;
	bias *= g_BiasScale;
	//bias *= (1 + (vcam.z/2000)*20);
	float4 swpos = float4(wpos + bias * -g_LightDir, 1);
	//float4 swpos = wpos;

	float2 ShadowDepth = CalcDepth(swpos);
	float SDepth = ShadowDepth.x/ShadowDepth.y;
	float4 SMTexC = CalcSMTexC(swpos);

	float2 tc = SMTexC.xy/SMTexC.w;

	float2 rsdepthproj = CalcDepth(float4(wpos, 1));
	float rsdepth = rsdepthproj.x / rsdepthproj.y;

	if (selecttile)
	{
		float4 vpos = mul(float4(wpos, 1), g_matView);

		if (vpos.z < g_TileNear || vpos.z > g_TileFar)
			clip(-1);
	}
	else
	{
		//ShadowDepth is from biased world so its not exactly 1 and 0
		float2 ShadowDepthUnbiased = CalcDepth(float4(wpos, 1));
		float shdepthunbiased = ShadowDepthUnbiased.x/ShadowDepthUnbiased.y;
		if(shdepthunbiased <= 0.001 || shdepthunbiased >= 0.999)
			clip(-1);

		//clip if outside shadow map
		float4 vclip = float4(tc - 0.5/SM_ShadowMapSize, 1 - tc - 0.5/SM_ShadowMapSize);
		clip(vclip);
	}
	
	float2 samplepos = frac(tc * SM_ShadowMapSize);
	float conf = 1 - max(abs(samplepos.x - 0.5f), abs(samplepos.y - 0.5f))*2;

	//if smslope == 1, definitely in shadow
	if(slope >= (1 - g_DotLNHide))
	{
		o.Shadow = float4(1, g_iPass/g_MaxPasses, 1, 0);
		o.Z = 1;
	}
	else
	{
		float sh;

		if (filter)
		{
			//if(0)
			if (exactfilter)
			{
				float c = tex2D(g_sOptConf, ScreenCoord).r;
				float s = ((1 - c) * g_ConfScale) * g_ExactFilterSize;

				/*[branch] if (s > 1) //oversampling
				{
					int is = (int)s;
					sh = CalcShadow_XxAvg(SMTexC, SDepth,is, s/is); 
				} 
				else //undersampling
				{
					sh = CalcShadow_4xPCF(SMTexC, SDepth); 
				}*/
//				if (0)
				if (s <= 1)
				{
					sh = CalcShadow_4xPCF(SMTexC, SDepth); //undersampling
					//sh = CalcShadow_XxAvg(SMTexC, SDepth, 1, 1);
				}
				//else if (s <= 2) //oversampling up to 3x3 
				//{
					//sh = CalcShadow_25xGaussPCF(SMTexC.xy / SMTexC.w, SDepth, s/5 * 3); //offsetscale 1 = 5 samples
					//sh = CalcShadow_9xGaussPCF(SMTexC.xy / SMTexC.w, SDepth);  
					//sh = CalcShadow_XXxGaussPCF(SMTexC.xy / SMTexC.w, SDepth, s/3 );	
				//	sh = CalcShadow_XxAvg(SMTexC, SDepth, 2, s/2);
				//}
				//else if (s <= 3) //oversampling up to 3x3 
				//{
					//sh = CalcShadow_25xGaussPCF(SMTexC.xy / SMTexC.w, SDepth, s/5 * 3); //offsetscale 1 = 5 samples
					//sh = CalcShadow_9xGaussPCF(SMTexC.xy / SMTexC.w, SDepth);  
					//sh = CalcShadow_XXxGaussPCF(SMTexC.xy / SMTexC.w, SDepth, s/3 );	
				//	sh = CalcShadow_XxAvg(SMTexC, SDepth, 3, s/3);
				//}
				else //if (s <= 5)  
				{
					sh = CalcShadow_XXxGaussPCF(SMTexC.xy / SMTexC.w, SDepth, s/3 );	
					//sh = CalcShadow_9xGaussPCF(SMTexC.xy / SMTexC.w, SDepth);
				}
 
				//if (s > 3)
				//	sh = 0;

				//if (c < 0)
				//	sh = 0;
				//return float4((int)(s + 10)/ 20, 0 , 0, 1);
			}
			else
			{
				//sh = CalcShadow_4xPCF(SMTexC, SDepth);
				sh = CalcShadow_9xGaussPCF(SMTexC.xy / SMTexC.w, SDepth);			
			}
		}
		else 
		{
			sh = CalcShadow_Simple(SMTexC, SDepth, id ? tex2D(g_sID, ScreenCoord).r : 0);
		}

		//float currconf = saturate(conf + (1-confopt) * g_ConfScale);
		//float currconf = conf;
		float currconf = 1 - (1 - conf) / g_ConfScale;
		//float currconf = saturate(conf + (1 - g_ShadowConfT) + (1 - confopt) * g_ConfScale);
		o.Shadow = float4(sh, g_iPass/g_MaxPasses, currconf, 0);
		//o.Z = saturate(conf + (1-ShadowConfT));// because 0 is init
		o.Z = currconf*0.995 + 0.005;
		//o.Z = saturate(conf + (1-confopt));
		//o.Z = saturate(conf);
		
		/*if(conf > ShadowConfT)
		{
			o.Shadow = float4(sh, iPass/256, conf, 0);
			o.Z = 1;
			// stencil gets increased
		}
		else
		{
			clip(-1);
		}*/
	}	
	//return o;
	return o.Shadow;
}

stateblock RSDeferredShadow = stateblock_state
{
	CullMode = NONE;
    ZEnable = true;
	ZWriteEnable = true;
	ZFunc = GREATER;
    AlphaBlendEnable = false;
    AlphaTestEnable = false;
};


#define RenderShadow_Simple(nameext, wpt, id)								\
technique RenderShadow_Simple_##nameext										\
{																			\
    pass P0																	\
    {																		\
		StateBlock = (RSDeferredShadow);									\
																			\
        VertexShader = null;												\
        PixelShader  = compile ps_3_0 PSShadowSimple(false, wpt, id, false);\
    }																		\
}																			\
technique RenderShadow_Simple_PreTest_##nameext								\
{																			\
    pass P0																	\
    {																		\
		StateBlock = (RSDeferredShadow);									\
																			\
        VertexShader = null;												\
        PixelShader  = compile ps_3_0 PSShadowSimple(true, wpt, id, false);	\
    }																		\
}

#define RenderShadow_Adapted(nameext, wpt, id, clip)						\
technique RenderShadow_Adapted_##nameext									\
{																			\
    pass P0																	\
    {																		\
		StateBlock = (RSDeferredShadow);									\
																			\
        VertexShader = null;												\
        PixelShader  = compile ps_3_0 PSShadowAdapted(false, clip, wpt, id);\
    }																		\
}																			\
technique RenderShadow_Adapted_PreTest_##nameext							\
{																			\
    pass P0																	\
    {																		\
		StateBlock = (RSDeferredShadow);									\
																			\
        VertexShader = null;												\
        PixelShader  = compile ps_3_0 PSShadowAdapted(true, clip, wpt, id); \
    }																		\
}

#define RenderShadow_Tile(nameext, wpt, id, filter, exact)					\
technique RenderShadow_Tile_##nameext										\
{                                                                           \
    pass P0                                                                 \
    {                                                                       \
        StateBlock = (RSDeferredShadow);									\
																			\
		ZEnable = false;				                                    \
                                                                            \
        VertexShader = null;												\
        PixelShader  = compile ps_3_0 PSShadowTile(wpt, id, filter, false, exact); \
    }                                                                       \
}																			\
																			\
technique RenderShadow_Tile_Select_##nameext								\
{                                                                           \
    pass P0                                                                 \
    {                                                                       \
        StateBlock = (RSDeferredShadow);									\
																			\
		ZEnable = false;				                                    \
                                                                            \
        VertexShader = null;												\
        PixelShader  = compile ps_3_0 PSShadowTile(wpt, id, filter, true, exact);	\
    }                                                                       \
}


RenderShadow_Simple(World, WPT_WORLDPOS, false);
RenderShadow_Simple(Depth, WPT_DEPTH, false);
RenderShadow_Simple(LinearDepth, WPT_LINEARDEPTH, false);

RenderShadow_Simple(World_ID, WPT_WORLDPOS, true);
RenderShadow_Simple(Depth_ID, WPT_DEPTH, true);
RenderShadow_Simple(LinearDepth_ID, WPT_LINEARDEPTH, true);


RenderShadow_Adapted(World, WPT_WORLDPOS, false, false);
RenderShadow_Adapted(Depth, WPT_DEPTH, false, false);
RenderShadow_Adapted(LinearDepth, WPT_LINEARDEPTH, false, false);

RenderShadow_Adapted(World_ID, WPT_WORLDPOS, true, false);
RenderShadow_Adapted(Depth_ID, WPT_DEPTH, true, false);
RenderShadow_Adapted(LinearDepth_ID, WPT_LINEARDEPTH, true, false);

RenderShadow_Adapted(Clip_World, WPT_WORLDPOS, false, true);
RenderShadow_Adapted(Clip_Depth, WPT_DEPTH, false, true);
RenderShadow_Adapted(Clip_LinearDepth, WPT_LINEARDEPTH, false, true);

RenderShadow_Adapted(Clip_World_ID, WPT_WORLDPOS, true, true);
RenderShadow_Adapted(Clip_Depth_ID, WPT_DEPTH, true, true);
RenderShadow_Adapted(Clip_LinearDepth_ID, WPT_LINEARDEPTH, true, true);


technique RenderShadow_Simple_Filter_LinearDepth_ID
{                                
    pass P0                      
    {                            
        CullMode = NONE;
		ZEnable = false;
		ZWriteEnable = true;
		ZFunc = GREATER;
		AlphaBlendEnable = true;
		SrcBlend = SRCALPHA;
		DestBlend = ONE;
		BlendOP = ADD;
		AlphaTestEnable = false;				                                   
 
        VertexShader = null;											
        PixelShader  = compile ps_3_0 PSShadowSimple(false, WPT_LINEARDEPTH, true, true);
    }
}

technique RenderShadow_Accumulate_LinearDepth_ID
{                                
    pass P0                      
    {                            
        CullMode = NONE;
		ZEnable = false;
		ZWriteEnable = true;
		ZFunc = GREATER;
		AlphaBlendEnable = true;
		SrcBlend = SRCALPHA;
		DestBlend = ONE;
		BlendOP = ADD;
		AlphaTestEnable = false;				                                   
 
        VertexShader = null;											
        PixelShader  = compile ps_3_0 PSShadowAccumulate(false, WPT_LINEARDEPTH, true);
    }
}

technique RenderShadow_Accumulate_Clip_LinearDepth_ID
{                                
    pass P0                      
    {                            
        CullMode = NONE;
		ZEnable = false;
		ZWriteEnable = true;
		ZFunc = GREATER;
		AlphaBlendEnable = true;
		SrcBlend = SRCALPHA;
		DestBlend = ONE;
		BlendOP = ADD;
		AlphaTestEnable = false;				                                   
 
        VertexShader = null;											
        PixelShader  = compile ps_3_0 PSShadowAccumulate(true, WPT_LINEARDEPTH, true);
    }
}

RenderShadow_Tile(World, WPT_WORLDPOS, false, false, false);
RenderShadow_Tile(Depth, WPT_DEPTH, false, false, false);
RenderShadow_Tile(LinearDepth, WPT_LINEARDEPTH, false, false, false);

RenderShadow_Tile(World_ID, WPT_WORLDPOS, true, false, false);
RenderShadow_Tile(Depth_ID, WPT_DEPTH, true, false, false);
RenderShadow_Tile(LinearDepth_ID, WPT_LINEARDEPTH, true, false, false);

RenderShadow_Tile(World_Filter, WPT_WORLDPOS, false, true, false);
RenderShadow_Tile(Depth_Filter, WPT_DEPTH, false, true, false);
RenderShadow_Tile(LinearDepth_Filter, WPT_LINEARDEPTH, false, true, false);

RenderShadow_Tile(World_FilterEx, WPT_WORLDPOS, false, true, true);
RenderShadow_Tile(Depth_FilterEx, WPT_DEPTH, false, true, true);
RenderShadow_Tile(LinearDepth_FilterEx, WPT_LINEARDEPTH, false, true, true);