#include "common.sh"


struct VsInput
{
  float4 pos       : POSITION;

  float3 norm      : NORMAL;

  #if !SH_TRIPROJ
    float2 tc        : TEXCOORD0;
  #endif

  #if INST_MORPH
    float3 dpos0     : POSITION1;
    float3 dpos1     : POSITION2;
    float3 dpos2     : POSITION3;
    float3 dnorm0    : NORMAL1;
    float3 dnorm1    : NORMAL2;
    float3 dnorm2    : NORMAL3;

    float4 morph     : POSITION15;
  #endif

  #if INST_SPLINE
    float3 sk0       : POSITION10;
    float3 sk1       : POSITION11;
    float3 sk2       : POSITION12;
    float3 sk3       : POSITION13;
    float3 bn0       : NORMAL10;
    float3 bn1       : NORMAL11;
    float4 c0        : COLOR10;
    float4 c1        : COLOR11;
  #else
    float4 mx        : POSITION11;
    float4 my        : POSITION12;
    float4 mz        : POSITION13;
    float3 instPos   : POSITION10;
    float4 c         : COLOR10;
  #endif
};

struct VsOutput
{
  float4 pos       : POSITION;
  #if LOW_MODE
    float3 norm    : TEXCOORD0;
  #else
    float4 norm    : TEXCOORD0;
  #endif

  #if SH_TRIPROJ
    float3 lpos    : TEXCOORD1;
    float3 lnorm   : TEXCOORD2;
  #else
    float2 tc      : TEXCOORD1;
  #endif

  float4 color     : COLOR0;

  #if LOW_MODE
    float4 fog     : COLOR1;
  #endif
};


VsOutput vsh(VsInput I)
{
  VsOutput O;

  float3x3 tm;

  float3 norm=I.norm*2-1;

  #if INST_SPLINE
    float3 p=I.pos.xyz;
    float4 pos;
    float t=p.z;
    pos.xyz=((I.sk3*t+I.sk2)*t+I.sk1)*t+I.sk0;

    float3 zdir=normalize((I.sk3*3*t+I.sk2*2)*t+I.sk1);
    float3 bn=lerp(I.bn0, I.bn1, t)*2-1;
    float3 ydir=normalize(cross(bn, zdir));
    float3 xdir=cross(ydir, zdir);

    pos.xyz+=xdir*p.x+ydir*p.y;
    pos.w=1;

    tm[0]=xdir;
    tm[1]=ydir;
    tm[2]=zdir;

    float4 color=lerp(I.c0, I.c1, t);
  #else
    tm[0]=I.mx.xyz*4-2;
    tm[1]=I.my.xyz*4-2;
    tm[2]=I.mz.xyz*4-2;

    float3 lp=I.pos.xyz;

    #if INST_MORPH
      float4 morph=I.morph;

      const float maxval=1;
      lp+=(I.dpos0*2*maxval-maxval)*morph.x;
      lp+=(I.dpos1*2*maxval-maxval)*morph.y;
      lp+=(I.dpos2*2*maxval-maxval)*morph.z;

      norm+=(I.dnorm0*4-2)*morph.x;
      norm+=(I.dnorm1*4-2)*morph.y;
      norm+=(I.dnorm2*4-2)*morph.z;

      norm=normalize(norm);
    #endif

    #if SH_TRIPROJ
      O.lpos=lp*0.25;
      O.lnorm=norm;
    #endif

    float4 pos=float4(mul(lp, tm)+I.instPos, 1);

    float4 color=I.c;
  #endif

  O.pos=mul(globtm, pos);

  O.norm.xyz=mul(norm, tm);

  #if LOW_MODE
    O.fog=vs_calc_fog_color(pos.xyz);
  #else
    O.norm.w=dot(pos, depth_proj);
  #endif

  #if !SH_TRIPROJ
    O.tc=I.tc;
  #endif

  O.color=color;

  return O;
}


sampler tex : register(s0);


#if LOW_MODE

  float4 psh(VsOutput I
  #if SH_FOLIAGE
      , float faceSign:VFACE
  #endif
    ) : COLOR
  {
    float3 norm=normalize(I.norm);

    #if SH_FOLIAGE
      if (faceSign<0) norm=-norm;

      float4 img=tex2D(tex, I.tc);

      float a=img.a*I.color.a;
      clip(a-0.25);

      float l=img.g;
      float3 color=pow(saturate(I.color.rgb), (1-l)*5+1);

      float3 light=calc_simple_light(norm);
      light+=calc_simple_light(-norm)*color;
    #else
      #if SH_TRIPROJ
        float3 lp=I.lpos;
        float3 ln=normalize(I.lnorm);
        ln*=ln;
        float3 color;
        color =tex2D(tex, lp.zy+float2(0.3, 0.0)).rgb*ln.x;
        color+=tex2D(tex, lp.xz).rgb*ln.y;
        color+=tex2D(tex, lp.xy+float2(0.4, 0.2)).rgb*ln.z;
      #else
        float3 color=tex2D(tex, I.tc).rgb;
      #endif

      float3 light=calc_simple_light(norm);
      light=lerp(light, 1, I.color.a);

      color*=I.color.rgb;
    #endif

    float3 res=light*color;

    // fog
    res=lerp(res, I.fog.rgb, I.fog.a);

    return pack_color(res, 1);
  }

#else

  GBuffer psh(VsOutput I
  #if SH_FOLIAGE
      , float faceSign:VFACE
  #endif
    )
  {
    float3 norm=normalize(I.norm.xyz);
    float depth=I.norm.w;

    #if SH_FOLIAGE
      if (faceSign<0) norm=-norm;

      float4 img=tex2D(tex, I.tc);

      float a=img.a*I.color.a;
      clip(a-0.25);

      float l=img.g;
      // float3 color=lerp(I.color.rgb, 1, l)*I.color.rgb*l;
      float3 color=pow(saturate(I.color.rgb), (1-l)*5+1);

      float glow=0, gloss=1;
    #else
      #if SH_TRIPROJ
        float3 lp=I.lpos;
        float3 ln=normalize(I.lnorm);
        ln*=ln;
        float3 color;
        color =tex2D(tex, lp.zy+float2(0.3, 0.0)).rgb*ln.x;
        color+=tex2D(tex, lp.xz).rgb*ln.y;
        color+=tex2D(tex, lp.xy+float2(0.4, 0.2)).rgb*ln.z;
      #else
        float3 color=tex2D(tex, I.tc).rgb;
      #endif

      color*=I.color.rgb;
      float glow=I.color.a;
      float gloss=0;
    #endif

    return pack_gbuf(depth, norm, color, glow, gloss);
  }

#endif
