#include "common.effect"

//------------------------------------------------------------------------------
// Defines
//------------------------------------------------------------------------------
#define MAX_BLUR_SIZE 128

//------------------------------------------------------------------------------
// Technique: Directional / Area
//------------------------------------------------------------------------------
float4 PSBlur1D(VertexInformation vtx) : TARGET {
	float4 final = pImage.Sample(LinearClampSampler, vtx.uv);

	// Loop unrolling is only possible with a fixed known maximum.
	// Some compilers may unroll up to x iterations, but most will not.
	for (int n = 1; n <= MAX_BLUR_SIZE; n++) {
		float2 nstep = (pImageTexel * pStepScale) * n;
		final += pImage.Sample(LinearClampSampler, vtx.uv + nstep);
		final += pImage.Sample(LinearClampSampler, vtx.uv - nstep);

		if (n >= pSize) {
			break;
		}
	}

	final *= pSizeInverseMul;
	return final;
}

technique Draw {
	pass {
		vertex_shader = VSDefault(vtx);
		pixel_shader  = PSBlur1D(vtx);
	}
}

//------------------------------------------------------------------------------
// Technique: Rotate
//------------------------------------------------------------------------------
float4 PSRotate(VertexInformation vtx) : TARGET {
	float4 final = pImage.Sample(LinearClampSampler, vtx.uv);
	
	float angstep = pAngle * pStepScale.x;

	// Loop unrolling is only possible with a fixed known maximum.
	// Some compilers may unroll up to x iterations, but most will not.
	for (int n = 1; n <= MAX_BLUR_SIZE; n++) {
		final += pImage.Sample(LinearClampSampler, rotateAround(vtx.uv, pCenter, angstep * n));
		final += pImage.Sample(LinearClampSampler, rotateAround(vtx.uv, pCenter, angstep * -n));

		if (n >= pSize) {
			break;
		}
	}
	
	final *= pSizeInverseMul;
	return final;
}

technique Rotate {
	pass {
		vertex_shader = VSDefault(vtx);
		pixel_shader  = PSRotate(vtx);
	}
}

//------------------------------------------------------------------------------
// Technique: Zoom
//------------------------------------------------------------------------------
float4 PSZoom(VertexInformation vtx) : TARGET {
	float4 final = pImage.Sample(LinearClampSampler, vtx.uv);

	// step is calculated from the direction relative to the center
	float2 dir = normalize(vtx.uv - pCenter) * pStepScale * pImageTexel;
	float dist = distance(vtx.uv, pCenter);

	// Loop unrolling is only possible with a fixed known maximum.
	// Some compilers may unroll up to x iterations, but most will not.
	for (int n = 1; n <= MAX_BLUR_SIZE; n++) {
		final += pImage.Sample(LinearClampSampler, vtx.uv + (dir * n) * dist);
		final += pImage.Sample(LinearClampSampler, vtx.uv + (dir * -n) * dist);

		if (n >= pSize) {
			break;
		}
	}
	
	final *= pSizeInverseMul;
	return final;
}

technique Zoom {
	pass {
		vertex_shader = VSDefault(vtx);
		pixel_shader  = PSZoom(vtx);
	}
}
