#ifdef GL_ES
precision mediump float;
#endif

uniform sampler2D u_texture;
uniform sampler2D u_heightmapTexture;
uniform vec2 u_resolution;

uniform int u_lightCount;
uniform float u_lightFalloffs[8];
uniform vec2 u_lightPositions[8];
uniform vec4 u_lightColors[8];
uniform vec2 u_cameraScale;


/**
 * PLAY AROUND WITH THESE
 */

// color of "HDR" bright pixels
const vec4 highlightLight = vec4(1.0, 0.95, 0.9, 1.0);
const vec4 ambientLight = vec4(0.15, 0.1, 0.175, 1.0);

// pixels brighter than this are candidates for HDR brightness
const float highlightThreshold = 1.0;
// pixels brighter than this stay source color, darker ones are tinted
const float brightThreshold = 0.6;
// pixels darker than this are unlit
const float darkThreshold = 0.1;

// size of the "border area" between different lighting levels (plus minus, so effectively twice this much)
const float borderSize = 0.1;

// if source pixel brightness is over this, border pixel belongs to the brighter lighting level
const float borderCutoff = 0.5;

// adjust the brightness of mid-level (tinted) pixels
const float midBrightness = 0.6;

// cull lights more than this many pixels outside of the screen
const float cullDist = 500.0;

/**
 * OK STOP PLAYING AROUND
 */

varying vec2 v_texCoord;
varying vec4 v_color;

vec4 greyscale(in vec4 color, in float level) {
	float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));

	return mix(color, vec4(gray, gray, gray, color.a), level);
}

void main() {
	vec2 texCoord = vec2(gl_FragCoord.x / u_resolution.x, gl_FragCoord.y / u_resolution.y);
	vec4 color = texture2D(u_texture, texCoord);

	vec2 glCoord = vec2(gl_FragCoord);

	float distance;

	// figure out the brightest color for this fragment so we can use that as the tinted color
	vec4 brightestColor = ambientLight;
	float brightestBrightness = 0.0;

	vec4 adjustedColor;
	float currentBrightness;
	float brightness = 0.0;

	for (int i = 0; i < u_lightCount; i++) {
		if (u_lightPositions[i].x < -cullDist || u_lightPositions[i].y < -cullDist || u_lightPositions[i].x > u_resolution.x+cullDist || u_lightPositions[i].y > u_resolution.y+cullDist) continue;

		distance = length((glCoord - u_lightPositions[i])/u_cameraScale);
		if (distance > u_lightFalloffs[i]) continue;

		adjustedColor = ((u_lightFalloffs[i]-distance)/u_lightFalloffs[i])*u_lightColors[i];
		currentBrightness = (adjustedColor[0] + adjustedColor[1] + adjustedColor[2]) / 3.0;
		if (currentBrightness > brightestBrightness) {
			brightestColor = u_lightColors[i];
			brightestBrightness = currentBrightness;
		}

		brightness += currentBrightness;
	}

	vec4 heightmapColor = texture2D(u_heightmapTexture, texCoord);

//	gl_FragColor = heightmapColor;

	float heightmapBrightness = (heightmapColor[0] + heightmapColor[1] + heightmapColor[2]) / 3.0;

	// use highlight color
	if (brightness > highlightThreshold && heightmapBrightness > 0.7) {
		gl_FragColor = highlightLight;
	// use original color
	} else if (brightness > brightThreshold || (brightness > brightThreshold-borderSize && heightmapBrightness > brightThreshold)) {
		gl_FragColor = color;
	// use tinted color
	} else if (brightness > darkThreshold || (brightness > darkThreshold-borderSize && heightmapBrightness > darkThreshold)) {
		gl_FragColor = color*brightestColor * midBrightness;
	// ambient
	} else {
		gl_FragColor = greyscale(color, 1.0)*ambientLight;
	}
}