//Settings//
#include "/lib/settings.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 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(inout vec4 albedo, 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.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 +=texture(noisetex,noiseCoord*lacunarity).r*persistance;
				else{
					      noise    +=texture(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 = texture(tex, texCoord.xy);
		albedo.rgb*=color.rgb;

		float dither = InterleavedGradientNoise(gl_FragCoord.xy);

		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 COLORED_SHADOWS || defined OVERWORLD
			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(albedo, 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(albedo, dither);
				}
			}

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

		/*DRAWBUFFERS:0*/
			gl_FragData[0] = clampVec4_01(albedo);
	}

#endif

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

	//Uniforms//

	uniform float frameTimeCounter;

	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; //Premult
		if (mc_Entity.x == 10300) mat = 2; // Water Block
		if (mc_Entity.x == 10302) mat = 3; // ice Block

		float istopv      =gl_MultiTexCoord0.t < mc_midTexCoord.t ? 1.0 : 0.0;
		float skylight    =(gl_TextureMatrix[1] * gl_MultiTexCoord1).y;
		      skylight    =clamp01((skylight - 0.03125) * 1.06667);
		      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 == 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) {

			#ifdef SHADOW_SUBSURFACE

				#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