
struct VsOutput
{
  float4 pos: POSITION;
  float2 tc : TEXCOORD0;
};

float4 ofs   : register(c16);
float4 texsz : register(c17);

VsOutput vsh(float2 pos : POSITION)
{
  VsOutput O;
  float2 p=pos*ofs.xy+ofs.zw;
  O.pos=float4(p, 1, 1);
  O.tc=p*texsz.xy+texsz.zw;
  return O;
}


sampler hmap       : register(s0);

float4 pixelOfs    : register(c0);


float4 psh(VsOutput I) : COLOR
{
  #define SAMPLE(DX, DZ) tex2D(hmap, I.tc+pixelOfs.xy*float2(DX, DZ)).r

  float ch=SAMPLE( 0,  0);

  float4 maxh;

  float4 l;

  // nearest samples
  {
    float d2=1;

    float h0=SAMPLE(+1,  0);
    float h1=SAMPLE( 0, +1);
    float h2=SAMPLE(-1,  0);
    float h3=SAMPLE( 0, -1);

    float4 h=float4(h0, h1, h2, h3)-ch;
    maxh=h;
    l=h*rsqrt(h*h+d2);
  }

  //*
  {
    float dd2=2;

    float h4=SAMPLE(+1, +1);
    float h5=SAMPLE(-1, +1);
    float h6=SAMPLE(-1, -1);
    float h7=SAMPLE(+1, -1);

    float4 hd=(float4(h4, h5, h6, h7)+float4(h7, h4, h5, h6))*0.5f-ch;
    maxh=max(maxh, hd);
    float4 ad=hd*rsqrt(hd*hd+dd2);

    //l=max(l, ad);
    l=lerp(l, ad, 0.5);
  }
  //*/

  #if QUALITY>0

    #if QUALITY==1
      static const int U_SAMPLES=7;
      static const int V_SAMPLES=16;
      static const float RANGE=30;
    #else
      static const int U_SAMPLES=15;
      static const int V_SAMPLES=32;
      static const float RANGE=60;
    #endif

    float4 aper=0;

    for (int ui=1; ui<=U_SAMPLES; ++ui)
    {
      float uf=ui*(2.0/(U_SAMPLES+1))-1.0;
      float uf2=uf*uf;

      float4 rayAper=-1;

      for (int vi=0; vi<V_SAMPLES; ++vi)
      {
        float v=vi*(1.0/V_SAMPLES);
        v=v*v;
        v=v*(RANGE-2)+2;
        //v=v*RANGE;

        float u=uf*v;
        float d2=v*v*(1+uf2);

        float h0=SAMPLE(+v, +u);
        float h1=SAMPLE(+u, +v);
        float h2=SAMPLE(-v, -u);
        float h3=SAMPLE(-u, -v);

        float4 h=float4(h0, h1, h2, h3)-ch;
        maxh=max(maxh, h);
        float4 c=h*rsqrt(h*h+d2);

        rayAper=max(rayAper, c);
      }

      aper+=rayAper;
      //l=max(l, rayAper);
    }

    l=max(l, aper*(1.0/U_SAMPLES));
  #endif

  // calc circular aperture
  float4 H=1-l;
  float ca=1-dot(H, 0.25);

  float4 my=1-H*0.5;
  float4 mh=sqrt(1-my*my)*H;

  float4 av=float4(mh.x-mh.z, dot(my, H), mh.y-mh.w, 0);
  av=float4(normalize(av.xyz), ca);

  av=av*0.5+0.5;
  av.y=max(max(maxh.x, maxh.y), max(maxh.z, maxh.w))/25;

  return av;

  #undef SAMPLE
}
