#version 330 compatibility
// version 400 was released in 2010. https://en.wikipedia.org/wiki/OpenGL_Shading_Language


// TODO: https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/

// fragment shader for map rendering

#define sp_mapGround	0
#define sp_mapWall		1
#define sp_water		2
#define sp_light		3
#define sp_cars			4
#define sp_actors		5
#define sp_particles	6
#define sp_triggers		7
#define sp_decals		10
#define sp_gui			11

// https://learnopengl.com/Lighting/Basic-Lighting

// TODO: light parameters.

uniform vec2 u_resolution;	// Canvas size (width,height)
uniform vec2 u_mouse;	 	// mouse position in screen pixels
uniform float u_time;	 	// Time in seconds since load

uniform int ShadowsPass;		// Pipeline: shadow mapping shadows
uniform float AmbientLighting;	// minimum ambient brightness 0..1, even in shadows
uniform float ShadowSharpness;	// adjusting this gives more blurred shadows.. this value is in relation to how big shadow is (dimensions of world).

uniform int uRenderingPass;		// what is being rendered? 0 = map, 1 = water, 3 = cars, 4 = actors, 5 = particles, 10 = gui
uniform int uShadowQuality;		// shadow mapping quality, with 0 = lowest quality.
uniform int MultiBuffer;		// should secondary compositing be used?
uniform float uAddHue;			
uniform float uAddSaturation;	
uniform float uAddLightness;	
uniform bool uAddShadows;		// Should shadow mapping be taken into account during rendering or not
uniform float uShadowOpacity;	
uniform bool uBurnt_out;		
uniform bool uShadow_mode;		
uniform bool uUnderwater;		
uniform bool uBicubic;		
uniform float uTransluscency;	
uniform bool uDebugShadowmap;

// shadow mapping
uniform sampler2D ShadowMap;
in vec4 ShadowCoord_LightSpace; // passed from vertex shader

uniform sampler2D Texture0; // First texture
uniform vec3 PlayerPosition;
uniform vec3 CameraVector;
uniform int UndergroundMode;
uniform float UndergroundIntensity;


// sprite shadow
// todo..

const float smoothing = 1.0/16.0;
const vec2 shadowOffset = vec2(-1.0/512.0);
const vec4 glowColor = vec4(vec3(0.1), 1.0);
const float glowMin = 0.2;
const float glowMax = 0.8;


// Passed in from the vertex shader.
in vec3 Playercheckcoords; // Player coordinates, for visual effects
in vec4 VertexColor;
in vec3 vertexcoords; // Vertex coordinates without modelview (so where in world it actually is)
in vec4 WorldCoords;
in vec3 normcoords; // unused
in vec4 compat_TexCoord;

layout (location = 0) out vec4 FragColor;
layout (location = 1) out vec4 gLightingData;
layout (location = 2) out vec4 gShadowData;
//layout (location = 3) out float fragmentdepth; // GL_DEPTH_COMPONENT24

// TODO: replace HSL with sam hocevar's version:
// http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
// Note that for these functions the range for H is [0…1] instead of [0…360], so you will have to adapt your input.

vec3 rgb2hsv(vec3 c) {
	
	vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
	vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
	vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
	
	float d = q.x - min(q.w, q.y);
	float e = 1.0e-10;
	return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
	
}

vec3 hsv2rgb(vec3 c) {
	
	vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
	vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
	return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
	
}

/*
bool IsSkinTone2(vec4 color) {
	
	// The ranges for a skin pixel in different color spaces used by our algorithm are as follows:
	// 0.0 <= H <= 50.0
	// and 0.23 <= S <= 0.68
	// and R > 95 and G > 40 and B > 20 and R > G and R > B and | R - G | > 15 and A > 15
	
	// https://fiveko.com/tutorials/image-processing/skin-detection-segmentation/
	// (R > 95), (G > 40), (B > 20), max{R, G, B} − min{R, G, B} > 15, |R − G| > 15, R>G, R>B
	
}
*/

