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

//Varyings//
varying vec2 texCoord;
varying vec3 sunVec, upVec;

//Fragment Shader///////////////////////////////////////////////////////////////////////////////////

#ifdef FSH

	//Uniforms//
	uniform sampler2D colortex0;
	uniform sampler2D colortex1;
	uniform sampler2D depthtex0;
	uniform sampler2D depthtex1;
	uniform sampler2D noisetex;

	uniform int isEyeInWater;

	uniform float nightVision;
	uniform float blindFactor;
	uniform float far, near;
	uniform float frameTimeCounter;

	uniform float rainStrengthS;
	uniform float screenBrightness;
	uniform float viewWidth, viewHeight, aspectRatio;

	uniform ivec2 eyeBrightnessSmooth;

	uniform vec3 cameraPosition;

	uniform mat4 gbufferProjection, gbufferProjectionInverse;
	uniform mat4 gbufferModelView, gbufferModelViewInverse;
	uniform mat4 shadowModelView;
	uniform mat4 shadowProjection;

	uniform vec3 fogColor;

	#if (defined OVERWORLD || defined END) && defined LIGHT_SHAFT
		uniform sampler2DShadow shadowtex0;
		uniform sampler2DShadow shadowtex1;
		uniform sampler2D shadowcolor0;
	#endif


	//Optifine Constants//
	const bool colortex0Clear  = true;
	const bool colortex1Clear  = true;
	const bool colortex2Clear  = false;
	const bool colortex3Clear  = true;
	const bool colortex5Clear  = false;
	const bool colortex9Clear  = true;
	const bool colortex10Clear = true;
	const bool colortex11Clear = true;
	const bool gaux1Clear      = false;
	const bool gaux2Clear      = false;
	const bool gaux3Clear      = false;
	const bool gaux4Clear      = true;

	//Common Variables//
	float eBS = eyeBrightnessSmooth.y / 240.0;
	float eBS2 = clamp01(pow(eBS,8.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);

	vec3 lightVec = sunVec * (1.0 - 2.0 * float(timeAngle > 0.5325 && timeAngle < 0.9675));

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

	float GetLinearDepth(float depth) {
		return (2.0 * near) / (far + near - depth * (far - near));
	}

	#if (defined OVERWORLD || defined END) && defined LIGHT_SHAFT
		float GetDepth(float depth) {
			return 2.0 * near * far / (far + near - (2.0 * depth - 1.0) * (far - near));
		}

		float GetDistX(float dist) {
			return (far * (dist - near)) / (dist * (far - near));
		}
	#endif

	//Includes//
	#if defined NETHER || defined END
	#include "/lib/color/lightColor.glsl"
	#endif

	#include "/lib/color/dimensionColor.glsl"
	#include "/lib/color/waterColor.glsl"
	#include "/lib/util/dither.glsl"
	#include "/lib/atmospherics/waterFog.glsl"
	#include "/lib/util/spaceConversion.glsl"

	#ifdef LIGHT_SHAFT
	#include "/lib/atmospherics/volumetricLight.glsl"
	#endif

	#ifdef OUTLINE_ENABLED
	#include "/lib/color/skyColor.glsl"
	#include "/lib/color/blocklightColor.glsl"
	#include "/lib/outline/outlineOffset.glsl"
	#include "/lib/outline/outlineMask.glsl"
	#include "/lib/atmospherics/sky.glsl"
	#include "/lib/atmospherics/fog.glsl"
	#include "/lib/outline/blackOutline.glsl"
	#endif

	//Program//
	void main(){
		vec4  color      =texture(colortex0, texCoord);
		vec3  translucent=texture(colortex1,texCoord).rgb;
		vec3  worldPos   =vec3(0.0);
		float z0         =texture(depthtex0, texCoord).r;
		float z1         =texture(depthtex1, texCoord).r;

		bool water = false;

		if (translucent.b > 0.999 && z1 > z0) {
			water       = true;
			translucent = vec3(1.0);
		}

		vec4 viewPos = gbufferProjectionInverse * (vec4(texCoord, z0, 1.0) * 2.0 - 1.0);
		viewPos /= viewPos.w;

		#ifdef WATER_REFRACTION

			if (water){
				worldPos = ViewToWorld(viewPos.xyz);

				vec3 worldPosWF=worldPos.xyz + cameraPosition.xyz;
				vec2 PosRF     =worldPosWF.xz * 0.005 + worldPosWF.y * 0.0025 + 0.0045 * WATER_SPEED * frameTimeCounter;

				float hand    =1.0 - float(z0 < 0.56);//Detection mains
				float d0      =GetLinearDepth(z0);
				float fovScale=gbufferProjection[1][1] / 1.37;
				float ScaleWF =fovScale;

				float distScaleRF =max((far - near) * d0 + near, 14.0);
				      ScaleWF    *=2.0 / distScaleRF;

				vec2 NoiseRF =texture(noisetex, PosRF).rb;//Texture noise
					 NoiseRF.r -= 0.45;
					 NoiseRF.g -= 0.58;

				     NoiseRF*=vec2(0.07 * hand * ScaleWF);
				vec2 CoordRF =texCoord.xy + NoiseRF;

				float Wateraim=float(texture(colortex1, CoordRF).b > 0.999);
				float z0aim     =texture(depthtex0, CoordRF).r;
				float z1aim     =texture(depthtex1, CoordRF).r;

				float depthDif =GetLinearDepth(z1aim) - GetLinearDepth(z0aim);
				      NoiseRF *=clamp01(depthDif * 150.0);

				if (z0aim >= 0.56 && Wateraim > 0.95){

					CoordRF = texCoord.xy + NoiseRF;

					color.rgb = texture(colortex0, CoordRF).rgb;

				//Water Surface
					if (isEyeInWater == 1) {
						      translucent                         = texture(colortex1, CoordRF).rgb;
						   if (translucent.b < 0.999) translucent = vec3(1.0);
						      z0                                  = texture(depthtex0, CoordRF).r;
						      z1                                  = texture(depthtex1, CoordRF).r;
					}

				}
				//Petit debug pour detecter l'eau avec la texture
				//color.rgb = vec3(NoiseRF,0.0);
			}
		#endif

		#ifdef OUTLINE_ENABLED
			vec4  outerOutline=vec4(0.0), innerOutline=vec4(0.0);
			float outlineMask =GetOutlineMask();
			if (outlineMask > 0.5 || isEyeInWater > 0.5)
				Outline(color.rgb, true, outerOutline, innerOutline);

			#if PROMO_OUTLINE_EVERYWHERE > 0
				if(z1 > z0) color.rgb=mix(color.rgb, innerOutline.rgb, innerOutline.a);
			#endif
		#endif

		if (isEyeInWater == 1.0) {
			vec4 waterFog   =GetWaterFog(viewPos.xyz);
			     waterFog.a =mix(waterAlpha * 0.1, 1.0, waterFog.a);
			     color.rgb  =mix(sqrt(color.rgb), sqrt(waterFog.rgb), waterFog.a);
			     color.rgb *=color.rgb;
		}

		#ifdef LIGHT_SHAFT
			#ifdef OVERWORLD
				vec3  nViewPos = normalize(viewPos.xyz);
				float cosS     = dot(nViewPos, lightVec);
			#else
				float cosS = 0.0;
			#endif
		#endif

		#if (defined OVERWORLD || defined END) && defined LIGHT_SHAFT

		vec3  vlAlbedo                              = translucent;
		float dither                                = InterleavedGradientNoise(gl_FragCoord.xy);
		if    (isEyeInWater == 0 && water) vlAlbedo = vec3(0.0);
		float depth0                                = GetDepth(z0);
		float depth1                                = GetDepth(z1);
		vec3  vl                                    = getVolumetricRays(depth0, depth1, vlAlbedo, dither, cosS);
		#else
		 	vec3 vl = vec3(0.0);
		#endif

		#ifdef OUTLINE_ENABLED
			color.rgb = mix(color.rgb, outerOutline.rgb, outerOutline.a);
		#endif

		/*DRAWBUFFERS:01*/
		gl_FragData[0] = vec4(color);
		gl_FragData[1] = vec4(vl, 1.0);


	}

#endif

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

	//Uniforms//

	uniform mat4 gbufferModelView;

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

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

		gl_Position=ftransform();

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

#endif
