//------------------------------------
float4 sddx;
texture ZTexture : ZBackBuffer;
texture NoiseTexture : NoiseTexture;

sampler2D DepthMap = sampler_state
{
	Texture = <ZTexture>;
	MinFilter = None;
	MagFilter = None;
	MipFilter = None;
	AddressU = Clamp;
	AddressV = Clamp;
	AddressW = Clamp;
};

sampler2D NoiseMap = sampler_state
{
	Texture = <NoiseTexture>;
	MinFilter = None;
	MagFilter = None;
	MipFilter = None;
	AddressU = Clamp;
	AddressV = Clamp;
	AddressW = Clamp;
};

struct vertexOutput {
    float4 HPosition : POSITION;
    float2 UV	: TEXCOORD0;
};

//------------------------------------
float4 PS_Texture(vertexOutput In) : COLOR0
{
	float4 samples[16] =
	{
		float4(0.355512, 	-0.709318, 	-0.102371,	0.0 ),
		float4(0.534186, 	0.71511, 	-0.115167,	0.0 ),
		float4(-0.87866, 	0.157139, 	-0.115167,	0.0 ),
		float4(0.140679, 	-0.475516, 	-0.0639818,	0.0 ),
		float4(-0.0796121, 	0.158842, 	-0.677075,	0.0 ),
		float4(-0.0759516, 	-0.101676, 	-0.483625,	0.0 ),
		float4(0.12493, 	-0.0223423,	-0.483625,	0.0 ),
		float4(-0.0720074, 	0.243395, 	-0.967251,	0.0 ),
		float4(-0.207641, 	0.414286, 	0.187755,	0.0 ),
		float4(-0.277332, 	-0.371262, 	0.187755,	0.0 ),
		float4(0.63864, 	-0.114214, 	0.262857,	0.0 ),
		float4(-0.184051, 	0.622119, 	0.262857,	0.0 ),
		float4(0.110007, 	-0.219486, 	0.435574,	0.0 ),
		float4(0.235085, 	0.314707, 	0.696918,	0.0 ),
		float4(-0.290012, 	0.0518654, 	0.522688,	0.0 ),
		float4(0.0975089, 	-0.329594, 	0.609803,	0.0 )

	};
	
	// Get a random normal from randomization texture, the multiplier (here 100.0) maybe could be selected more wisely?
	float3 randNormal = tex2D( NoiseMap, In.UV * 100.0 ).rgb;
	
	// Unpack normal components to lie between [-1.0, 1.0] range
	randNormal = normalize(randNormal*2-1.0);
	
	float depth = tex2D(DepthMap, In.UV).x;
	float occ = 0.0;
	for (int i = 0; i < 16 ; i += 1 )
	{
		float3 curSample = samples[i].xyz;
		
		// Get a sample by reflecting the constant samples[i].xyz value by a random normal vector for this pixel
		// Neighboring 128 pixels will get different random normal vectors
		curSample = reflect(curSample, randNormal.xyz);
		
		float4 texCoord = float4(In.UV + i * curSample.xy * sddx.xy * 1.0, 0, 0 ); // 0.1
		float newdepth = tex2D(DepthMap, texCoord).x;
		
		float depthDif = (newdepth - depth);
				
		// Blur if samples are less than 10cm apart	and angle between their normals is less than about 10 deg
		float falloff;
		if(newdepth > depth)
		{
			// Quad falloff
			falloff = 1.0 / ( 1 + ( depthDif * depthDif * 1.0 ) ); // 0.01
			
			// Sum
			occ += falloff;
		}
	}
	
	// Average
	float unOcclusion = 1.0 - ( occ / 16.0 );
	
	// Only first component matters
	return float4(unOcclusion, unOcclusion, unOcclusion, 1.0);
}

//-----------------------------------
technique ShowTexture
{
    pass p0 
    {		
		VertexShader = NULL;
		PixelShader = compile ps_3_0 PS_Texture();
		
		// Just use the color
		ColorArg1[0] = Diffuse;
		AlphaArg1[0] = Diffuse;
		ColorOp[0] = SelectArg1;
		AlphaOp[1] = SelectArg1;
		
		AlphaBlendEnable= TRUE;
		SrcBlend  = SRCALPHA;
	    DestBlend = INVSRCALPHA;
		
		CullMode = None;
		ZEnable = true;
		ZFunc = ALWAYS;
		ZWriteEnable = false;
    }
}