bool IsSkinTone(vec4 color) {
	
	mat4 RGBtoYUV = mat4(vec4(0.257,  0.439, -0.148, 0.0),
				  vec4(0.504, -0.368, -0.291, 0.0),
				  vec4(0.098, -0.071,  0.439, 0.0),
				  vec4(0.0625, 0.500,  0.500, 1.0)
	);
	
	vec4 YUV = RGBtoYUV * color;
	
	//precision mediump float;
	vec4 thr = vec4(80.0/255.0, 120.0/255.0, 133.0/255.0, 173.0/255.0);
	
	return ( (YUV[0] > thr[0]) && (YUV[1] >= thr[0]) && (YUV[1] <= thr[1]) && (YUV[2] >= thr[2]) && (YUV[2] <=thr[3])) ? true : false;
	
}

// float Hue_2_RGB(float v1, float v2, float vH ) {
// 	
// 	float result;
// 	
// 	if (vH < 0.0)
// 		vH += 1.0;
// 	
// 	if (vH > 1.0)
// 		vH -= 1.0;
// 	
// 	if ((6.0 * vH) < 1.0) {
// 		result = (v1 + (v2 - v1) * 6.0 * vH); 
// 	} else if ((2.0 * vH) < 1.0) {
// 		result = ( v2 );
// 	} else if ((3.0 * vH) < 2.0) {
// 		result = (v1 + (v2 - v1) * ((2.0 / 3.0) - vH) * 6.0);
// 	} else {
// 		result = v1;
// 	}
// 	
// 	return result;
// 	
// }
// 
// // convert to HSL
// vec4 RGB2HSL(float R, float G, float B) {
// 	
// 	float H, S, L;
// 	
// 	float Cmax, Cmin;
// 	float D;
// 	
// 	Cmax = max (R, max (G, B));
// 	Cmin = min (R, min (G, B));
// 	
// 	// calculate lightness
// 	L = (Cmax + Cmin) / 2.0;
// 	
// 	if (Cmax == Cmin) { // it's grey
// 		H = 0.0; // it's actually undefined
// 		S = 0.0;
// 	} else {
// 		D = Cmax - Cmin; // we know D != 0 so we cas safely divide by it
// 	}
// 	
// 	// calculate Saturation
// 	if (L < 0.5) {
// 		S = D / (Cmax + Cmin);
// 	} else {
// 		S = D / (2.0 - (Cmax + Cmin));
// 	}
// 	
// 	// calculate Hue
// 	if (R == Cmax) {
// 		
// 		H = (G - B) / D;
// 		
// 	} else {
// 		
// 		if (G == Cmax) {
// 			H = 2.0 + (B - R) /D;
// 		} else {
// 			H = 4.0 + (R - G) / D;
// 		}
// 	}
// 	
// 	H = H / 6.0;
// 	
// 	if (H < 0.0) {
// 		H = H + 1.0;
// 	}
// 	
// 	return vec4(H, S, L, 0.0);
// 	
// }

