DepthStencilState noDepth_DepthStencilState
{
	DepthEnable				= FALSE;
	DepthWriteMask			= ZERO;
};

RasterizerState default_RasterizerState
{
	FillMode				= SOLID;
	FrontCounterClockwise	= TRUE;
	CullMode				= BACK;
};

 SamplerState linear_SamplerState
{
	Filter					= MIN_MAG_MIP_POINT;
	AddressU				= CLAMP;
	AddressV				= CLAMP;
};

 
 // dummy Vertex shader output
 struct VS_QuadOutput
 {
	float4 position : SV_Position;
 };

 // dummy Geometry shader input
struct GS_QuadInput
{
};

// Pixel Shader input, only needs position and texcoord
struct PS_QuadInput
{
	float4 position : SV_Position;
    float2 texCoord : TEXCOORD0;	
};

// Pixel Shader output
struct PS_QuadOutput
{
    float4 color : SV_Target;
};


// The Texture to render
Texture2D screenTexture;
Texture2D depthTexture;
Texture2D blurredTexture;
float4 depthInfo;
float2 gaussSampleOffsets[16];
float4 gaussSampleWeights[16];


VS_QuadOutput VS_Quad()
{
	VS_QuadOutput output;
	output.position = 0;
	return output;
}

[maxvertexcount(4)]
void GS_Quad( point GS_QuadInput inputPoint[1], inout TriangleStream<PS_QuadInput> outputQuad )
{
	PS_QuadInput output;
	
	// z and w are only set once.
	output.position.z = 0.0;
	output.position.w = 1.0;
	
	// vertex 1
	output.position.x = -1.0;
	output.position.y = 1.0;
	output.texCoord.xy = float2(0.0, 0.0);
	outputQuad.Append(output);
	
	// vertex 2
	output.position.x = -1.0;
	output.position.y = -1.0;
	output.texCoord.xy = float2(0.0, 1.0);
	outputQuad.Append(output);
	
	// vertex 3
	output.position.x = 1.0;
	output.position.y = 1.0;
	output.texCoord.xy = float2(1.0, 0.0);
	outputQuad.Append(output);
	
	// vertex 4
	output.position.x = 1.0;
	output.position.y = -1.0;
	output.texCoord.xy = float2(1.0, 1.0);
	outputQuad.Append(output);
	
	outputQuad.RestartStrip();
}

PS_QuadOutput PS_Quad(PS_QuadInput input)
{
	PS_QuadOutput output;
			
	float4 fDepthV = depthTexture.Sample(linear_SamplerState, input.texCoord);;
	float fDepth = fDepthV.x;
	
	float fBlur = 0.0;
	
	if(fDepth < depthInfo.y)
	{
		fBlur = (fDepth - depthInfo.y)/(depthInfo.y-depthInfo.x);
	}
	else
	{
		fBlur = (fDepth - depthInfo.y)/(depthInfo.z-depthInfo.y);
	}
	
	fBlur = saturate(abs(fBlur));
	
	//float fBlur = abs( (fDepth.x - depthInfo.w )/( fDepth.x + depthInfo.w )) / 2;
	
	float4 tempColor1 = screenTexture.Sample(linear_SamplerState, input.texCoord);
	float4 tempColor2 = blurredTexture.Sample(linear_SamplerState, input.texCoord);
	
	output.color = saturate(lerp(tempColor1,tempColor2,fBlur));
	return output;
}

PS_QuadOutput PS_Gauss(PS_QuadInput input)
{
    
    PS_QuadOutput output;
    float4 vColor = 0.0f;
    float2 vSamplePosition;
    
    for( int i = 0; i < 15; i++ )
    {
        // Sample from adjacent points
        vSamplePosition = input.texCoord + gaussSampleOffsets[i];
        vColor = screenTexture.Sample(linear_SamplerState, vSamplePosition);
        
        output.color += gaussSampleWeights[i]*vColor;
    }
    
    return output;
}


technique10 Render
{
    pass P0
    {
        SetVertexShader(CompileShader(vs_4_0, VS_Quad()));
        SetGeometryShader(CompileShader(gs_4_0, GS_Quad()));
        SetPixelShader(CompileShader(ps_4_0, PS_Quad()));
        
        SetDepthStencilState(noDepth_DepthStencilState, 0);
        SetRasterizerState(default_RasterizerState);
    }
}

technique10 Blur
{
    pass P0
    {
        SetVertexShader(CompileShader(vs_4_0, VS_Quad()));
        SetGeometryShader(CompileShader(gs_4_0, GS_Quad()));
        SetPixelShader(CompileShader(ps_4_0, PS_Gauss()));
        
        SetDepthStencilState(noDepth_DepthStencilState, 0);
        SetRasterizerState(default_RasterizerState);
    }
}

