/*
BSLex (BSL Edit) by LexBoosT
*/

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

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

//Varyings//
varying float mat;

varying vec2 texCoord,lmCoord;

varying vec4 color;
varying vec4 position;

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

uniform vec3 fogColor;
uniform vec3 cameraPosition;

uniform sampler2D tex;
uniform sampler2D noisetex;
uniform float shadowFade;
uniform float rainStrength;
uniform float frameTimeCounter;
uniform int worldTime;
//Common Variables//

//Includes//
#include "/lib/color/waterColor.glsl"

#ifdef WATER_CAUSTICS
#ifdef OVERWORLD
#include "/lib/lighting/caustics.glsl"
#endif
#endif

//Common Functions//
void doWaterShadowCaustics(inout vec4 albedo){
	#if defined(OVERWORLD)&&defined WATER_CAUSTICS
	vec3 worldPos=position.xyz+cameraPosition.xyz;
	worldPos*=.5;
	float noise=0.;
	float mult=.5;
	
	vec2 wind=vec2(frameTimeCounter)*.3;
	float verticalOffset=worldPos.y*.2;
	
	if(mult>.01){
		float lacunarity=1./750.,persistance=1.,weight=0.;
		
		mult*=(lmCoord.y*.9+.1);
		
		for(int i=0;i<8;i++){
			float windSign=mod(i,2)*2.-1.;
			vec2 noiseCoord=worldPos.xz+wind*windSign-verticalOffset;
			if(i<7)noise+=texture2D(noisetex,noiseCoord*lacunarity).r*persistance;
			else{
				noise+=texture2D(noisetex,noiseCoord*lacunarity*.125).r*persistance*10.;
				noise=-noise;
				float noisePlus=1.+.125*-noise;
				noisePlus*=noisePlus;
				noisePlus*=noisePlus;
				noise*=noisePlus;
			}
			
			if(i==0)noise=-noise;
			
			weight+=persistance;
			lacunarity*=1.50;
			persistance*=.60;
		}
		noise*=mult/weight;
	}
	#ifndef SHADOW_COLOR
	float discardFactor=.025;
	if(noise>discardFactor||noise<-discardFactor)discard;
	#else
	albedo.rgb=sqrt(albedo.rgb);
	float noiseFactor=1.1+noise;
	noiseFactor=pow(noiseFactor,10.);
	albedo.rgb*=noiseFactor;
	#endif
	#else
	discard;
	#endif
}

//Program//
void main(){
	#if MC_VERSION>=11300
	if(blockEntityId==10250)discard;
	#endif
	
	vec4 albedo=texture2D(tex,texCoord.xy);
	
	#ifndef SHADOW_COLOR
	if(albedo.a<.0001)discard;
	#endif
	
	albedo.rgb*=color.rgb;
	
	float premult=float(mat>.98&&mat<1.02);
	float ice=float(mat>1.48&&mat<1.52);
	float water=float(mat>1.98&&mat<2.02);
	if(water>.5||albedo.a<.01)discard;
	
	#ifdef SHADOW_COLOR
	albedo.rgb=mix(vec3(1.),albedo.rgb,pow(albedo.a,(1.-albedo.a)*.5)*1.05);
	albedo.rgb*=1.-pow(albedo.a,64.);
	
	if(water>.5){
		if(isEyeInWater<.5){
			vec3 waterShadowColor=waterColor.rgb*waterColor.rgb;
			waterShadowColor*=waterShadowColor;
			waterShadowColor*=waterShadowColor;
			albedo.rgb=waterShadowColor;
			float maxWater=max(waterShadowColor.b,max(waterShadowColor.r,waterShadowColor.g));
			albedo.rgb*=(1./maxWater);
		}else{
			
			doWaterShadowCaustics(albedo);
		}
	}
	
	if(ice>.5){
		if(isEyeInWater<.5){
			albedo.rgb*=albedo.rgb*albedo.rgb;
		}else{
			discard;
		}
	}
	#else
	if(water>.5){
		if(isEyeInWater<.5){
			
		}else{
			doWaterShadowCaustics(albedo);
		}
	}
	if(premult>.5){
		if(albedo.a<.51)discard;
	}
	#endif
	
	#ifdef SHADOW_COLOR
	gl_FragData[0]=clamp(albedo,vec4(0.),vec4(1.));
	#endif
}

#endif

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

//Varyings//
varying float mat;

varying vec2 texCoord,lmCoord;

#ifdef SHADOW_BACKFACE_CULLING
varying vec3 normal;
#endif

varying vec4 color;
varying vec4 position;

//Uniforms//
uniform int worldTime;

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;

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

#ifdef WORLD_CURVATURE
#include "/lib/vertex/worldCurvature.glsl"
#endif

//Program//
void main(){
	texCoord=gl_MultiTexCoord0.xy;
	color=gl_Color;
	
	lmCoord=(gl_TextureMatrix[1]*gl_MultiTexCoord1).xy;
	lmCoord=clamp((lmCoord-.03125)*1.06667,0.,1.);
	
	mat=0;
	if(mc_Entity.x==10301)mat=1.5;
	if(mc_Entity.x==10300||mc_Entity.x==10249||mc_Entity.x==10252)mat=2;
	if(mc_Entity.x==10100||mc_Entity.x==10105||mc_Entity.x==10102||mc_Entity.x==10103||mc_Entity.x==10104)mat=3;
	
	vec4 position=shadowModelViewInverse*shadowProjectionInverse*ftransform();
	
	float istopv=gl_MultiTexCoord0.t<mc_midTexCoord.t?1.:0.;
	float skylight=(gl_TextureMatrix[1]*gl_MultiTexCoord1).y;
	skylight=clamp((skylight-.03125)*1.06667,0.,1.);
	position.xyz=WavingBlocks(position.xyz,istopv,skylight);
	
	#ifdef WORLD_CURVATURE
	position.y-=WorldCurvature(position.xz);
	#endif
	
	#ifdef MOUVEMENT_CAM
	position+=vec4(.03*sin(frameTimeCounter*3.),.015*cos(frameTimeCounter*4.),0.,0.)*gbufferModelView;
	#endif
	
	gl_Position=shadowProjection*shadowModelView*position;
	
	#ifdef SHADOW_BACKFACE_CULLING
	normal=gl_NormalMatrix*gl_Normal;
	if(normal.z<0.){
		gl_Position=vec4(-1.);
		return;
	}
	#endif
	
	float dist=sqrt(gl_Position.x*gl_Position.x+gl_Position.y*gl_Position.y);
	float distortFactor=dist*shadowMapBias+(1.-shadowMapBias);
	
	gl_Position.xy*=1./distortFactor;
	gl_Position.z=gl_Position.z*.2;
}

#endif