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

//Settings//

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

#include "/settings/globalSettings.glsl"

//Varyings//
varying float mat;

varying vec2 texCoord;

varying vec3 sunVec, upVec;

varying vec4 color;
varying vec4 position;

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

	//Uniforms//
	uniform int frameCounter;
	uniform int isEyeInWater;
	uniform int blockEntityId;

	uniform vec3 fogColor;
	uniform vec3 cameraPosition;

	uniform sampler2D tex;
	uniform sampler2D noisetex;

	uniform float rainStrengthS;
	uniform float frameTimeCounter;

	//Includes//

	#include "/lib/color/waterColor.glsl"
	#include "/lib/color/endColor.glsl"
	#include "/lib/util/dither.glsl"

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

	//Common Functions//
	void doWaterShadowCaustics(float dither){

		#if (defined OVERWORLD && defined WATER_CAUSTICS && defined COLORED_SHADOWS)
		vec3  worldPos =position.xyz + cameraPosition.xyz;
		      worldPos *= 0.5;
		float noise     = 0.0;
		float mult      = 0.5;

		vec2  wind      =vec2(frameTimeCounter * 0.3);
		float verticalOffset = worldPos.y * 0.2;

		if(mult>0.01){
			float numberRays = UNDERWATER_LIGHT_SHAFT_SIZE;
			float lacunarity = 1.0/numberRays, persistance = 1.0, weight = 0.0;

			for(int i=0;i<8;i++){
				float windSign   =mod(i,2) * 2.0 - 1.0;
				vec2  noiseCoord =worldPos.xz + wind * windSign - verticalOffset;
				if   (i<7)noise +=texture2D(noisetex, noiseCoord * lacunarity).r * persistance;
				else{
					      noise    +=texture2D(noisetex, noiseCoord * lacunarity * 0.125).r * persistance * 10.0;
					      noise     =-noise;
					float noisePlus =1.0 + 0.125 * -noise;
					      noisePlus*=noisePlus;
					      noisePlus*=noisePlus;
					      noise    *=noisePlus;
				}

				if(i==0)noise=-noise;

				weight      += persistance;
				lacunarity  *= 1.50;
				persistance *= 0.60;
			}
			noise*= mult / weight;
		}
			float noiseFactor = 1.1 + noise;
			      noiseFactor = pow(noiseFactor, 20.0);
		if (noiseFactor > 1.0 - dither * 0.5) discard;
		#else
		discard;
		#endif
	}

	//Program//
	void main(){
		#if MC_VERSION>=11300
		if(blockEntityId==10250)discard;
		#endif

		vec4 albedo = texture2D(tex, texCoord.xy);
		albedo.rgb*=color.rgb;

		float dither = InterleavedGradientNoise();

		if (blockEntityId == 10888) {
			if (color.r >0.1) discard;
		}

		if (albedo.a < 0.0001) discard;

		float premult = float(mat > 0.95 && mat < 1.05);
		float water   = float(mat > 1.95 && mat < 2.05);
		float ice     = float(mat > 2.95 && mat < 3.05);

		#if ((defined OVERWORLD || defined END) && defined COLORED_SHADOWS) || (defined OVERWORLD && defined WATER_CAUSTICS) || ((defined OVERWORLD || defined END) && defined LIGHT_SHAFT)
			if (water > 0.5) {
				if (isEyeInWater < 0.5) {
					albedo.rgb = mix(vec3(1.0), albedo.rgb, pow(albedo.a, (1.0 - albedo.a) * 0.5) * 1.05);
					albedo.rgb *= 1.0 - pow(albedo.a, 64.0);
				} else {

					albedo.rgb *= 0.1;
					doWaterShadowCaustics(dither);
				}
			} else {

					albedo.rgb = mix(vec3(1.0), albedo.rgb, pow(albedo.a, (1.0 - albedo.a) * 0.5) * 1.05);
					albedo.rgb *= 1.0 - pow(albedo.a, 64.0);

			}
			if (ice > 0.5) {
				if (isEyeInWater < 0.5) {
					albedo.rgb = mix(vec3(1.0), albedo.rgb, pow(albedo.a, (1.0 - albedo.a) * 0.5) * 1.05);
					albedo.rgb *= 1.0 - pow(albedo.a, 64.0);
				} else {
					discard;
				}
			}
		#else
			if (water > 0.5) {
				if (isEyeInWater < 0.5) {
				} else {
					doWaterShadowCaustics(dither);
				}
			}

			if (premult > 0.5) {
				if (albedo.a < 0.51) discard;
			}
		#endif

		#if (defined OVERWORLD && defined PROJECTED_CAUSTICS)

			if (water > 0.5){
				vec3  worldPos =position.xyz + cameraPosition.xyz;

				float projectedStrenght=PROJECTED_VISIBILITY * 5.0;

				vec3 causticsColor = (waterColorSqrt.rgb + vec3(0.01));
				float caustics = getCausticWaves(worldPos);
				albedo.rgb *= caustics * causticsColor * projectedStrenght+vec3(0.01);

			}

		#endif
			gl_FragData[0] = clampVec4_01(albedo);
	}

