void main_vertex
(
   float4 position : POSITION,
   out float4 oPosition : POSITION,
   uniform float4x4 modelViewProj,

   float2 tex : TEXCOORD,
   out float2 oTex : TEXCOORD
)
{
   oPosition = mul(modelViewProj, position);
   oTex = tex;
}

struct input
{
   float2 video_size;
   float2 texture_size;
   float2 output_size;
};

float4 main_fragment(uniform sampler2D tex : TEXUNIT0, float2 coords : TEXCOORD0, uniform input IN) : COLOR
{
   float2 texelSize = 1.0 / IN.texture_size;

   float2 range = 0.5 / IN.output_size;

   float left   = coords.x - range.x;
   float top    = coords.y + range.y;
   float right  = coords.x + range.x;
   float bottom = coords.y - range.y;

   float3 topLeftColor     = tex2D(tex, (floor(float2(left, top)     / texelSize) + 0.5) * texelSize).rgb;
   float3 bottomRightColor = tex2D(tex, (floor(float2(right, bottom) / texelSize) + 0.5) * texelSize).rgb;
   float3 bottomLeftColor  = tex2D(tex, (floor(float2(left, bottom)  / texelSize) + 0.5) * texelSize).rgb;
   float3 topRightColor    = tex2D(tex, (floor(float2(right, top)    / texelSize) + 0.5) * texelSize).rgb;

   float2 border = clamp(round(coords / texelSize) * texelSize, float2(left, bottom), float2(right, top));

   float totalArea = 4.0 * range.x * range.y;

   float3 averageColor;
   averageColor  = ((border.x - left)  * (top - border.y)    / totalArea) * topLeftColor;
   averageColor += ((right - border.x) * (border.y - bottom) / totalArea) * bottomRightColor;
   averageColor += ((border.x - left)  * (border.y - bottom) / totalArea) * bottomLeftColor;
   averageColor += ((right - border.x) * (top - border.y)    / totalArea) * topRightColor;

   return float4(averageColor, 1.0);
}
