float4x4 g_matInvViewProj : INVVIEWPROJ;
float4x4 g_matInvView;
float4x4 g_matInvProj;
float g_ShadowConfT;
float3 g_LightDir;
float2 g_RTSize;

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

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

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

//get shadow map texture coordinates for given screencoord
float2 GetSMTCOptConf(const float2 coord, const int wpt)
{
	float3 wpos = GetFragmentWorldPos(coord, wpt);

	//project to lightspace and get texture coordinates
	float4 smtc = CalcSMTexC(float4(wpos, 1));

	return smtc.xy / smtc.w;
}

float4 PSOptConf(float2 ScreenCoord:TEXCOORD0, uniform int wpt) : COLOR
{
	//calculate shadow map texture coordinates for current fragment
	float2 tccenter = GetSMTCOptConf(ScreenCoord, wpt);

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

	//also get smtc for neighbours and find minimum distance
	float tcmindist = 1;

	float2 rcpRTSize = 1.0f / g_RTSize;
	
	tcmindist = min(length(tccenter - GetSMTCOptConf(ScreenCoord + float2(-rcpRTSize.x, 0), wpt)), 1);
	tcmindist = min(length(tccenter - GetSMTCOptConf(ScreenCoord + float2(+rcpRTSize.x, 0), wpt)), tcmindist);
	tcmindist = min(length(tccenter - GetSMTCOptConf(ScreenCoord + float2(0, -rcpRTSize.y), wpt)), tcmindist);
	tcmindist = min(length(tccenter - GetSMTCOptConf(ScreenCoord + float2(0, +rcpRTSize.y), wpt)), tcmindist);

	//maybe also sample 8er neighbours
	/*tcmindist = min(length(tccenter - GetSMTCOptConf(ScreenCoord + float2(-1,-1) * rcpRTSize, wpt)), tcmindist);
	tcmindist = min(length(tccenter - GetSMTCOptConf(ScreenCoord + float2(-1,+1) * rcpRTSize, wpt)), tcmindist);
	tcmindist = min(length(tccenter - GetSMTCOptConf(ScreenCoord + float2(+1,-1) * rcpRTSize, wpt)), tcmindist);
	tcmindist = min(length(tccenter - GetSMTCOptConf(ScreenCoord + float2(+1,+1) * rcpRTSize, wpt)), tcmindist);*/
	
	//return tccenter.x;

	float optconf = 1 - tcmindist * SM_ShadowMapSize;

	//optconf *= g_ShadowConfT;

	//return saturate(tcmindist * SM_ShadowMapSize);

	//add approximation of projective error
	if(0)
	{
		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;

		//weaken factor by * 0.5
		optconf = 1 - (1-optconf) * (1 - saturate(dot(Normal, -g_LightDir)) * 0.5) ;

		//return saturate(dot(Normal, -LightDir));
	}
	
	return optconf; // can also be negative, if < 0 then there is oversampling; if surface type does not support negative numbers, it will be clamped
}

technique RenderOptConf_Depth
{
    pass P0
    {      
		CullMode = NONE;
		ZEnable = false;
		AlphaBlendEnable = false;
		AlphaTestEnable = false;

        VertexShader = null;
        PixelShader  = compile ps_2_b PSOptConf(WPT_DEPTH);
    }
}

technique RenderOptConf_LinearDepth
{
    pass P0
    {      
		CullMode = NONE;
		ZEnable = false;
		AlphaBlendEnable = false;
		AlphaTestEnable = false;

        VertexShader = null;
        PixelShader  = compile ps_2_b PSOptConf(WPT_LINEARDEPTH);
    }
}

technique RenderOptConf_World
{
    pass P0
    {      
		CullMode = NONE;
		ZEnable = false;
		AlphaBlendEnable = false;
		AlphaTestEnable = false;

        VertexShader = null;
        PixelShader  = compile ps_2_b PSOptConf(WPT_WORLDPOS);
    }
}