#include "common.sh"


struct VsOutput
{
  float4 pos  : POSITION;
  float2 tc   : TEXCOORD0;
  float3 wvec : TEXCOORD1;
  float4 tc2  : TEXCOORD2;
};


float4 texsz : register(c16);
float4 viewx : register(c17);
float4 viewy : register(c18);
float4 viewz : register(c19);
float4 texofs : register(c20);


VsOutput vsh(float2 pos: POSITION)
{
  VsOutput O;
  O.pos=float4(pos, 1, 1);
  O.tc.xy=pos.xy*texsz.xy+texsz.zw;
  O.tc2.xy=pos.xy*float2(0.5, -0.5)-texofs.xy*0.5+texsz.zw;
  O.tc2.zw=O.tc2.xy+texofs.xy;
  O.wvec=pos.x*viewx.xyz+pos.y*viewy.xyz+viewz.xyz;
  return O;
}


float3 viewPos : register(c16);
float4 lowResScale : register(c17);

sampler aperTex : register(s0);
sampler hmapTex : register(s1);

sampler lowResDepthTex : register(s12);
sampler lowResNormTex  : register(s13);


float3 calcLight(float3 norm, float4 aper, float4 shadow)
{
  // sky
  float3 light=(1-saturate(aper.w))*
    calc_sky_light(normalize(norm.xyz+aper.xyz*2))*shadow.x;

  // sun
  float c=dot(aper.xyz, sun_dir.xyz);
  float ca=aper.w, cb=sun_dir.w;

  float cc=ca*cb, ss=sqrt((1-ca*ca)*(1-cb*cb));
  float maxc=cc+ss;
  float f=smoothstep(cc-ss, maxc, c)*(1-maxc);

  float3 dir=normalize(sun_dir.xyz*(1+sun_dir.w)+aper.xyz*(1+aper.w));
  f*=saturate(dot(norm.xyz, dir.xyz));

  light+=sunL.rgb*f*shadow.y;
  return light;
}


float4 psh(VsOutput I) : COLOR
{
  UNPACK_GBUF(I.tc.xy)

  // upsample shadows
  float lrd00=unpack_from_8x3(tex2D(lowResDepthTex, I.tc2.xy).xyz);
  float lrd10=unpack_from_8x3(tex2D(lowResDepthTex, I.tc2.zy).xyz);
  float lrd01=unpack_from_8x3(tex2D(lowResDepthTex, I.tc2.xw).xyz);
  float lrd11=unpack_from_8x3(tex2D(lowResDepthTex, I.tc2.zw).xyz);

  float4 sh00=tex2D(light_tex, I.tc2.xy);
  float4 sh10=tex2D(light_tex, I.tc2.zy);
  float4 sh01=tex2D(light_tex, I.tc2.xw);
  float4 sh11=tex2D(light_tex, I.tc2.zw);

  float4 shadow;
  float2 bc=frac(I.tc2.xy*lowResScale.xy+lowResScale.zw);

  float thr=0.00005;
  float eps=0.1;

  // float lrd=lerp(
  //   lerp(lrd00, lrd10, bc.x),
  //   lerp(lrd01, lrd11, bc.x),
  //   bc.y);

  // if (abs(lrd-depth)<thr)
  // {
  //   shadow=lerp(
  //     lerp(sh00, sh10, bc.x),
  //     lerp(sh01, sh11, bc.x),
  //     bc.y);
  //   // shadow=0;
  // }
  // else
  {
    lrd00=abs(lrd00-depth);
    lrd10=abs(lrd10-depth);
    lrd01=abs(lrd01-depth);
    lrd11=abs(lrd11-depth);

    float3 lrn00=normalize(tex2D(lowResNormTex, I.tc2.xy).xyz*2-1);
    float3 lrn10=normalize(tex2D(lowResNormTex, I.tc2.zy).xyz*2-1);
    float3 lrn01=normalize(tex2D(lowResNormTex, I.tc2.xw).xyz*2-1);
    float3 lrn11=normalize(tex2D(lowResNormTex, I.tc2.zw).xyz*2-1);

    float w00=(1-bc.x)*(1-bc.y)/(lrd00+eps)*pow(saturate(dot(norm, lrn00)), 32);
    float w10=   bc.x *(1-bc.y)/(lrd10+eps)*pow(saturate(dot(norm, lrn10)), 32);
    float w01=(1-bc.x)*   bc.y /(lrd01+eps)*pow(saturate(dot(norm, lrn01)), 32);
    float w11=   bc.x *   bc.y /(lrd11+eps)*pow(saturate(dot(norm, lrn11)), 32);

    float sumw=w00+w10+w01+w11;

    if (sumw<0.1)
      shadow=(sh00+sh10+sh01+sh11)*0.25;
    else
      shadow=(sh00*w00+sh10*w10+sh01*w01+sh11*w11)/sumw;
  }

  // compute light
  float3 eyeVec=I.wvec*depth;
  float3 pos=eyeVec+viewPos;

  float2 tc=pos.xz*(1.0/HMAP_SIZE)+0.5/HMAP_SIZE;
  float4 aper=tex2D(aperTex, tc);
  aper.xzw=aper.xzw*2-1;
  float maxHeight=aper.y*25;
  aper.y=sqrt(1-dot(aper.xz, aper.xz));
  //aper.xyz=normalize(aper.xyz);

  float surfHt=tex2D(hmapTex, tc).r;
  float t=saturate((pos.y-surfHt)/maxHeight);
  t=(2-t)*t;

  aper=lerp(aper, float4(0, 1, 0, 0), t);
  aper.xyz=normalize(aper.xyz);

  //shadow.x=1;

  float3 light=calcLight(norm.xyz, aper, shadow);

  if (gloss>0) light+=calcLight(-norm.xyz, aper, shadow)*gloss*color*2;

  // specular
  float spec=0;
  //==

  return pack_color(light*0.5, spec);
}
