matrix World;
matrix View;
matrix Projection;

struct vsInput
{
	float4 Pos 	: POSITION;
	float2 Tex 	: TEXCOORD;
};

struct psInput
{
	float4 Pos 		: SV_POSITION;
	float2 Tex 		: TEXCOORD0;
};

SamplerState PointSampler
{
	Filter = MIN_MAG_MIP_POINT;
	AddressU = Clamp;
	AddressV = Clamp;
};

SamplerState LinearSampler
{
	Filter = MIN_MAG_LINEAR_MIP_POINT;
	AddressU = Clamp;
	AddressV = Clamp;
};

//=============================================================================

Texture2D InputTex;
Texture2D BaseEdge;
Texture2D Length;
Texture2D TableTex;

psInput vShader(vsInput input)
{
	psInput output;
	
	output.Pos = mul(input.Pos, World);
	output.Pos = mul(output.Pos, View);
	output.Pos = mul(output.Pos, Projection);	
	output.Tex = input.Tex;

	return output;
}

//=============================================================================

float2 pxsize = float2(1.f  / 1280.f, 1.f / 720.f);
float2 right = float2(1.f / 1280.f, 0.f);
float2 up = float2(0.f, 1.f / 720.f);
float2 coeff = float2(1.f / 128.f, 1.f / 128.f);

float4 getWeightsAlt(psInput input)
{
	float4 alpha = 0.f;
	float4 cline = Length.Sample(PointSampler, input.Tex) * 255.f;

	{
		float size = cline.r + cline.g;
		float dx = (cline.r < cline.g) ? -(cline.r + 1.f) : cline.g;

		alpha.g += TableTex.Sample(LinearSampler, float2(min(cline.r, cline.g), size) * coeff).r;
		alpha.g *= BaseEdge.Sample(PointSampler, input.Tex + dx * right).r * (size > 0.f);
	}
	
	{
		float size = cline.b + cline.a;
		float dx = (cline.b < cline.a) ? (cline.b + 1.f) : -cline.a;

		alpha.b += TableTex.Sample(LinearSampler, float2(min(cline.b, cline.a), size) * coeff).r;
		alpha.b *= BaseEdge.Sample(PointSampler, input.Tex + dx * up).g * (size > 0.f);
	}
	
	float2 coord = input.Tex + up;
	float4 center = BaseEdge.Sample(PointSampler, coord);
	{
		float2 hline = Length.Sample(PointSampler, coord).rg;
		hline *= 255.f;

		float size = hline.r + hline.g;
		float dx = (hline.r < hline.g) ? -(hline.r + 1.f) : hline.g;

		alpha.r += TableTex.Sample(LinearSampler, float2(min(hline.r, hline.g), size) * coeff).r;
		alpha.r *= BaseEdge.Sample(PointSampler, input.Tex + dx * right).r * (center.g > 0.f);
	}

	coord = input.Tex - right;
	center = BaseEdge.Sample(PointSampler, coord);
	{
		float2 vline = Length.Sample(PointSampler, coord).ba;
		vline *= 255.f;

		float size = vline.r + vline.g;
		float dx = (vline.r < vline.g) ? (vline.r + 1.f) : -vline.g;

		alpha.a += TableTex.Sample(LinearSampler, float2(min(vline.r, vline.g), size) * coeff).r;
		alpha.a *= BaseEdge.Sample(PointSampler, input.Tex + dx * up).g * (center.r > 0.f);
	}

	float maxv = max(max(alpha.r, alpha.g), max(alpha.b, alpha.a));
	alpha = (alpha == maxv) * alpha;

	return alpha;
}

float4 EdgeBlendPShader(psInput input) : SV_Target
{
	float4 alpha = getWeightsAlt(input);
	float2 tex = input.Tex + (float2(alpha.b - alpha.a, alpha.r - alpha.g) * pxsize);

	return InputTex.Sample(LinearSampler, tex);
}

//=============================================================================
DepthStencilState NoDepth
{
	DepthEnable = false;

	StencilEnable = true;
	StencilReadMask  = 0xFFFFFFFF;
	StencilWriteMask = 0;

    	BackFaceStencilFunc = Equal;
	BackFaceStencilPass = Keep;
};

technique10 Default
{
	pass P0
	{
		SetVertexShader(CompileShader(vs_4_0, vShader()));
		SetGeometryShader(NULL);
		SetPixelShader(CompileShader(ps_4_0, EdgeBlendPShader()));
		SetDepthStencilState(NoDepth, 1);
	}
}
//=============================================================================