#version 330

in vec3 pPos;
in vec3 pTexture;
in vec3 pLightMapPos;
in vec3 pSunDepth;
in vec2 pVertex;
in float pCameraDepth;

flat in int pFlags;
flat in float pFade;
flat in int pRGB;

out vec4 FragColor;

uniform sampler3D atlas;
uniform sampler2D lightmap;
uniform sampler2D depthmap;

uniform vec3 lighting_day_low;
uniform vec3 lighting_day_high;

uniform vec2 lightmap_offset;
uniform vec2 lightmap_size;

uniform int do_discard_coords;
uniform vec4 discard_coords;
uniform vec4 color;

uniform float contrast;
uniform int mode;

vec3 color_grass_hot_wet = vec3(0.05, 0.8, 0);
vec3 color_grass_hot_dry = vec3(1, 0.6, 0);
vec3 color_grass_cold_wet = vec3(0.075, 0.533, 0.047);
vec3 color_grass_cold_dry = vec3(0.812, 0.761, 0);

float depth_c = 0.0001;

float map(float x, float in_min, float in_max, float out_min, float out_max) {
	return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

vec3 mapVec(float x, float in_min, float in_max, vec3 out_min, vec3 out_max) {
	return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

vec3 biggest(vec3 a, vec3 b) {
	return vec3(a.x > b.x ? a.x : b.x,
				a.y > b.y ? a.y : b.y,
				a.z > b.z ? a.z : b.z);
}

float scaleLight(float level) {
	return level * level;
}

float smoothStep(float a) {
	return a * a * (3 - 2 * a);
}

float interpolate2(float x, float y, float v00, float v01, float v10, float v11) {
	return (v00 * x + v10 * (1 - x)) * y + (v01 * x + v11 * (1 - x)) * (1 - y);
}

vec3 interpolate2RGB(float x, float y, vec3 v00, vec3 v01, vec3 v10, vec3 v11) {
	return (v00 * x + v10 * (1 - x)) * y + (v01 * x + v11 * (1 - x)) * (1 - y);
}

void main()
{
	vec4 textureRGB = texture(atlas, pTexture);

	if(mode == 0)
	{
		vec4 light = texture(lightmap, vec2(
			map(pLightMapPos.x, lightmap_offset.x, lightmap_offset.x + lightmap_size.x, 0, 1),
			map(pLightMapPos.z, lightmap_offset.y, lightmap_offset.y + lightmap_size.y, 0, 1)));

		vec2 sunDepthTexPos = pSunDepth.xy * 0.5 + 0.5;
		
		vec3 light_day = pSunDepth.z < (texture(depthmap, sunDepthTexPos).r * 2 - 1 + depth_c
			) ? lighting_day_high : lighting_day_low;
		vec3 light_src = vec3(1, 1, 1) * (scaleLight(max(0, light.r)) - abs(pLightMapPos.y) * 0.1);
		vec4 rgb = vec4((pRGB % 64) / 64.0, ((pRGB >> 6) % 64) / 64.0, ((pRGB >> 12) % 64) / 64.0, 1);
		
		vec4 color_grass = vec4(interpolate2RGB(
			smoothStep(light.g), smoothStep(light.b), 
			color_grass_cold_dry, color_grass_hot_dry,
			color_grass_cold_wet, color_grass_hot_wet), 1);
			
		float saturation = contrast * 1.6 + 1;
		float fog = pCameraDepth;
	
		FragColor = (fog + (1 - fog) * textureRGB * (mod(int(pFlags / 4), 2) == 1 ? color_grass : vec4(1,1,1,1)) * color)
			* vec4(biggest(light_day, light_src), pFade) * (mod(int(pFlags / 2), 2) == 1 ? rgb : vec4(1, 1, 1, 1))
			* saturation + contrast;
		
		FragColor.r = min(1, FragColor.r);
		FragColor.g = min(1, FragColor.g);
		FragColor.b = min(1, FragColor.b);
	}
	
	discard(textureRGB.a == 0 || (do_discard_coords == 1 && (
					pVertex.x < discard_coords.x || pVertex.y < discard_coords.y ||
					pVertex.x > discard_coords.z || pVertex.y > discard_coords.w)));
}