/*******************************************************************
*	PPEdgeDetection.fx
*	Author - Pongthep Charnchaichujit
*	Created on - ?
*
*   All content © 2007 - 2008 DigiPen (USA) Corporation, all rights reserved.
*******************************************************************/
// Constants
float4x4 Projection;
texture InputTex;
texture NormalDepthTex;
float2 TexelSize;

//int hack;

// Settings controlling the edge detection filter.
float EdgeIntensity = 1;

// How sensitive should the edge detection be to tiny variations in the input data?
// Smaller settings will make it pick up more subtle edges, while larger values get
// rid of unwanted noise.
float NormalThreshold = 0.5;
float DepthThreshold = 0.025;

// How dark should the edges get in response to changes in the input data?
float NormalSensitivity = 1;
float DepthSensitivity = 100;

sampler InputSampler = sampler_state
{
    texture = <InputTex>;
    AddressU  = CLAMP;
    AddressV  = CLAMP;
    MIPFILTER = LINEAR;
    MINFILTER = LINEAR;
    MAGFILTER = LINEAR;
};

sampler NormalDepthSampler = sampler_state
{
    texture = <NormalDepthTex>;
    AddressU  = CLAMP;
    AddressV  = CLAMP;
    MIPFILTER = POINT;
    MINFILTER = POINT;
    MAGFILTER = POINT;
};

struct VS_IN {
	float4 pos : POSITION;
	float2 tex : TEXCOORD0;
};

struct PS_IN {
	float4 pos : POSITION;
	float2 tex : TEXCOORD0;
};

// PostProcess Vertex Shader
PS_IN PostProcessVertexShader(VS_IN input)
{
	PS_IN output;
	
	output.pos = mul(input.pos, Projection);
	output.tex = input.tex;
	
	return output;
}
#if 1
float4 UnpackNormal(float4 color, out float id)
{
    id = color.z;
    
    float2 n = ( color.xy*2 - 1 );
    //color.xyz = color.xy
    

    color.xy = n;
    color.z = 1.0f - sqrt(n.x*n.x + n.y*n.y);
    

    return color;
}
#else
#define UnpackNormal( x, i ) x
#endif

// Blur PostProcess Pixel Shader
float4 EdgeDetectPixelShader(PS_IN input): COLOR
{
	float4 color = tex2D(InputSampler, input.tex);

    //int id5;
    //float4 n5 = UnpackNormal( tex2D(NormalDepthSampler, input.tex), id5 );
    //return id5/255.0f;

    float id0, id1, id2, id3;
	float4 n1 = UnpackNormal( tex2D(NormalDepthSampler, input.tex + float2(-1, -1) * TexelSize), id0 );
	float4 n2 = UnpackNormal( tex2D(NormalDepthSampler, input.tex + float2( 1,  1) * TexelSize), id1 );
	float4 n3 = UnpackNormal( tex2D(NormalDepthSampler, input.tex + float2(-1,  1) * TexelSize), id2 );
	float4 n4 = UnpackNormal( tex2D(NormalDepthSampler, input.tex + float2( 1, -1) * TexelSize), id3 );

	// Work out how much the normal and depth values are changing.
	float4 diagonalDelta = abs(n1 - n2) + abs(n3 - n4);

	float normalDelta = dot(diagonalDelta.xyz, 1);
	float depthDelta = diagonalDelta.w;

	// Filter out very small changes, in order to produce nice clean results.
	normalDelta = saturate((normalDelta - NormalThreshold) * NormalSensitivity);
	depthDelta = saturate((depthDelta - DepthThreshold) * DepthSensitivity);

    float not_same_object = 1.0f;
    if(id0 == id1) not_same_object = 0.0f;
    if(id2 == id3) not_same_object = 0.0f;
    //else if(id0 == id3) not_same_object = 0.0f;
    //if(id0==0 || id1==0 || id2==0 || id3==0) not_same_object = 1.0f;
    //if(!all(float4(id0, id1, id2, id3))) not_same_object = 1.0f;

	// Does this pixel lie on an edge?
	float edgeAmount = saturate(normalDelta + depthDelta*not_same_object) * EdgeIntensity;

	// Apply the edge detection result to the main scene color.
	
	//if (hack == 1)
	//	return tex2D(NormalDepthSampler, input.tex);
	//if (hack == 2)
	//	return tex2D(InputSampler, input.tex);
		
	return float4(color.xyz * (1 - edgeAmount), 1);
}

// Edge Detect Technique
technique EdgeDetect
{
	pass P0
	{
		VertexShader = compile vs_2_a PostProcessVertexShader();
		PixelShader = compile ps_2_a EdgeDetectPixelShader();
		ZEnable = false;
		ZWriteEnable = false;
		CullMode = NONE;
	}
}