vec4 HueShiftColor(vec4 color_input, float ChangeHue, float ChangeSat, float ChangeLit, bool burnt_out, bool shadow_mode, float ShadowOpacity, float in_transluscency) {
	
	// rgb2hsv
	
	float ModifyHue = ChangeHue;
	float ModifySat = ChangeSat;
	float ModifyLit = ChangeLit;
	
	if (shadow_mode) // shadow mode
		return vec4(0,0,0, (color_input.a * ShadowOpacity) );
	
	if ( burnt_out ) { // exploded burnt out rendering mode
		
		ModifyHue = 0;
		ModifySat = -1.0;
		ModifyLit = -0.8;
		
	}
	
	//if (true) {
		
		vec3 hsv = rgb2hsv(color_input.rgb);
		hsv.x += ModifyHue;
		hsv.y += ModifySat;
		
		if (burnt_out) // exploded burnt out rendering mode
			hsv.z = (hsv.z - 0.5) * 0.2; // clamp lightness so it removes highlights, TODO: maybe just multiply everything by 0.5 ?
		else
			hsv.z += ModifyLit;
		
		color_input.rgb = hsv2rgb(hsv);
		
		return vec4(color_input.r, color_input.g, color_input.b, color_input.a * in_transluscency) * VertexColor;
		
	//}
	
	// a rather bad implementation:
	//	float H, S, L;
	//	float R, G, B;
	//	
	//	R = color_input.r;
	//	G = color_input.g;
	//	B = color_input.b;
	//	
	//	// properly process white color which cannot be properly converted to hsl and back (ends up black)
	//	if ((R == 1.0) && (G == 1.0) && (B == 1.0))
	//		return color_input;
	//	
	//	vec4 hsl = RGB2HSL(R, G, B);
	//	
	//	H = hsl.x;
	//	S = hsl.y;
	//	L = hsl.z;
	//	
	//	// modify H/S/L values
	//	H += ModifyHue;
	//	S += ModifySat;
	//	L += ModifyLit;
	//	
	//	/*if (VertexColor.r < 1.0)
	//		L -= (1 - VertexColor.r);
	//	*/
	//	
	//	if (H < 0.0) {
	//		H = H + 1.0;
	//	}
	//	
	//	// clamp H,S and L to [0..1]
	//	
	//	if (burnt_out) // exploded burnt out rendering mode
	//		L = L * 0.5; // clamp lightness so it removes highlights, TODO: maybe just multiply everything by 0.5 ?
	//	
	//	H = clamp(H, 0.0, 1.0);
	//	S = clamp(S, 0.0, 1.0);
	//	L = clamp(L, 0.0, 1.0);
	//	
	//	// convert back to RGB
	//	float var_2, var_1;
	//	
	//	if (S == 0.0) {
	//		
	//		R = L;
	//		G = L;
	//		B = L;
	//		
	//	} else {
	//		
	//		if ( L < 0.5 ) { 
	//			var_2 = L * ( 1.0 + S );
	//		} else {
	//			var_2 = ( L + S ) - ( S * L );
	//		}
	//		
	//		var_1 = 2.0 * L - var_2;
	//		
	//		R = Hue_2_RGB( var_1, var_2, H + ( 1.0 / 3.0 ) );
	//		G = Hue_2_RGB( var_1, var_2, H );
	//		B = Hue_2_RGB( var_1, var_2, H - ( 1.0 / 3.0 ) );
	//		
	//	}
	//	
	//	return vec4(R, G, B, color_input.a * in_transluscency) * VertexColor;
	
}

// from http://www.java-gaming.org/index.php?topic=35123.0
vec4 cubic(float v){
	vec4 n = vec4(1.0, 2.0, 3.0, 4.0) - v;
	vec4 s = n * n * n;
	float x = s.x;
	float y = s.y - 4.0 * s.x;
	float z = s.z - 4.0 * s.y + 6.0 * s.x;
	float w = 6.0 - x - y - z;
	return vec4(x, y, z, w) * (1.0/6.0);
}

vec4 textureBicubic(sampler2D sampler, vec2 texCoords){
	
	if (!uBicubic) {
		
		return texture(sampler, texCoords);
		
	}
	
   vec2 texSize = textureSize(sampler, 0);
   vec2 invTexSize = 1.0 / texSize;

   texCoords = texCoords * texSize - 0.5;


	vec2 fxy = fract(texCoords);
	texCoords -= fxy;

	vec4 xcubic = cubic(fxy.x);
	vec4 ycubic = cubic(fxy.y);

	vec4 c = texCoords.xxyy + vec2 (-0.5, +1.5).xyxy;

	vec4 s = vec4(xcubic.xz + xcubic.yw, ycubic.xz + ycubic.yw);
	vec4 offset = c + vec4 (xcubic.yw, ycubic.yw) / s;

	offset *= invTexSize.xxyy;

	vec4 sample0 = texture(sampler, offset.xz);
	vec4 sample1 = texture(sampler, offset.yz);
	vec4 sample2 = texture(sampler, offset.xw);
	vec4 sample3 = texture(sampler, offset.yw);

	float sx = s.x / (s.x + s.y);
	float sy = s.z / (s.z + s.w);

	return mix(
	   mix(sample3, sample2, sx), mix(sample1, sample0, sx)
	, sy);
}

