/*
BSLex (BSL Edit) by LexBoosT
*/

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

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

//Varyings//
varying vec2 texCoord;

//Uniforms//
uniform float viewWidth, viewHeight, aspectRatio;
uniform float centerDepthSmooth;
uniform ivec2 eyeBrightnessSmooth;
uniform mat4 gbufferProjection;

uniform sampler2D colortex0;
uniform sampler2D depthtex1;
uniform sampler2D depthtex0;
uniform mat4 gbufferProjectionInverse;

uniform int isEyeInWater;

//Optifine Constants//
const bool colortex0MipmapEnabled = true;

//Includes//

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

//Common Functions//

vec3 ChromaAberration(vec3 color)
{
	#ifdef CHROMATIC_ABERRATION
	float chromaOffset = CHROMA_STRENGTH /100.0;
	chromaOffset *= pow(distance(texCoord.st, vec2(1.0)), 2.5);
	
	color.r = texture2D(colortex0, texCoord.st + vec2(chromaOffset, 0.0)).r;
	color.g = texture2D(colortex0, texCoord.st).g;
	color.b = texture2D(colortex0, texCoord.st - vec2(chromaOffset, 0.0)).b;
	
	#endif
	return color;
}


vec3 DepthOfField(vec3 color, float z){
	
	#ifdef NETHER
	float DISTANCE_BLUR_STRENGTH = NETHER_DISTANCE_BLUR_STRENGTH;
	float DOF_STRENGTH = NETHER_DOF_STRENGTH;
	#else
	float DISTANCE_BLUR_STRENGTH = OVERWORLD_DISTANCE_BLUR_STRENGTH;
	float DOF_STRENGTH = OVERWORLD_DOF_STRENGTH;
	#endif
	
	vec3 dof = vec3(0.0);
	float hand = float(z < 0.56);
	float fovScale = gbufferProjection[1][1] / 1.37;
	float fovScale2 = gbufferProjection[1][1] / 2.74;
	#ifdef DISTANCE_BLUR
	float z0 = texture2D(depthtex0, texCoord.xy).r;
	vec4 screenPos = vec4(texCoord.x, texCoord.y, z0, 1.0);
	vec4 viewPos = gbufferProjectionInverse * (screenPos * 2.0 - 1.0);
	viewPos /= viewPos.w;
	
	float coc1 = max(min(length(viewPos) * 0.001, 0.1) * DISTANCE_BLUR_STRENGTH / 256, 0.001);
	#else
	float coc1 = 0;
	#endif
	
	#ifdef DOF
	float coc2 = max(abs(z - centerDepthSmooth) * 0.125 * DOF_STRENGTH - 0.0001, 0.001);
	
	#ifdef CIRCULAR_DOF
	float coc2dist = max(clamp(abs(1 - centerDepthSmooth), 0.0, 0.002) * 0.125 * DOF_STRENGTH - 0.001, 0.001);
	float coc2center = max(length((texCoord.xy*2.0-1.0)*vec2(aspectRatio,1.0)),0.001);
	coc2 = max(coc2,coc2dist*coc2center);
	#endif
	
	#else
	float coc2 = 0;
	#endif
	float coc = max(coc1,coc2);
	
	#ifdef FLOU_EAU
	if (float(isEyeInWater) > 0.9) coc = max(FACTEUR_FLOU_EAU / 2 ,coc);
	#endif
	
	coc = coc / sqrt(coc * coc + 0.1);
	float chromaOffset = CHROMA_STRENGTH /100.0;
	chromaOffset *= coc;
	
	if (coc * 0.5 > 1.0 / max(viewWidth, viewHeight) && hand < 0.5){
		#if BLUR_QUALITY == 1
		int nbOffsets = 30;
		#endif
		#if BLUR_QUALITY == 2
		int nbOffsets = 50;
		#endif
		#if BLUR_QUALITY == 3
		int nbOffsets = 75;
		#endif
		#if BLUR_QUALITY == 4
		int nbOffsets = 209;
		#endif
		#if BLUR_QUALITY == 5
		int nbOffsets = 6;
		#endif
		#if BLUR_QUALITY == 6
		int nbOffsets = 60;
		#endif
		#if BLUR_QUALITY == 7
		int nbOffsets = 18;
		#endif
		
		
		for(int i = 0; i < nbOffsets; i++) {
			vec2 offset = dofOffsets[i] * coc * 0.0085 * fovScale * vec2(1.0 / aspectRatio, 1.0);
			float lod = log2(viewHeight * aspectRatio * coc * 0.75 / 320.0);
			#ifdef CHROMATIC_ABERRATION
			dof.r += texture2DLod(colortex0, texCoord + offset+vec2(chromaOffset*fovScale2,0.0), lod).r;
			dof.g += texture2DLod(colortex0, texCoord + offset, lod).g;
			dof.b += texture2DLod(colortex0, texCoord + offset-vec2(chromaOffset*fovScale2,0.0), lod).b;
			#else
			dof += texture2DLod(colortex0, texCoord + offset, lod).rgb;
			#endif
		}
		dof /= nbOffsets;
	}
	else dof = color;
	return dof;
}

//Includes//
#ifdef BLACK_OUTLINE
#include "/lib/outline/outlineOffset.glsl"
#include "/lib/outline/depthOutline.glsl"
#endif


void main(){
	vec3 color = texture2D(colortex0,texCoord).rgb;
	
	
	float z = texture2D(depthtex1, texCoord.st).x;
	
	#ifdef BLACK_OUTLINE
	DepthOutline(z);
	#endif
	
	if(z > 0.56){
		color = ChromaAberration(color);
	}
	
	color = DepthOfField(color, z);
	
	
	/*DRAWBUFFERS:0*/
	gl_FragData[0]=vec4(color,1.);
}

#endif

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

//Varyings//
varying vec2 texCoord;

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

#endif