#version 330
#pragma optionNV (unroll all)

in vec3 worldSpacePosition;
in vec3 color;
in vec3 normal;
//in vec3 tangent;

in vec3 uv;

layout(location = 0) out vec4 fragColor;
layout(location = 1) out vec4 fragData;

uniform float matSpecExponent;

const float PI = 3.14159265358979323846264;

const float P_DEPTH=2;
const int P_MAX_SAMPLES=30;
const int P_MIN_SAMPLES=5;

uniform float alpha;

const int MAX_LIGHTS = 20;
uniform int lightCount;
uniform int lightType[MAX_LIGHTS];
uniform vec3 lightPosition[MAX_LIGHTS];
uniform vec3 lightDirection[MAX_LIGHTS];
uniform vec3 lightIntensity[MAX_LIGHTS];
uniform float lightRange[MAX_LIGHTS];
uniform float lightAngle[MAX_LIGHTS];

uniform int textureCount;
uniform sampler2D texture0;
uniform sampler2D texture1;
uniform sampler2D texture2;
uniform sampler2D texture3;
uniform sampler2D texture4;
uniform sampler2D texture5;
uniform sampler2D texture6;
uniform sampler2D texture7;

uniform int fogEnabled;
uniform vec3 fogColor;
uniform float fogRange;
uniform float fogDensity;

uniform vec3 cameraWorldPos;

uniform mat4 transformationMatrix;
uniform mat4 viewMatrix;

uniform mat4 iMvp;
uniform mat4 lastMvp;

float cosTheta;

vec3 up = vec3(0,1,0);

vec3 lightingResult = vec3(0,0,0);

int i;
float lightDist=0;
vec3 lightVec;

void main() {
	vec4 modelspacepos = iMvp*gl_FragCoord;
	//modelspacepos /= modelspacepos.w;
	vec4 lastScreenSpacePos = lastMvp*modelspacepos;
	//lastScreenSpacePos.xyz /= lastScreenSpacePos.w;

	vec3 blurVector = lastScreenSpacePos.xyz - gl_FragCoord.xyz;
	
	fragData = vec4(blurVector.xy, gl_FragCoord.z, 1);

	
	
	for (i=0;i<lightCount;i++) {
		if (lightType[i]==3) {
			lightVec = worldSpacePosition-lightPosition[i];
			lightDist = length(lightVec);
			
			if (lightDist<lightRange[i]) {
				float angleDot = dot(normalize(lightDirection[i]),normalize(lightVec));
				float lightAngleCos = cos(lightAngle[i]*2*PI/360);
				if (angleDot>lightAngleCos) {
					lightingResult += lightIntensity[i] * max(1-lightDist / lightRange[i], 0);
				} else if (angleDot>lightAngleCos/1.04) {
					float fuzzFactor = 1-25*((lightAngleCos/angleDot)-1);
					lightingResult += lightIntensity[i] * max(1-lightDist / lightRange[i], 0) * fuzzFactor*fuzzFactor;//*fuzzFactor*fuzzFactor;
				}
			}
		} else if (lightType[i]==2) {
			lightVec = lightPosition[i]-worldSpacePosition;
			lightDist = length(lightVec);
			lightingResult += lightIntensity[i] * max(1-lightDist/ lightRange[i], 0);
		} else if (lightType[i]==1) {
			vec2 luv = uv.xz*50/512;
			luv.x = -luv.x;
			lightingResult += texture(texture2, luv).xyz;
		}
	}

	vec3 nnormal = normal;
	float gradient = dot(nnormal, up);

	vec4 textureColor0 = texture(texture0, uv.xz).xyzw;

	//Tri-Planar texture mapping
	vec4 textureColor1x = texture(texture1, uv.xy+0.9f).xyzw;
	vec4 textureColor1y = texture(texture1, uv.xz+0.4f).xyzw;
	vec4 textureColor1z = texture(texture1, uv.yz+0.7f).xyzw;

	fragColor = (textureColor0 * gradient)
				+ (textureColor1x*abs(nnormal.z)*.5) * (1-gradient)
				+ (textureColor1y*abs(nnormal.y)*.5) * (1-gradient)
				+ (textureColor1z*abs(nnormal.x)*.5) * (1-gradient);
	fragColor = vec4(fragColor.xyz*lightingResult,fragColor.a*alpha);
	
	if (fogEnabled==1) {
		float dist = length(worldSpacePosition-cameraWorldPos);
		dist = 1 - dist/fogRange;
		dist = min(max(dist,0),1);

		float expterm = exp(dist * fogDensity);
		float ratio = 1.0f/(expterm*expterm);

		fragColor = vec4(fragColor.xyz*(1-ratio)+(ratio)*fogColor, fragColor.a);
	}
}