// Information from Oolite.
uniform sampler2D      uColorMap; // Diffuse and Specular Intensity map
uniform sampler2D      uFXMap; // Effects & Light Illumination Map
uniform sampler2D      uNormalMap; // Normal Map

const float specExponent = 20.0;
uniform vec4    SpecularRGB;
uniform float   time;
uniform float   uEngineLevel;
uniform float   uHullHeatLevel;

// Information from vertex shader.
varying vec2         vTexCoord;
varying vec3         vEyeVector;   // These are all in tangent space
varying vec3         vLight0Vector;
varying vec3         vLight1Vector;

// redGlow effect
vec4 redGlow(float level)
{
   vec4 result;
   result.rgb = vec3(0.9, 0.4, 0.2) * level * 2.0;
   result.a = 1.0;
   return result;
}

// EngineGlow effect
vec4 EngineGlow(float level)
{
	return vec4(vec3(0.9, 0.6, 0.3) * level, 1.0);
}

void Light(in vec3 lightVector, in vec3 normal, in vec4 lightColor, in vec3 eyeVector,
           in float specExponent, inout vec4 totalDiffuse, inout vec4 totalSpecular)
{
   lightVector = normalize(lightVector);
   vec3 reflection = normalize(-reflect(lightVector, normal));
   
   totalDiffuse += gl_FrontMaterial.diffuse * lightColor * max(dot(normal, lightVector), 0.0);
   totalSpecular += lightColor * pow(max(dot(reflection, eyeVector), 0.0), specExponent);
}

#ifdef OO_REDUCED_COMPLEXITY
#define Pulse(v, ts) ((v) * 0.95)
#else
// Irregular flickering function.
float Pulse(float value, float timeScale)
{
   float t = time * timeScale;   

   float s0 = t;
   s0 -= floor(s0);
   float sum = abs( s0 - 0.5);
   
   float s1 = t * 0.7 - 0.05;
   s1 -= floor(s1);
   sum += abs(s1 - 0.5) - 0.25;
   
   float s2 = t * 1.3 - 0.3;
   s2 -= floor(s2);
   sum += abs(s2 - 0.5) - 0.25;
   
   float s3 = t * 5.09 - 0.6;
   s3 -= floor(s3);
   sum += abs(s3 - 0.5) - 0.25;

   return (sum * 0.1 + 0.9) * value;
}
#endif

// Calculate the contribution of a single light. Ought to be a function, but OS X's GLSlang implementation isn't sufficiently clever.
#define LIGHT(idx, vector) Light(vector, normal, gl_LightSource[idx].diffuse, eyeVector, specExponent, diffuse, specular)

void main()
{
   vec4 diffuse = vec4(0.0), specular = vec4(0);
   vec3 eyeVector = normalize(vEyeVector);
   vec2 texCoord = vTexCoord;

   // Load texture data
   vec4 colorMap = texture2D(uColorMap, texCoord);
   vec4 fxMap = texture2D(uFXMap, texCoord);
   vec3 normal = normalize( texture2D(uNormalMap, texCoord).xyz - 0.5);
   normal = normalize(normal);

	float specAlpha = 1.0 - fxMap.g;
   float specIntensity = 1.0 * specAlpha;

#ifdef OO_LIGHT_0_FIX
   LIGHT(0, normalize(vLight0Vector));
#endif
   LIGHT(1, normalize(vLight1Vector)); // change the 0 to 1 when exporting back to oolite
   
   diffuse += gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
   //diffuse += 1.0 - fxMap.a; // use fxMap alpha channel as an inverse-illumination map

	specular = mix(specular * SpecularRGB, specular * colorMap, 0.0); // Adds the Specular Effect 

	// Add in constant glow (blue on effects map)
	diffuse += fxMap.b;
	
	// Apply part of engine effect before applying colour, so it is partially texture-dependant
	float engineAlpha = fxMap.r;
	vec4 engineEffect = engineAlpha * EngineGlow(min(uEngineLevel, 0.5));
	diffuse += 0.4 * engineEffect;

   
   vec4 color = diffuse * colorMap + specular * specIntensity;

	// Apply rest of engine effect
	color += 0.6 * engineEffect;

   	// ...and heat effects
	//float hullHeat;
	//hullHeat = max(uHullHeatLevel - 0.5, 0.0) * 2.0;
	//hullHeat = Pulse(hullHeat * hullHeat, 0.1);
	//color += redGlow(hullHeat);

   color.a = 1.0;
   
   gl_FragColor = color;
} 









