// __multiversion__
// This signals the loading code to prepend either #version 100 or #version 300 es as apropriate.

#include "fragmentVersionCentroid.h"

#if __VERSION__ >= 300
	#ifndef BYPASS_PIXEL_SHADER
		#if defined(TEXEL_AA) && defined(TEXEL_AA_FEATURE)
			_centroid in highp vec2 uv0;
			_centroid in highp vec2 uv1;
		#else
			_centroid in vec2 uv0;
			_centroid in vec2 uv1;
		#endif
	#endif
#else
	#ifndef BYPASS_PIXEL_SHADER
		varying vec2 uv0;
		varying vec2 uv1;
	#endif
#endif

varying vec4 color;

#ifdef FOG
varying vec4 fogColor;
#endif

#ifdef GL_FRAGMENT_PRECISION_HIGH
	varying highp vec3 cPos;
#else
	varying mediump vec3 cPos;
#endif
varying POS3 wPos;
varying float wf;

#include "uniformShaderConstants.h"
#include "util.h"
#include "PSutil.h"
uniform vec2 FOG_CONTROL;
uniform float TIME;
uniform vec4 FOG_COLOR;

LAYOUT_BINDING(0) uniform sampler2D TEXTURE_0;
LAYOUT_BINDING(1) uniform sampler2D TEXTURE_1;
LAYOUT_BINDING(2) uniform sampler2D TEXTURE_2;

float filmic_curve(float x) {
	float A = 0.20;									// Shoulder strength
	float B = 0.30;									// Linear strength
	float C = 0.15 * TM_BRIGHTNESS;	// Linear angle
	float D = 0.20 * TM_GAMMA;			// Toe strength
	float E = 0.02 * TM_CONTRAST;		// Toe numerator
	float F = 0.30;									// Toe denominator
	return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
}

vec3 PSmapping(vec3 clr) {
	#ifdef PS_TONEMAP
		float W = 1.0 / TM_EXPOSURE;
		float Luma = dot(clr, vec3(0.7, 0.5, 0.3));
		vec3 Chroma = clr - Luma;
		clr = (Chroma * TM_SATURATION) + Luma;
		clr = vec3(filmic_curve(clr.r), filmic_curve(clr.g), filmic_curve(clr.b)) / filmic_curve(W);
	#endif
	return clr;
}

float flat_shading(float dusk){
	dusk = dusk*0.75+0.25;
	vec3 n = normalize(vec3(cross(dFdx(cPos),dFdy(cPos))));
	n.x = abs(n.x*mix(1.5,0.8,dusk));
	n.yz = n.yz*0.5+0.5;
	n.yz *= mix(vec2(0.5,0.0),vec2(1.0),dusk);
	return max(n.x,max(n.y,n.z));
}

#ifdef PS_WATER
highp vec3 mod289(highp vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
highp vec2 mod289(highp vec2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
highp vec3 permute(highp vec3 x) { return mod289(x*(x * 34.0 + 1.0)); }

highp float snoise(highp vec2 v) {
	const highp vec4 C = vec4(
		0.211324865405187,   // (3.0-sqrt(3.0))/6.0
		0.366025403784439,   // 0.5*(sqrt(3.0)-1.0)
		-0.577350269189626,  // -1.0 + 2.0 * C.x
		0.024390243902439);  // 1.0 / 41.0

	highp vec2 i  = floor(v + dot(v, C.yy));
	highp vec2 x0 = v -   i + dot(i, C.xx);
	highp vec2 i1  = x0.x > x0.y ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
	highp vec4 x12 = x0.xyxy + C.xxzz;
	x12.xy -= i1;

	i = mod289(i);
	highp vec3 p =permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0));

	highp vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0);
	m = m*m;
	m = m*m;

	highp vec3 x  = 2.0 * fract(p * C.www) - 1.0;
	highp vec3 h  = abs(x) - 0.5;
	highp vec3 ox = round(x);
	highp vec3 a0 = x - ox;

	m *= inversesqrt(a0 * a0 + h * h);
	highp vec3 g;
	g.x  = a0.x  * x0.x   + h.x  * x0.y;
	g.yz = a0.yz * x12.xz + h.yz * x12.yw;
	return 130.0 * dot(m, g);
}

