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

//Settings//
#include "/lib/settings.glsl"

//Varyings//
varying float mat;

varying vec2 texCoord;

#if defined(OVERWORLD) && defined WATER_CAUSTICS
varying vec2 lmCoord;
varying vec4 position;
#endif

varying vec4 color;

varying vec3 sunVec;

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

//Uniforms//
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/util/dither.glsl"

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

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

	#if defined(OVERWORLD) && defined WATER_CAUSTICS
	vec3 worldPos=position.xyz+cameraPosition.xyz;
	worldPos*=0.5;
	float noise=0.0;
	float mult=0.5;
	
	vec2 wind=vec2(frameTimeCounter*0.2);
	float verticalOffset=worldPos.y*0.2;
	
	if(mult>0.01){
		float numberRays=UNDERWATER_LIGHTSHAFT_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,10.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 = vec4(0.0);

	#ifdef WRONG_MIPMAP_FIX
		#if !defined COLORED_SHADOWS || !defined OVERWORLD
  			albedo.a = texture2DLod(tex, texCoord.xy, 0.0).a;
		#else
  			albedo = texture2DLod(tex, texCoord.xy, 0.0);
		#endif
	#else
		#if !defined COLORED_SHADOWS || !defined OVERWORLD
			albedo.a = texture2D(tex, texCoord.xy).a;
		#else
			albedo = texture2D(tex, texCoord.xy);
		#endif
	#endif
	
	if (blockEntityId == 10888) {
		if (color.r >0.1) discard;
	}

	float dither = InterleavedGradientNoise(gl_FragCoord.xy);

	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);
	
	vec4 albedo0 = albedo;
	if (water > 0.5) {
		if (isEyeInWater < 0.5) {
			albedo0 = vec4(1.0, 1.0, 1.0, 1.0);
			albedo = vec4(0.0, 0.0, 0.0, 1.0);
		} else {
			float dither = Bayer64(gl_FragCoord.xy);
			doWaterShadowCaustics(dither);
		}
	} else albedo0.rgb = vec3(0.0);

	#if !defined COLORED_SHADOWS || !defined OVERWORLD
	if (premult > 0.5) {
		if (albedo.a < 0.51) discard;
	}
	#endif
	
	gl_FragData[0]=clamp(albedo,vec4(0.0),vec4(1.0));

	#if defined COLORED_SHADOWS && defined OVERWORLD
		vec4 albedoCS = albedo;
		albedoCS.rgb *= 1.0 - albedo.a * albedo.a;

		if (ice > 0.5) albedoCS = vec4(0.0, 0.0, 0.0, 1.0);

		gl_FragData[1] = clamp(albedoCS, vec4(0.0), vec4(1.0));
	#endif
}

#endif

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

//Uniforms//

uniform float frameTimeCounter;

uniform vec3 cameraPosition;

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

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

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

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

#if !defined(OVERWORLD) || !defined WATER_CAUSTICS
vec4 position;
vec2 lmCoord;
#endif

//Program//
void main(){
	texCoord=gl_MultiTexCoord0.xy;
	color=gl_Color;
	
	lmCoord=(gl_TextureMatrix[1]*gl_MultiTexCoord1).xy;
	lmCoord = clamp((lmCoord - 0.03125) * 1.06667, vec2(0.0), vec2(0.9333, 1.0));
	
	position=shadowModelViewInverse*shadowProjectionInverse*ftransform();
	
	mat=0;

	if (mc_Entity.x == 10301) mat = 1; //premult
	if (mc_Entity.x == 10300) mat = 2; // water
	if (mc_Entity.x == 10302) mat = 3; //ice
	
	float istopv=gl_MultiTexCoord0.t<mc_midTexCoord.t?1.0:0.0;
	float skylight=(gl_TextureMatrix[1]*gl_MultiTexCoord1).y;
	skylight=clamp((skylight-0.03125)*1.06667,0.0,1.0);
	position.xyz=WavingBlocks(position.xyz,istopv,skylight);
	
	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 == 10100 || mc_Entity.x == 10101 || mc_Entity.x == 10102 ||
	    mc_Entity.x == 10103 || mc_Entity.x == 10104 || mc_Entity.x == 10105 ||
		mc_Entity.x == 10106 || mc_Entity.x == 10107 || mc_Entity.x == 10108 ||
		mc_Entity.x == 10109 || mc_Entity.x == 10110 || mc_Entity.x == 10111 ||
		mc_Entity.x == 10112 || mc_Entity.x == 10113) {

			const vec2 sunRotationData=vec2(cos(sunPathRotation*.01745329251994),-sin(sunPathRotation*.01745329251994));
			float ang=fract(timeAngleM-.25);
			ang=(ang+(cos(ang*3.14159265358979)*-.5+.5-ang)/3.)*6.28318530717959;
			sunVec=normalize((gbufferModelView*vec4(vec3(-sin(ang),cos(ang)*sunRotationData)*2000.,1.)).xyz);

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

			vec3 upVec = normalize(gbufferModelView[1].xyz);
			float NdotLm = clamp(dot(upVec, lightVec) * 1.01 - 0.01, 0.0, 1.0) * 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; //12.0

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

#endif