/*//////////////////////////////////////////////////////////////////////////////
//    ##      #####   ######   ######     ##     ####     #######  ##  ##     //
//   ####    ##   ##  # ## #    ##  ##   ####     ##       ##   #  ##  ##     //
//  ##  ##   #          ##      ##  ##  ##  ##    ##       ## #     ####      //
//  ##  ##    #####     ##      #####   ##  ##    ##       ####      ##       //
//  ######        ##    ##      ## ##   ######    ##   #   ## #     ####      //
//  ##  ##   ##   ##    ##      ##  ##  ##  ##    ##  ##   ##   #  ##  ##     //
//  ##  ##    #####    ####    #### ##  ##  ##   #######  #######  ##  ##     //
//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//
//      #####   ##   ##    ##     #####    #######  ######    #####           //
//     ##   ##  ##   ##   ####     ## ##    ##   #   ##  ##  ##   ##          //
//     #        ##   ##  ##  ##    ##  ##   ## #     ##  ##  #                //
//      #####   #######  ##  ##    ##  ##   ####     #####    #####           //
//          ##  ##   ##  ######    ##  ##   ## #     ## ##        ##          //
//          ##  ##   ##  ######    ##  ##   ## #     ## ##        ##          //
//     ##   ##  ##   ##  ##  ##    ## ##    ##   #   ##  ##  ##   ##          //
//      #####   ##   ##  ##  ##   #####    #######  #### ##   #####           //
/////(BSL Shaders Edit)//////////////////////////////////////By LexBoosT//////*/

//Settings//

//#define DEBUG_ENTITIES

#include "/lib/util/fastMath.glsl"

#include "/settings/globalSettings.glsl"

//Varyings//
varying vec2 texCoord, lmCoord;

varying vec3 normal;
varying vec3 sunVec, upVec, eastVec;

varying vec4 color;
varying vec4 position;

#ifdef ADVANCED_MATERIALS
	varying float dist;

	varying vec3 viewVector;
	varying vec3 binormal, tangent;

	varying vec4 vTexCoord, vTexCoordAM;
#endif

