varying vec4 ViewPos;
varying vec3 normal;
varying vec3 tangent;
varying vec3 binormal;
//varying vec3 up;
varying vec3 WorldNormal;

uniform sampler2D Color0; // celshadey
uniform sampler2D Color1; // ground
uniform sampler2D Height; // mix
uniform sampler2D Normal; // normal map
//uniform sampler2D Height;


//////////////////////////////////////////////////////////////////////////
// method to pack a f32 into an rgba8 from gamedev.net forums
//
// http://www.gamedev.net/community/forums/topic.asp?topic_id=463075
//
//////////////////////////////////////////////////////////////////////////

const vec4 bitSh  = vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);
const vec4 bitMsk = vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);

const float scale = 0.02;
const float bias  = -0.02;
void main()
{
  // noise effect
  /*
  vec2 t = WorldNormal.xz;		
	float x=t.x*t.y*123456.0 * 0.001;
	x=mod(x,13.0) * mod(x,123.0);	
	float dx = mod(x,0.01);
	float dy = mod(x,0.012);
	t = vec2( dx,dy );
  */

  vec4 color, color1, norm, packpos;
  vec3 e = -normalize( ViewPos.xyz );

  // want eye linear depth ////////////////////////////////////////////////////////////////////////
  float pos = 1.0 - ViewPos.z / 10000.0;
 
  // scale blending
  vec3 Nscreen = abs( normalize(WorldNormal).xyz ); 
  Nscreen = ( Nscreen - .2 ) * 7.0;
  Nscreen = max( Nscreen, 0.0 );
  Nscreen = Nscreen / ( Nscreen.x + Nscreen.y + Nscreen.z );

  // normal ///////////////////////////////////////////////////////////////////////////////////////
  vec3 h;
  h.x = 1.0 - texture2D( Height, gl_TexCoord[1].st ).x * Nscreen.x;
  h.y = 1.0 - texture2D( Height, gl_TexCoord[2].st ).x * Nscreen.y;
  h.z = 1.0 - texture2D( Height, gl_TexCoord[3].st ).x * Nscreen.z;
  h *= scale;
  h += bias;
  
  vec2 offsetx = h.x * e.yz;//vec2( 0.0 );//
  vec2 offsety = h.y * e.xz;//vec2( 0.0 );//
  vec2 offsetz = h.z * e.yx;//vec2( 0.0 );//

  vec2 xprojscale = 0.112233 * gl_TexCoord[1].st;
  vec2 yprojscale = 0.112233 * gl_TexCoord[2].st;
  vec2 zprojscale = 0.112233 * gl_TexCoord[3].st;

  vec3 tangentspacenormal = texture2D( Normal, xprojscale        + offsetx/**/ ).xyz * Nscreen.x +
                            texture2D( Normal, yprojscale        + offsety/**/ ).xyz * Nscreen.y +
                            texture2D( Normal, zprojscale        + offsetz/**/ ).xyz * Nscreen.z +
                            texture2D( Normal, gl_TexCoord[1].st + offsetx/**/ ).xyz * Nscreen.x +
                            texture2D( Normal, gl_TexCoord[2].st + offsety/**/ ).xyz * Nscreen.y +
                            texture2D( Normal, gl_TexCoord[3].st + offsetz/**/ ).xyz * Nscreen.z;
  
  // tangentspace scaled... magic number here
  tangentspacenormal = tangentspacenormal * 0.86 - 1.0;
  
  /* normalized ver */
  vec3 t1 = normalize( tangent );
  vec3 b1 = normalize( binormal );
  vec3 n1 = normalize( normal );
  norm.x = dot( vec3( t1.x, b1.x, n1.x ), tangentspacenormal );
  norm.y = dot( vec3( t1.y, b1.y, n1.y ), tangentspacenormal );
  norm.z = dot( vec3( t1.z, b1.z, n1.z ), tangentspacenormal );
  norm.w = 1.0;

  // blend projected textures
  float grasschance = WorldNormal.y + ( h.x + h.y + h.z );// + t.x - t.y;
  grasschance -= 0.3;
  grasschance = clamp( grasschance, 0.0, 1.0 );


  color = texture2D( Color1, xprojscale + offsetx ) * Nscreen.x +
          texture2D( Color1, zprojscale + offsetz ) * Nscreen.z;
  
  vec3 gcolor = ( 1.0 - grasschance ) * texture2D( Color1, yprojscale + offsety ).rgb + 
                grasschance           * vec3( grasschance, 1.0, 0.0 );

  color.rgb += gcolor;

  float colormod = mix( 1.0, (h.x + h.y + h.z)/scale, ViewPos.z / 2000.0 );
  color.rgb *= colormod;
  /**/
  // weird lighting thing
  vec2 texCoord;
  //vec3 e = -normalize( ViewPos.xyz );
  // v coord is normal dot up for a lighting like effect
  //texCoord.y = max( dot( norm.xyz, up ), 0.0 ) * 0.45 + 0.5;
  // u coord is normal dot eye for cel-shading like effect
  texCoord.x = abs( dot( norm.xyz, e ) ) * 0.81 + 0.19;//max( dot( norm.xyz, e ), 0.0 ) * 0.81 + 0.19;//0.9+ 0.1;
  texCoord.y = 1.0;//texCoord.x * 0.45 + 0.5;//
 
  // modulate with texture color
  color *= texture2D( Color0, texCoord );
  color.a = 1.0;
 
  // pack //////////////////////////////////////////////////////////////////////////////////////////
  packpos = fract( pos * bitSh );
  packpos -= packpos.xxyz * bitMsk;
  
  // write output //////////////////////////////////////////////////////////////////////////////////
  gl_FragData[0] = color;
  gl_FragData[1] = norm * .5 + .5;
  gl_FragData[2] = packpos;
}