#endif

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

	//Uniforms//
	uniform float frameTimeCounter;

	uniform int frameCounter;

	uniform vec3 cameraPosition;

	uniform mat4 gbufferModelView;
	uniform mat4 shadowProjection,shadowProjectionInverse;
	uniform mat4 shadowModelView,shadowModelViewInverse;

	//Attributes//
	attribute vec4 mc_Entity;
	attribute vec4 mc_midTexCoord;

	//Common Variables//

	vec2 lmCoord = vec2(0.0);

	float GetNoise(vec2 pos){
	return fract(sin(dot(pos,vec2(12.9898,4.1414)))*43758.5453);
	}

	//Includes//
	#include "/lib/vertex/waving.glsl"

	//Program//
	void main(){
		texCoord=gl_MultiTexCoord0.xy;
		color=gl_Color;

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

		position=shadowModelViewInverse * shadowProjectionInverse * ftransform();

		mat=0;

		if (mc_Entity.x == 10301 || mc_Entity.x == 10303) mat = 1;
		if (mc_Entity.x == 10300) mat = 2;
		if (mc_Entity.x == 10302) mat = 3;

		float istopv      =gl_MultiTexCoord0.t < mc_midTexCoord.t ? 1.0 : 0.0;
		      position.xyz=WavingBlocks(position.xyz, istopv);

		gl_Position=shadowProjection * shadowModelView * position;

		float dist         =sqrt(gl_Position.x * gl_Position.x + gl_Position.y * gl_Position.y);
		float distortFactor=dist * shadowMapBias + (1.0 - shadowMapBias);

		if (mc_Entity.x == 10102 ||	mc_Entity.x == 10103 || mc_Entity.x == 10104 ||
			mc_Entity.x == 10108 ||	mc_Entity.x == 10109 || mc_Entity.x == 10110 ||
			mc_Entity.x == 10111 ||	mc_Entity.x == 10112 || mc_Entity.x == 10113) {

			#if SHADOW_SUBSURFACE > 0

				#ifdef OVERWORLD
					float timeAngleM = timeAngle;
				#else
					float timeAngleM = 0.25;
				#endif

				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);


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

				float NdotLm=clamp01(dot(upVec, lightVec) * 1.01 - 0.01) * 0.99 + 0.01;

				float distortBias =distortFactor * shadowDistance / 256.0;
				      distortBias*=8.0 * distortBias;
				float biasFactor  =sqrt(1.0 - NdotLm * NdotLm) / NdotLm;
				float bias        =(distortBias * biasFactor + 0.05) / shadowMapResolution;

				gl_Position.z-=bias * FOLIAGE_BIAS_MULTIPLIER;

			#else
				mat = 4;
			#endif
		}

		gl_Position.xy*=1.0/distortFactor;
		gl_Position.z  =gl_Position.z*0.2;
	}

#endif