uniform sampler3D tex3D;
uniform bool specialLighting;
uniform bool beach;

uniform float waterLevel;
uniform bool withFog;
uniform bool withTextures;

varying vec3 normal;
varying vec3 vertex;

varying vec3 glVertex;

void main()
{	
	vec3 lightVec = gl_LightSource[0].position.xyz + vec3(0, 5, -5) - vertex;
	lightVec = normalize(lightVec);

   if(withTextures)
   {
      gl_FragColor = vec4(texture3D(tex3D, vec3(glVertex.xz/25.0, smoothstep(0.0, 0.9, (glVertex.y-waterLevel)/6.0+0.27))).rgb, 0);

      if(specialLighting)  // some lighting adopted from http://www.yaldex.com/open-gl/ch11lev1sec4.html
      {
	      vec3 specialLightVec =gl_LightSource[0].position.xyz + vec3(0.5, 2, 0) - vertex;
         specialLightVec = normalize(specialLightVec);

         float SpecularFactor = 0.65;
         vec3 baseColor = beach ? vec3(0.65, 0.62, 0.4) : vec3(0.05, 0.2, 0.5) ;
         vec3 litColor = baseColor * max(dot(normal, specialLightVec), 0.0);
         vec3 reflectDir = reflect(specialLightVec, normal);

         float spec = max(dot(normalize(-vertex), reflectDir), 0.0);
         spec = pow(spec, 8.0);
         spec *= SpecularFactor;
         litColor = min(litColor + spec, vec3(1.0));

         gl_FragColor.rgb = mix(gl_FragColor.rgb, litColor, 0.1);
         gl_FragColor.rgb += litColor/1.75;

      }
   }
   else
   {

      vec4 color = vec4(0);//gl_Color;
      if (glVertex.y < waterLevel + 0.2)
         color = vec4(0.0,
         clamp(-glVertex.y / 2.0, 0.0, 1.0),
         1.0,
         1.0);
      else color = vec4(clamp(glVertex.y / 2.0, 0.0, 1.0),
         1.0,
         glVertex.y / 8.0,
         1.0);	



      //float lightDistance = length(lightDirection);
      //lightDirection = normalize(lightDirection);
      //lightDistance = max(lightDistance, 0.0);
      //lightDistance = 1 / lightDistance;

      //vec3 reflection = normalize(-reflect(lightDirection, normal));  
      //vec3 eye = normalize(-vertex);


      vec4 mountainColor = vec4(0.98, 0.86, 0.57, 0);
      vec4 grassColor = vec4(0.41, 0.6, 0.3, 0);
      vec4 beachColor = vec4(0.68, 0.56, 0.17, 0);

      gl_FragColor = (mountainColor * color.r
         + grassColor * color.g
         + beachColor * color.b
         + beachColor * clamp(waterLevel - vertex.y, 0.3, 0.7) * 0.3
         + grassColor * (0.5 - color.r) * (0.5 - color.g)
         );
	  gl_FragColor *= clamp(dot(normal, lightVec), 0.0, 1.0);

	  vec3 R = normalize(reflect(-lightVec, normal));
	  float cosTheta = max(0.0, dot(R, normalize(-vertex.xyz)));

	  gl_FragColor += vec4(0.5)*pow(cosTheta, 6.0);

   }

   if(withFog)
   {
      const float LOG2 = 1.442695;
      float z = gl_FragCoord.z / gl_FragCoord.w;
      float density = 0.1;
      float fogFactor = exp2( -density * density * 
         z * 
         z * 
         LOG2 );
      fogFactor = clamp(fogFactor, 0.0, 1.0);

      gl_FragColor = mix(vec4(0.80, 0.83, 0.96, 1.0), gl_FragColor, fogFactor );
   }

   gl_FragColor.a = 0.0;

//	 +	vec4(0.1f, 0.1f, 0.1f, 0.3f);
//	 +	vec4(0.2f, 0.2f, 0.2f, 0.3f) * clamp(dot(normal, lightDirection), 0.0, 1.0) * lightDistance * 0.5;
//	 +  clamp(vec4(1f, 1f, 1f, 0.4f) * pow(dot(reflection, eye), 3.0), 0.0, 1.0) * lightDistance;

}