void main() {
	
	// Get fragment color
	vec4 color = textureBicubic(Texture0, compat_TexCoord.st);
	
	if ((uRenderingPass == sp_mapGround) /*|| (uRenderingPass == sp_mapWall)*/) {
		
		// Produce cone shaped holes in ground, to see thru ceilings
		if (UndergroundIntensity > 0.0) {
			
			vec3 comparison = vertexcoords.xyz;
			float maxdist = 3.0;
			vec3 checkpcoords = Playercheckcoords;
			checkpcoords.z += maxdist;
			
			float Dist2D = distance(checkpcoords.xy, comparison.xy);
			float dist3d = distance(checkpcoords.xyz, comparison.xyz);
			
			// discard based on sort of cone shape, 0.4 is minimum height at which the effect starts.
			
			float offset = 0.0;
			
			if (UndergroundMode > 1) // /* + 0.4 USE THIS WHEN STANDING ON angled surfaces. */
				offset = 0.4;
			
			if ( (Dist2D < maxdist) && (comparison.z > (Playercheckcoords.z + offset) + (Dist2D * 0.15)) ) {
				
				maxdist = exp2(dist3d);
				
				float how_much_alpha = (Dist2D * 0.25 /*(1.0 /maxdist)*/);
				
				color.a = color.a * (how_much_alpha + (1.0 - UndergroundIntensity) );
				
			}
			
		}
		
	}
	
	float shadow = 1.0;
	float shadow_WithoutAlpha = 1.0;
	
	if (ShadowsPass != 0) {
		
		vec4 shadowCoordinateWdivide = ShadowCoord_LightSpace; // dividing - / ShadowCoord_LightSpace.w  is needed only for projected lights?
		
		float bias = 0.001 * 0.4;
		
		if (uDebugShadowmap) {
			
			// Debugging if shadow mapping projection is correct.
			FragColor = texture(ShadowMap, shadowCoordinateWdivide.st); //  + (color * 0.5)
			
			return;
			
		}
		
		/*
		
		NVIDIA DEBUG 1:
		
		// Normalize the Shadow Map coordinates
		vec3 shadowCoordinateWdivide = ShadowCoord_LightSpace.xyz / ShadowCoord_LightSpace.w; //  is needed only for projected lights?
		
		if (uDebugShadowmap) {
			
			// Debugging if shadow mapping projection is correct.
			float distanceFromLight = texture(ShadowMap, shadowCoordinateWdivide.xy).r; //  + (color * 0.5)
			
			float depthInShadow = shadowCoordinateWdivide.z - distanceFromLight;
			
			distanceFromLight = ( texture( ShadowMap, shadowCoordinateWdivide.xy ).r < shadowCoordinateWdivide.z ? 1.0 : 0.0);
			
			FragColor = vec4(distanceFromLight, color.g, color.b, color.a);
			//FragColor = vec4(depthInShadow, color.g, color.b, color.a);
			
			return;
			
		}
		*/
		
		// primitive technique:
		
		/*
		shadow = ( texture( ShadowMap, shadowCoordinateWdivide.xy ).r  <  shadowCoordinateWdivide.z) ? 0.5 : 1.0;
		
		color = color * VertexColor; // take vertex color
		FragColor = vec4(color.r * shadow, color.g * shadow, color.b * shadow, color.a);
		
		
		//FragColor = vec4(
		//	texture( ShadowMap, shadowCoordinateWdivide.xy ).r, 
		//	texture( ShadowMap, shadowCoordinateWdivide.xy ).g,
		//	texture( ShadowMap, shadowCoordinateWdivide.xy ).z,
		//	color.a);
		
		
		return;
		
		*/
		
		// V2
		
		/*
		
		textureGather() added in 4.00 - ??? https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/textureGather.xhtml
		
		//float closestDepth = texture(shadowMap, projCoords.xy).r;   
		
		float distanceFromLight = texture(ShadowMap, shadowCoordinateWdivide.xy).z; // was .z
		
		//float distanceFromLight = texture(ShadowMap, shadowCoordinateWdivide.xy).r; // was .z
		
		//float distanceFromLight = texture(ShadowMap, shadowCoordinateWdivide.st).r; // was .z
		
	 	// if (ShadowCoord_LightSpace.w > 0.0) // This is when we try to sample value behind the light's view frustrum.
	 		shadow = distanceFromLight < (shadowCoordinateWdivide.z - bias) ? 0.5 : 1.0; // - bias = Used to lower moiré pattern and self-shadowing
		
		color = color * VertexColor; // take vertex color
		FragColor = vec4(color.r * shadow, color.g * shadow, color.b * shadow, color.a);
		return;
		
		*/
		
		if (uShadowQuality == 0) {
			
			// poisson disk, small:
			
			vec2 poissonDisk[4] = vec2[](
				vec2( -0.94201624, -0.39906216 ),
				vec2( 0.94558609, -0.76890725 ),
				vec2( -0.094184101, -0.92938870 ),
				vec2( 0.34495938, 0.29387760 )
			);
			
			int num_samples = 4;
			
			float poisson_divider = 700.0 * ShadowSharpness; // adjusting this gives more blurred shadows.. this value is in relation to how big shadow is (dimensions of world).
			
			for (int i = 0; i < num_samples; i++) {
				if ( texture( ShadowMap, shadowCoordinateWdivide.st + poissonDisk[i] / poisson_divider ).r  < shadowCoordinateWdivide.z - bias ){
					shadow -= (1.0 / num_samples);
				}
			}
			
			
		} else {
			
			// poisson disk, large:
			int num_samples = 16;
			
			vec2 poissonDisk[16] = vec2[]( 
			   vec2( -0.94201624, -0.39906216 ), 
			   vec2( 0.94558609, -0.76890725 ), 
			   vec2( -0.094184101, -0.92938870 ), 
			   vec2( 0.34495938, 0.29387760 ), 
			   vec2( -0.91588581, 0.45771432 ), 
			   vec2( -0.81544232, -0.87912464 ), 
			   vec2( -0.38277543, 0.27676845 ), 
			   vec2( 0.97484398, 0.75648379 ), 
			   vec2( 0.44323325, -0.97511554 ), 
			   vec2( 0.53742981, -0.47373420 ), 
			   vec2( -0.26496911, -0.41893023 ), 
			   vec2( 0.79197514, 0.19090188 ), 
			   vec2( -0.24188840, 0.99706507 ), 
			   vec2( -0.81409955, 0.91437590 ), 
			   vec2( 0.19984126, 0.78641367 ), 
			   vec2( 0.14383161, -0.14100790 ) 
			);
			
			float poisson_divider = 700.0 * ShadowSharpness; // adjusting this gives more blurred shadows.. this value is in relation to how big shadow is (dimensions of world).
			
			for (int i = 0; i < num_samples; i++) {
				if ( texture( ShadowMap, shadowCoordinateWdivide.st + poissonDisk[i] / poisson_divider ).r  < shadowCoordinateWdivide.z - bias ){
					shadow -= (1.0 / num_samples);
				}
			}
			
		}
		
		// Take ambient brightness into account
		
		shadow_WithoutAlpha = shadow;
		
		shadow = AmbientLighting + (shadow * (1.0 - AmbientLighting));
		
		shadow = shadow * texture(Texture0, compat_TexCoord.st).a;
		
		// todo: multiply with texture(Texture0, compat_TexCoord.st).a; as that is transluscency of that piece.
		
	}
	
	/*
	#define sp_mapGround	0
	#define sp_mapWall		1
	#define sp_water		2
	#define sp_light		3
	#define sp_cars			4
	#define sp_actors		5
	#define sp_particles	6
	#define sp_triggers		7
	#define sp_decals		10
	#define sp_gui			11
	*/
	
	// TODO in the end shadow can be multiplied by alpha of shadowed object.
	
	// color is fetched from texture, alpha is already modified by transluscency
	
	// sp_water
	
	float FinalOutshadow;
	
	if (MultiBuffer == 1)
		FinalOutshadow = texture(Texture0, compat_TexCoord.st).a; // shadows are added in later in postprocessing.
	else
		FinalOutshadow = shadow;
	
	float shadowa = 0.0;
	
	vec4 outLight = vec4(0.0, 0.0, 0.0, 0.0);
	
	// we handle uShadowOpacity differently in multibuffer.
	
	if (uRenderingPass == sp_light) {
		
		color = texture(Texture0, compat_TexCoord.st);
		
		color = color * VertexColor; // take vertex color
		
		//color = vec4(1, 1, 1, 1);
		
		// Output to color buffer
		
		//in_transluscency
		
		outLight = color; //vec4(color.r, color.g, color.b, color.a);
		// gShadowData = vec4(1.0, 1.0, 1.0, shadow_WithoutAlpha);
		
		// shadowa = FragColor.a;
		
	} else if (uRenderingPass == sp_decals) {
		
		color = texture(Texture0, compat_TexCoord.st);
		
		color = color * VertexColor; // take vertex color
		
		FragColor = vec4(color.r * FinalOutshadow, color.g * FinalOutshadow, color.b * FinalOutshadow, color.a);
		// gShadowData = vec4(1.0, 1.0, 1.0, shadow_WithoutAlpha);
		
		shadowa = FragColor.a;
		
	} else if (uRenderingPass == sp_particles) {
		
		color = color * VertexColor; // take vertex color
		
		if (uAddShadows)
			FragColor = vec4(color.r * FinalOutshadow, color.g * FinalOutshadow, color.b * FinalOutshadow, color.a);
		else
			FragColor = vec4(color.r, color.g, color.b, color.a);
		
		// gShadowData = vec4(1.0, 1.0, 1.0, shadow_WithoutAlpha);
		
		shadowa = FragColor.a;
		
	} else if (uRenderingPass == sp_actors) { // actors pass
		
		//if (IsSkinTone(color)) {
		//	
		//	color = vec4(0.0, 0.0, 0.0, 0.0);
		//	
		//} else {
		//	
			color = HueShiftColor(color, 0.0, 0.0, 0.0, uBurnt_out, uShadow_mode, uShadowOpacity, uTransluscency);
		//	
		//}
		
		// experimental drop-shadow effect thingie.
		//	
		//	https://github.com/mattdesl/gl-sprite-text/blob/master/demo/sdf/frag.glsl
		//	
		//	vec4 texColor = color; // color = texture(Texture0, compat_TexCoord.st);
		//	
		//	float dst = texColor.a;
		//	float alpha = smoothstep(0.5 - smoothing, 0.5 + smoothing, dst);
		//	
		//	float glowDst = texture(Texture0, compat_TexCoord.st + shadowOffset).a;
		//	vec4 glow = glowColor * smoothstep(glowMin, glowMax, glowDst);
		//	
		//	float mask = 1.0-alpha;
		//	
		//	vec4 tint = vec4(1, 0, 0, 1);
		//	
		//	vec4 base = /*v_col*/ VertexColor * vec4(vec3(1.0), alpha) * tint;
		//	FragColor = mix(base, glow, mask);
		//	
		
		if ( (uShadow_mode) && (MultiBuffer == 1) ) { // handle sprite shadows also in multibuffer.
			
			shadow = 0.0;
			shadowa = color.a; // uShadowOpacity
			
		} else {
			
			FragColor = vec4(color.r * FinalOutshadow, color.g * FinalOutshadow, color.b * FinalOutshadow, color.a);
			// gShadowData = vec4(1.0, 1.0, 1.0, shadow_WithoutAlpha);
			shadowa = FragColor.a;
			
		}
		
	} else if (uRenderingPass == sp_cars) { // vehicles pass
		
		color = color * VertexColor; // take VertexColor into account so things like EM lights and car damage can work.
		
		if (uUnderwater)
			color.a *= 0.1; // effect when a car is sunk in water.
		
		color = HueShiftColor(color, uAddHue, uAddSaturation, uAddLightness, uBurnt_out, uShadow_mode, uShadowOpacity, uTransluscency);
		
		if ( (uShadow_mode) && (MultiBuffer == 1) ) { // handle sprite shadows also in multibuffer.
			
			shadow = 0.0;
			shadowa = color.a; // uShadowOpacity
			
		} else {
			
			if (uAddShadows)
				FragColor = vec4(color.r * FinalOutshadow, color.g * FinalOutshadow, color.b * FinalOutshadow, color.a);
			else
				FragColor = vec4(color.r, color.g, color.b, color.a);
			
			// gShadowData = vec4(1.0, 1.0, 1.0, shadow_WithoutAlpha);
			shadowa = FragColor.a;
			
		}
		
	} else {
		
		// map pass
		
		FragColor = vec4(color.r * FinalOutshadow, color.g * FinalOutshadow, color.b * FinalOutshadow, color.a);
		
		//if (color.a > 0.5)
		//outLight.a = 0.0;
		outLight = vec4(0.0, 0.0, 0.0, color.a); // cancel light
		
		// gShadowData = vec4(1.0, 1.0, 1.0, shadow_WithoutAlpha);
		
		shadowa = FragColor.a;
		
	}
	
	// gl_FragDepth = gl_FragCoord.z;
	gShadowData = vec4(1.0 - shadow, 1.0 - shadow, 1.0 - shadow, shadowa);
	gLightingData = outLight;
	
}