//Fragment Shader///////////////////////////////////////////////////////////////////////////////////
#ifdef FSH

	//Uniforms//
	uniform int entityId;
	uniform int frameCounter;
	uniform int isEyeInWater;
	uniform int heldItemId;
	uniform int heldItemId2;
	uniform int moonPhase;
	#define UNIFORM_MOONPHASE

	#ifdef DYNAMIC_HAND_LIGHT
		uniform int heldBlockLightValue;
		uniform int heldBlockLightValue2;
	#endif

	uniform float frameTimeCounter;
	uniform float nightVision;
	uniform float rainStrengthS;
	uniform float screenBrightness;
	uniform float viewWidth, viewHeight;
	uniform float far;

	#ifdef ENABLE_DARKNESS_EFFECT
		#if MC_VERSION >= 11900
			uniform float darknessFactor;
			uniform float darknessLightFactor;
		#endif
	#endif

	uniform ivec2 eyeBrightnessSmooth;

	uniform vec3 cameraPosition;
	uniform vec4 entityColor;

	uniform mat4 gbufferProjectionInverse;
	uniform mat4 gbufferModelViewInverse;
	uniform mat4 shadowProjection;
	uniform mat4 shadowModelView;

	uniform sampler2D texture;

	#if (defined OVERWORLD  && defined WATER_CAUSTICS)
		uniform sampler2D noisetex;
	#endif

	#ifdef ADVANCED_MATERIALS
		uniform ivec2 atlasSize;
		uniform sampler2D specular;
		uniform sampler2D normals;
	#endif

	uniform vec3 fogColor;

	//Common Variables//

	float eBS              =eyeBrightnessSmooth.y / 240.0;
	float sunVisibility    =clamp00125(dot( sunVec,upVec) + 0.0625) * 8.0;
	float moonVisibility   =clamp00125(dot( -sunVec,upVec) + 0.0625) * 8.0;
	float screenBrightness2=clamp01(screenBrightness);

	#ifdef ADVANCED_MATERIALS
		vec2 dcdx = dFdx(texCoord);
		vec2 dcdy = dFdy(texCoord);
	#endif

	#ifdef OVERWORLD
		vec3 lightVec = sunVec * ((timeAngle < 0.5325 || timeAngle > 0.9675) ? 1.0 : -1.0);
	#else
		vec3 lightVec = sunVec;
	#endif

	//Common Functions//
	float GetLuminance(vec3 color){
		return dot(color,vec3(0.299, 0.587, 0.114));
	}

	//Includes//
	#include "/lib/color/blocklightColor.glsl"
	#include "/lib/color/dimensionColor.glsl"
	#include "/lib/color/specularColor.glsl"
	#include "/lib/util/dither.glsl"
	#include "/lib/util/spaceConversion.glsl"

	#if (defined OVERWORLD  && defined WATER_CAUSTICS)
	#include "/lib/color/waterColor.glsl"
	#include "/lib/lighting/caustics.glsl"
	#endif

	#include "/lib/lighting/forwardLighting.glsl"

	#ifdef ADVANCED_MATERIALS
	#include "/lib/util/encode.glsl"
	#include "/lib/surface/ggx.glsl"
	#include "/lib/reflections/complexFresnel.glsl"
	#include "/lib/surface/materialGbuffers.glsl"
	#include "/lib/surface/parallax.glsl"
	#endif

	#ifdef NORMAL_SKIP
		#undef PARALLAX
		#undef SELF_SHADOW
	#endif

	#ifdef TECHNO_XP
	#include "/lib/color/hue.glsl"
	#endif

	//Program//
	void main(){

		vec4 multiplier = color;

		if (entityId == 10002 && color.g > color.b + 0.1) {

			#ifdef TECHNO_XP

				float variant = floor(texCoord.x * 4.0) + floor(texCoord.y * 4.0) * 4.0;
				multiplier = vec4(hue2(frameTimeCounter * 0.5 + variant * 0.1), 1.0);

				#ifndef ADVANCED_MATERIALS
				multiplier.rgb *=XP_ORB_INTENSITY;
				#else
				multiplier.rgb *=XP_ORB_INTENSITY;
				#endif

			#else

			multiplier.a = 1.0;

			#endif
		}

		vec4 albedo = texture2D(texture, texCoord) * multiplier;

		vec3  newNormal    =normal;
		float smoothness   =0.0;
		float isGlowing    =0.0;
		float skyOcclusion =0.0;
		float lightningBolt=float(entityId == 22258);

			if(lightningBolt > 0.5) {
				#ifdef OVERWORLD
				albedo.rgb = weatherCol.rgb / weatherCol.a;
				albedo.rgb *= albedo.rgb * albedo.rgb;
				#endif
				#ifdef NETHER
				albedo.rgb = sqrt(netherCol.rgb / netherCol.a);
				#endif
				#ifdef END
				albedo.rgb = endCol.rgb / endCol.a;
				#endif
				albedo.a = 1.0;
			}

		#ifdef ADVANCED_MATERIALS
			vec2  newCoord    =vTexCoord.st * vTexCoordAM.pq + vTexCoordAM.st;
			float surfaceDepth=1.0;
			float parallaxFade=clamp01((dist - PARALLAX_DISTANCE) / 32.0);
			float skipAdvMat  =float(entityId == 10100 || entityId == 10002 || entityId == 10312 || entityId == 10315);

			#ifdef PARALLAX
				if (skipAdvMat < 0.5 ){
					newCoord = GetParallaxCoord(parallaxFade, surfaceDepth);
					albedo = texture2DGradARB(texture, newCoord, dcdx, dcdy) * color;
				}
			#endif

		vec3 fresnel3 = vec3(0.0);

		#endif

		albedo.rgb = mix(albedo.rgb, entityColor.rgb, entityColor.a);

		if (albedo.a > 0.00001 && lightningBolt < 0.5){
			if (albedo.a > 0.99) albedo.a = 1.0;

			vec2  lightmap       =clampVec2_01(lmCoord);
			float metalness      =0.0;
			float emission       =float(entityColor.a > 0.05) * 0.125;
			float subsurface     =0.0;
			vec3  rawAlbedo      =vec3(0.0);
			vec3  baseReflectance=vec3(0.04);

			emission *= dot(albedo.rgb, albedo.rgb) * 0.333;

			#ifdef FLASH_VICTIME

				bool flash = false;

				#ifdef FLASH_SWORD
					if((heldItemId==10278) || (heldItemId==10267) || ( heldItemId == 10268) || (heldItemId == 10272) || (heldItemId == 10276) || (heldItemId == 10283) ||
					(heldItemId2==10278) || (heldItemId2==10267) || ( heldItemId2 == 10268) || (heldItemId2 == 10272) || (heldItemId2 == 10276) || (heldItemId2 == 10283))
					flash = true;
				#endif

				#ifdef FLASH_AXE
					if((heldItemId==10746) || (heldItemId==10279) || ( heldItemId == 10286) || (heldItemId == 10258) || (heldItemId == 10275) || (heldItemId == 10271) ||
					(heldItemId2==10746) || (heldItemId2==10279) || ( heldItemId2 == 10286) || (heldItemId2 == 10258) || (heldItemId2 == 10275) || (heldItemId2 == 10271))
						flash = true;
				#endif
				#ifdef FLASH_BOW
					if((heldItemId==10262) || (heldItemId == 10261) ||
					(heldItemId2==10262) || (heldItemId2 == 10261))
						flash = true;
				#endif
				#ifdef FLASH_TRIDENT
					if((heldItemId == 19999)||
					(heldItemId2 == 19999))
						flash = true;
				#endif
				#ifdef FLASH_SNOWBALL
					if((heldItemId == 10332 ||
						heldItemId2 == 10332 ))
						flash = true;
				#endif
				#ifdef FLASH_FISHING
					if((heldItemId == 10346) ||
						(heldItemId2 == 10346))
						flash = true;
				#endif
				#ifdef FLASH_EGG
					if((heldItemId == 10344 ||
						heldItemId2 == 10344))
						flash = true;
				#endif
					if(flash)
					{
						if(entityId != 10401 && entityId != 10311 && entityId != 10312 && entityId !=10313 && entityId != 10187 && entityId != 10002)	{

							float oscillation = 0;

							#ifdef OSCILLATION
								oscillation = sin(frameTimeCounter * OSCILLATION_SPEED);
								oscillation = oscillation * oscillation;
							#endif

							emission = mix(INTENSITE_FLASH_VICTIME / 10.0, emission, oscillation);
						}
					}
			#endif

			if (entityId == 18213) lightmap.x *= 0.8;

			vec3  screenPos      =vec3(gl_FragCoord.xy / vec2(viewWidth, viewHeight), gl_FragCoord.z);
			vec3  viewPos        =ScreenToView(screenPos);
			vec3  worldPos       =ViewToWorld(viewPos);
			float lViewPos       =length(viewPos.xyz);
			float lViewPosToLight=lViewPos;

			#ifdef ADVANCED_MATERIALS

				float f0 = 0.0, porosity = 0.5, ao = 1.0;
				vec3 normalMap = vec3(0.0, 0.0, 1.0);
				GetMaterials(smoothness, metalness, f0, emission, subsurface, porosity, ao, normalMap, newCoord, dcdx, dcdy);

				#ifdef NORMAL_SKIP
					normalMap = vec3(0.0, 0.0, 1.0);
				#endif

				mat3 tbnMatrix = mat3(tangent.x, binormal.x, normal.x,
									tangent.y, binormal.y, normal.y,
									tangent.z, binormal.z, normal.z);

				if (normalMap.x > -0.999 && normalMap.y > -0.999 && skipAdvMat < 0.5)
				newNormal = clampVec3Inv_11(normalize(normalMap.xyz * tbnMatrix));

			#endif

			albedo.rgb = pow(albedo.rgb, vec3(2.2));

			#ifdef WHITE_WORLD
				#ifdef ENTITIESW
					albedo.rgb = vec3(0.5);
				#endif
			#endif

			#ifdef BLACK_WORLD
				#ifdef ENTITIESW
					albedo.rgb = vec3(0.0);
				#endif
			#endif

			#ifdef GBUFFERS_ENTITIES_GLOWING
				lViewPosToLight = 999999.0;
			#endif

			float NoL            =clamp01(dot(newNormal, lightVec) * 1.01 - 0.01);
			float NoU            =clampInv11(dot(newNormal, upVec));
			float NoE            =clampInv11(dot(newNormal, eastVec));
			float vanillaDiffuse =(0.25 * NoU + 0.75) + (0.667 - abs(NoE)) * (1.0 - abs(NoU)) * 0.15;
			      vanillaDiffuse*=vanillaDiffuse;

			float parallaxShadow = 1.0;

			#ifdef ADVANCED_MATERIALS
				rawAlbedo = albedo.rgb * 0.999 + 0.001;
				albedo.rgb *= ao;

				#ifdef REFLECTION_SPECULAR
					albedo.rgb *= 1.0 - metalness * smoothness * 0.65;
				#endif

				float doParallax = 0.0;

				#ifdef SELF_SHADOW

					#ifdef OVERWORLD
						doParallax = float(lightmap.y > 0.0 && NoL > 0.0);
					#endif

					#ifdef END
						doParallax = float(NoL > 0.0);
					#endif

					if (doParallax > 0.5){
						parallaxShadow = GetParallaxShadow(surfaceDepth, parallaxFade, newCoord, lightVec, tbnMatrix);
					}

				#endif
			#endif

			vec3 shadow = vec3(0.0);
			GetLighting(albedo.rgb, shadow, viewPos, worldPos, lightmap, 1.0, NoL, vanillaDiffuse,
			parallaxShadow, emission, subsurface, 0.0, 1.0);

			#ifdef ADVANCED_MATERIALS

				skyOcclusion=lightmap.y * lightmap.y * (3.0 - 2.0 * lightmap.y);

				      baseReflectance=mix(vec3(f0), rawAlbedo, metalness);

				float fresnel        =pow(clamp01(1.0 + dot(newNormal, normalize(viewPos.xyz))), 5.0);

				fresnel3 = mix(baseReflectance, vec3(1.0), fresnel);

				#if MATERIAL_FORMAT == 1

					if (f0 >= 0.9 && f0 < 1.0) {
						baseReflectance = GetMetalCol(f0);
						fresnel3 = ComplexFresnel(pow(fresnel, 0.2), f0);
						#ifdef ALBEDO_METAL
						fresnel3 *= rawAlbedo;
						#endif
					}

				#endif

				float aoSquared  =ao * ao;
				      shadow    *=aoSquared; fresnel3*=aoSquared;
				      albedo.rgb =albedo.rgb * (1.0 - fresnel3 * smoothness * smoothness * (1.0 - metalness));

				#if (defined OVERWORLD || defined END) && (defined ADVANCED_MATERIALS || defined SPECULAR_HIGHLIGHT_ROUGH)

					vec3 specularColor = GetSpecularColor(lightmap.y, metalness, baseReflectance);

					albedo.rgb += GetSpecularHighlight(newNormal, viewPos, lightVec, smoothness, baseReflectance,
													specularColor, shadow * vanillaDiffuse, 1.0);

				#endif

				#if defined ADVANCED_MATERIALS && defined REFLECTION_SPECULAR && defined REFLECTION_ROUGH

					normalMap = mix(vec3(0.0, 0.0, 1.0), normalMap, smoothness);
					newNormal = clampVec3Inv_11(normalize(normalMap * tbnMatrix));

				#endif

			#endif

			#if (defined OVERWORLD  && defined WATER_CAUSTICS)
			#include "/lib/lighting/causticsCall.glsl"
			#endif

			#ifdef END
				albedo.rgb = pow(albedo.rgb, vec3(0.9));
			#endif

		}else{

		}

		#ifdef GBUFFERS_ENTITIES_GLOWING
			if (albedo.a > 0.99) isGlowing = 1.0;
		#endif

		/*DRAWBUFFERS:037*/
		#ifdef DEBUG_ENTITIES
            gl_FragData[0]=vec4(1.0, 0.0, 0.0, 0.75);
		#else
			gl_FragData[0] = vec4(albedo);
		#endif

		gl_FragData[1] = vec4(smoothness, skyOcclusion, isGlowing, 1.0);
		gl_FragData[2] = vec4(1.0);

		#if defined ADVANCED_MATERIALS && defined REFLECTION_SPECULAR

		/*DRAWBUFFERS:03761*/
		gl_FragData[3] = vec4(EncodeNormal(newNormal), float(gl_FragCoord.z < 1.0), 1.0);
		gl_FragData[4] = vec4(fresnel3, 1.0);

		#endif
	}

