/* COMPATIBILITY 
   - HLSL compilers
   - Cg   compilers
   - FX11 compilers
*/

/*
   Hyllian's biquad Shader
   
   Copyright (C) 2011-2015 Hyllian/Jararaca - sergiogdb@gmail.com

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#pragma parameter K "Blurring Param" 0.8 0.0 1.0 0.01
#ifdef PARAMETER_UNIFORM
uniform float K;
#else
#define K  0.8
#endif
// END PARAMETERS //

#include "../../compat_includes.inc"
uniform COMPAT_Texture2D(decal) : TEXUNIT0;
uniform float4x4 modelViewProj;

struct out_vertex
{
	float4 position : COMPAT_POS;
	float2 texCoord : TEXCOORD0;
#ifndef HLSL_4
	float4 Color    : COLOR;
#endif
};

out_vertex main_vertex(COMPAT_IN_VERTEX)
{
	out_vertex OUT;
#ifdef HLSL_4
	float4 position = VIN.position;
	float2 texCoord = VIN.texCoord;
#else
	OUT.Color = color;
#endif
	OUT.position = mul(modelViewProj, position);
	OUT.texCoord = texCoord;
	
	return OUT;
}
	
// Calculates the distance between two points
float d(float2 pt1, float2 pt2)
{
  float2 v = pt2 - pt1;
  return sqrt(dot(v,v));
}
     
float3 resampler(float3 x)
{
	float3 res;
	res = (x<=float3(0.5, 0.5, 0.5)) ?  (-2*K*x*x + 0.5*(K+1))  :  ((x<=float3(1.5, 1.5, 1.5))  ?  (K*x*x + (-2*K - 0.5)*x + 0.75*(K+1))  :  float3(0.0, 0.0, 0.0));
	return res;
}
     
float4 biquad(float2 texture_size, float2 texCoord, COMPAT_Texture2D(decal))
{
	float3 color;
	float3x3 weights;

	float2 dx = float2(1.0, 0.0);
	float2 dy = float2(0.0, 1.0);

	float2 pc = texCoord*texture_size;

	float2 tc = (floor(pc)+float2(0.5,0.5));
     
	weights[0] = resampler(float3(d(pc, tc    -dx    -dy), d(pc, tc           -dy), d(pc, tc    +dx    -dy)));
	weights[1] = resampler(float3(d(pc, tc    -dx       ), d(pc, tc              ), d(pc, tc    +dx       )));
	weights[2] = resampler(float3(d(pc, tc    -dx    +dy), d(pc, tc           +dy), d(pc, tc    +dx    +dy)));

	dx = dx/texture_size;
	dy = dy/texture_size;
	tc = tc/texture_size;
     
	// reading the texels
     
	float3 c00 = COMPAT_SamplePoint(decal, texCoord    -dx    -dy).xyz;
	float3 c10 = COMPAT_SamplePoint(decal, texCoord           -dy).xyz;
	float3 c20 = COMPAT_SamplePoint(decal, texCoord    +dx    -dy).xyz;
	float3 c01 = COMPAT_SamplePoint(decal, texCoord    -dx       ).xyz;
	float3 c11 = COMPAT_SamplePoint(decal, texCoord              ).xyz;
	float3 c21 = COMPAT_SamplePoint(decal, texCoord    +dx       ).xyz;
	float3 c02 = COMPAT_SamplePoint(decal, texCoord    -dx    +dy).xyz;
	float3 c12 = COMPAT_SamplePoint(decal, texCoord           +dy).xyz;
	float3 c22 = COMPAT_SamplePoint(decal, texCoord    +dx    +dy).xyz;

	color = mul(weights[0], float3x3(c00, c10, c20));
	color+= mul(weights[1], float3x3(c01, c11, c21));
	color+= mul(weights[2], float3x3(c02, c12, c22));
	color = color/(dot(mul(weights, float3(1.,1.,1.)), 1));

	// final sum and weight normalization
	return float4(color, 1);
}

float4 main_fragment(COMPAT_IN_FRAGMENT) : COMPAT_Output
{
	return biquad(COMPAT_texture_size, VOUT.texCoord, decal);
}
COMPAT_END