vec4 water(vec4 col,float weather,highp float time){
	vec3 p = cPos;
	float sun = smoothstep(.5,.75,uv1.y);
	float dist = smoothstep(100.,500.,(wPos.x*wPos.x+wPos.z*wPos.z)/max(1.,abs(wPos.y)));
	col.rgb = mix(col.rgb,vec3(col.r+col.g+col.b),dist*.25);
	col.rgb *= mix(1.,snoise(vec2(wPos.x-time,wPos.z)*.05)*.1+.95,sun);

	p.xz *= PS_WATER;
	p.xz += smoothstep(0.,8.,abs(p.y-8.))*.5;
	float n = (snoise(p.xz-time*.5)+snoise(vec2(p.x-time,(p.z+time)*.5)))*.375+.25;
	float n2 = smoothstep(.5,1.,n);

	vec4 col2 = vec4(mix(col.rgb*1.2,vec3(col.r+col.g+col.b),.3),col.a*1.1);
	vec4 col3 = mix(col*1.1,vec4(.8,.8,.9,.9),smoothstep(3.+abs(wPos.y)*.3,0.,abs(wPos.z))*sun*weather);

	return mix(col,mix(col2,col3,n2),n*((1.-dist)*.7+.3));
}
#endif


void main()
{
#ifdef BYPASS_PIXEL_SHADER
	gl_FragColor = vec4(0);
	return;
#else

#if USE_TEXEL_AA
	vec4 diffuse = texture2D_AA(TEXTURE_0, uv0);
#else
	vec4 diffuse = texture2D(TEXTURE_0, uv0);
#endif

#ifdef SEASONS_FAR
	diffuse.a = 1.0;
#endif

#if USE_ALPHA_TEST
	#ifdef ALPHA_TO_COVERAGE
		#define ALPHA_THRESHOLD 0.05
	#else
		#define ALPHA_THRESHOLD 0.5
	#endif
	if(diffuse.a < ALPHA_THRESHOLD)
		discard;
#endif

vec4 inColor = color;

#if defined(BLEND)
	diffuse.a *= inColor.a;
#endif

#if !defined(ALWAYS_LIT)
	diffuse *= texture2D( TEXTURE_1, uv1 );
#endif

#ifndef SEASONS
	#if !USE_ALPHA_TEST && !defined(BLEND)
		diffuse.a = inColor.a;
	#endif
	diffuse.rgb *= inColor.rgb;
#else
	vec2 uv = inColor.xy;
	diffuse.rgb *= mix(vec3(1.0,1.0,1.0), texture2D( TEXTURE_2, uv).rgb*2.0, inColor.b);
	diffuse.rgb *= inColor.aaa;
	diffuse.a = 1.0;
#endif

#ifdef FOG
	float weather = smoothstep(0.8,1.0,FOG_CONTROL.y);
#else
	float weather = 1.0;
#endif
float daylight = texture2D(TEXTURE_1,vec2(0.0, 1.0)).r;
float dusk = max(smoothstep(0.55,0.4,daylight),smoothstep(0.65,0.8,daylight));
float cosT = abs(dot(vec3(0.,1.,0.),normalize(wPos)));
daylight *= weather;

#ifdef PS_LIGHT
	diffuse.rgb += PS_LIGHT*max(0.0,uv1.x-0.5)*mix(1.0,smoothstep(1.0,0.8,uv1.y)*0.5+0.5,daylight);
#endif

#ifdef PS_SUN_LIGHT
	diffuse.rgb += (vec3(0.9)-diffuse.rgb)*diffuse.rgb*smoothstep(0.87-blur,0.87+blur,uv1.y)*daylight*PS_SUN_LIGHT;
#endif


diffuse.rgb = PSmapping(diffuse.rgb);
#ifdef PS_WATER
	if(wf > 0.0){
		diffuse = mix(diffuse,water(diffuse,weather,TIME),wf*(1.2-cosT));
	}
#endif

#ifdef PS_SHADOW
	float s_amount = mix(0.0,0.45,smoothstep(0.87 + blur,0.87 - blur,uv1.y));
	float nolight = 1.0-uv1.x;
	diffuse.rgb = mix(diffuse.rgb,PS_SHADOW,s_amount*nolight*daylight);
#endif

#ifdef PS_FLAT_SHADING
	diffuse.rgb *= mix(1.0,flat_shading(dusk),smoothstep(0.7,0.95,uv1.y)*min(1.25-uv1.x,1.0)*daylight);
#endif

#ifdef DUSK
	float dusk3 = DUSK*smoothstep(dusk1,dusk1+dusk2,uv1.y)*weather;
	dusk = dusk*dusk3+(1.0-dusk3);
	diffuse.rgb *= vec3(2.0-dusk,1.0,dusk);
#endif

#ifdef FOG
	diffuse.rgb = mix( diffuse.rgb, fogColor.rgb, fogColor.a );
#endif

gl_FragColor = diffuse;

#endif // BYPASS_PIXEL_SHADER
}
