float4x4 viewProjMatrix : register (c0);
float4x4 worldMatrix : register (c4);
float4 worldEye : register (c8);
float4 fogData : register (c9);
float4 dirLight : register (c14);
float4x4 viewMatrix : register (c16);
float4x4 invViewMatrix : register (c20);

int4 numOmniLight : register (i0); // (count, init, stride, 0)
float4 omniPosRad[64]   : register (c72);
float4 omniRGBDelta[64] : register (c136);


struct VS_OUTPUT
{
   float4 Pos    : POSITION;
   float4 BodyShadow : COLOR0;
#ifdef OMNISCALE
   float4 Omni   : COLOR1;
#endif
   float  Fog    : FOG;
   float4 Tex    : TEXCOORD0; // base=xy, spec=zw
 
   float3 Normal : TEXCOORD1; // normal vector
   float3 Light  : TEXCOORD2; // tangent space light
   float3 EyeVec : TEXCOORD3; // tangent space eye vec
};

 VS_OUTPUT MAINFUNCTION (float4 inPos : POSITION, float4 inNorm : NORMAL, float4 inColor : COLOR0, float2 inTex : TEXCOORD0, float2 inSpec : TEXCOORD1)
{
  VS_OUTPUT Out;
  
  // Transform vertex position into view space:
  Out.Pos = mul (viewProjMatrix, inPos);
  float3 worldPos = mul (worldMatrix, inPos);

  Out.Light = dirLight;
  Out.EyeVec = worldPos - invViewMatrix[3];
  
  float3 worldNorm = mul (worldMatrix, inNorm.xyz);
  float3 eyeVec = (worldEye + worldPos.xyz);

  Out.Fog = (fogData[1] - (length (eyeVec.xyz) * fogData[0]));

#ifdef OMNISCALE
  // Compute omnilights
  Out.Omni = float4(0,0,0,0);
  for (int i=0; i<numOmniLight.x; i++)
  {
    float intens;
    float3 omniToVert = omniPosRad[i].xyz - worldPos.xyz;
    float mag = dot (omniToVert.xyz, omniToVert.xyz);
    // check if vert in range
    if ( mag < omniPosRad[i].w) // using square distances
      if ((intens = dot (worldNorm, normalize (omniToVert))) > 0) // check backface
        Out.Omni.rgb += (sqrt(intens) * omniRGBDelta[i].rgb * (1.0F - (sqrt(mag) * omniRGBDelta[i].w)));
  }
#endif

  float4 sideVec = float4(0.0, 0.0, 0.0, 0.0);
  if (inPos.x > 0.0)
  {
    sideVec.x = 1.0;
  }
  else
  {
    sideVec.x = -1.0;
  }
#ifdef LEFTTYRE
  sideVec.x = 1.0;
#endif
#ifdef RIGHTTYRE
  sideVec.x = -1.0;
#endif
  sideVec.xyz = mul(worldMatrix, sideVec.xyz);

  float diffuseStrength = max(dot(worldNorm.xyz, sideVec.xyz) * 0.75 + 0.25, 0.0);
  float3 cubeCoord;
  cubeCoord = normalize(reflect(worldPos - invViewMatrix[3], worldNorm.xyz));
  float reflectStrength = pow(max(dot(cubeCoord.xyz, sideVec.xyz) * 0.9 + 0.1, 0.0), 0.4);
  Out.BodyShadow.x = diffuseStrength;
  Out.BodyShadow.y = reflectStrength;
  Out.BodyShadow.z = 0.0;
  Out.BodyShadow.w = 0.0;

  // Propagate texture coordinates:
  Out.Tex.xy = inTex;
  Out.Tex.zw = inSpec;
  Out.Normal = worldNorm;

  return (Out);
}