#endif

//Vertex Shader/////////////////////////////////////////////////////////////////////////////////////
#ifdef VSH

	//Uniforms//
	uniform int entityId;

	uniform float frameTimeCounter;
	uniform int heldItemId;
	uniform int heldItemId2;
	uniform vec3 cameraPosition;

	uniform mat4 gbufferModelView,gbufferModelViewInverse;

	//Attributes//

	#ifdef ADVANCED_MATERIALS
		attribute vec4 mc_midTexCoord;
		attribute vec4 at_tangent;
	#endif

	//Common Variables//
	#ifdef OVERWORLD
		float timeAngleM = timeAngle;
	#else
		float timeAngleM = 0.25;
	#endif

	//Program//
	void main(){
		texCoord=(gl_TextureMatrix[0]*gl_MultiTexCoord0).xy;

		lmCoord=(gl_TextureMatrix[1]*gl_MultiTexCoord1).xy;
		lmCoord=clamp01((lmCoord - 0.03125) * 1.06667);

		normal=normalize(gl_NormalMatrix*gl_Normal);

		#ifdef ADVANCED_MATERIALS
			tangent =normalize(gl_NormalMatrix * at_tangent.xyz);
			binormal=normalize(gl_NormalMatrix * cross(at_tangent.xyz, gl_Normal.xyz) * at_tangent.w);

			mat3 tbnMatrix=mat3(tangent.x,binormal.x,normal.x,
								tangent.y,binormal.y,normal.y,
								tangent.z,binormal.z,normal.z);

			viewVector=tbnMatrix * (gl_ModelViewMatrix * gl_Vertex).xyz;

			dist=length(gl_ModelViewMatrix * gl_Vertex);

			vec2 midCoord      =(gl_TextureMatrix[0] * mc_midTexCoord).st;
			vec2 texMinMidCoord=texCoord - midCoord;
			vTexCoord.xy=sign(texMinMidCoord) * 0.5 + 0.5;

			vTexCoordAM.pq=abs(texMinMidCoord) * 2;
			vTexCoordAM.st=min(texCoord, midCoord - texMinMidCoord);

		#endif

		color=gl_Color;

		const vec2 sunRotationData=vec2(cos(sunPathRotation * 0.01745329251994), -sin(sunPathRotation * 0.01745329251994));
		float ang                 =fract(timeAngleM - 0.25);
		      ang                 =(ang+(cos(ang * 3.14159265358979) * -0.5 + 0.5 - ang) / 3.0) * 6.28318530717959;
		      sunVec              =normalize((gbufferModelView * vec4(vec3(-sin(ang), cos(ang) * sunRotationData) * 2000.0, 1.0)).xyz);

		upVec  =normalize(gbufferModelView[1].xyz);
		eastVec=normalize(gbufferModelView[0].xyz);

		gl_Position = ftransform();

		if (entityId == 10312) {
				if (dot(normal, upVec) > 0.99) {
					vec4 position=gbufferModelViewInverse * gl_ModelViewMatrix * gl_Vertex;
					vec3 LexPos  =fract(position.xyz + cameraPosition);
					     LexPos  =abs(LexPos - vec3(0.5));
					if ((LexPos.y > 0.437 && LexPos.y < 0.438) || (LexPos.y > 0.468 && LexPos.y < 0.469)) {
						gl_Position.z+=0.0001;
					}
				}
			}

		#ifdef GBUFFERS_ENTITIES_GLOWING
			if (color.a > 0.99) gl_Position.z *= 0.01;
		#endif

	}

#endif