#include "ShaderConstants.fxh"
#include "util.fxh"

struct PS_Input
{
	float4 position : SV_Position;
	float3 wpos : WPOS;
	float4 posi : POSI;

#ifndef BYPASS_PIXEL_SHADER
	lpfloat4 color : COLOR;
	snorm float2 uv0 : TEXCOORD_0_FB_MSAA;
	snorm float2 uv1 : TEXCOORD_1_FB_MSAA;
#endif

#ifdef FOG
	float4 fogColor : FOG_COLOR;
#endif
};

struct PS_Output
{
	float4 color : SV_Target;
};

#include "dect.fxh"
#include "inform/option.txt"

//noise value 3D 
float hash(float3 p)
 {
    p  = frac(p * 0.3183099 + 0.1);
	p *= 17.0;
    return frac(p.x * p.y * p.z * (p.x + p.y + p.z));
}

float noise( in float3 x )
{
    float3 i = floor(x);
    float3 f = frac(x);
    f = f * f * (3.0 - 2.0 * f);
    return lerp(lerp(lerp(hash(i + float3(0.0,0.0,0.0)), hash(i + float3(1.0,0.0,0.0)), f.x), lerp(hash(i + float3(0.0,1.0,0.0)), hash(i + float3(1.0,1.0,0.0)), f.x), f.y), lerp(lerp(hash(i + float3(0.0,0.0,1.0)), hash(i + float3(1.0,0.0,1.0)), f.x), lerp(hash(i + float3(0.0,1.0,1.0)), hash(i + float3(1.0,1.0,1.0)), f.x), f.y), f.z);
}

float WaterPos(float3 v, float3 w, float4 col, float wt)
{
    float wap = (length(v)*0.2) / length(v) / length(w);
    if(FOG_CONTROL.x < 0.001){}else{if(wt == 1.0){}else{wap = 0.0;}}
	return wap;
}

float onda(float3 X)
{
    X.x *= 0.5;
    X.z *= 0.916;
    float D = abs(sin(noise(float3(X.x + TIME * 0.524, X.x + X.y + TIME * 0.5, X.x - X.z - TIME * 1.444))));
    return lerp(0.592, 1.568, D);
}

float3 WaterMap(float3 pos) {
    float H = onda(pos - float3(1.0,0.0,0.0)) - onda(pos);
    return  1.0 - float3(-H,1.0,1.0);
}

float3 light(float3 di, float3 d, float3 L, float2 u1, float dia, float ch, float dss) {
	float3 col = d;
	col +=  L * 1.5-0.5+col*smoothstep(0.75,1.0,pow(u1.x,1.));
	float ti = lerp(0.0,lerp(0.0,lerp(1.0,0.0,ch),dia),u1.y*1.1);
	float temp = lerp(0.0,1.5,pow(u1.x,3.0));
	temp = lerp(temp,0.0,ti);
	col = lerp(di,col,temp);
return col;
}

ROOT_SIGNATURE
void main(in PS_Input PSInput, out PS_Output PSOutput)
{
#ifdef BYPASS_PIXEL_SHADER
    PSOutput.color = float4(0.0f, 0.0f, 0.0f, 0.0f);
    return;
#else

#if USE_TEXEL_AA
	float4 diffuse = texture2D_AA(TEXTURE_0, TextureSampler0, PSInput.uv0 );
#else
	float4 diffuse = TEXTURE_0.Sample(TextureSampler0, PSInput.uv0);
	float4 tex = TEXTURE_0.Sample(TextureSampler0, PSInput.uv0);
#endif

    float4 tep = FOG_COLOR;
	float4 temp = TEXTURE_1.Sample(TextureSampler1, float2(0.0, 1.0));
    float chuva = Rain(FOG_CONTROL);
    float dia = pow(max(min(tep.r * 1.5, 1.0), 0.0), 1.2);
    float diat = pow(max(min(temp.r * 1.5, 1.0), 0.0), 1.2);
    float noite = lerp(0.0, 2.5, pow(max(min(1.0 - temp.r * 1.5, 1.0), 0.0), 1.2));
    float dsol = 0.5 - abs(0.5 - (1.0 - max(0.0, min(1.0, (temp.r - 0.46) * 2.0))));
             dsol = lerp(dsol,0.0,chuva);
    float dss = lerp(lerp( 0.0, 2.5, clamp((1.0 - max(0.0, min( 1.0, (temp.r - 0.48) * 2.0)) * (1.5 + chuva)) * 2.5, 0.0, 1.0) * clamp((temp.r - 0.15) * 1.0, 0.0, 1.0)), 0.5, lerp(0.0, 5.0, pow(max(min(1.0 - temp.r * 1.5, 1.0), 0.0), 1.2)));
//normal
    float3 N = normalize(cross(ddx(PSInput.posi.xyz), ddy(PSInput.posi.xyz)));
    float mx = 0.0;float nx = 0.0;float mz = 0.0;float nz = 0.0;float my = 0.0;float ny = 0.0;float mxy = 0.0;float nxy = 0.0;float mzy = 0.0;float nzy = 0.0;float myx = 0.0;float nyx = 0.0;float myz = 0.0;float nyz = 0.0;float mxyt = 0.0;float nxyt = 0.0;
//sombra bias
    float SC = lerp(lerp(0.8, 0.4, diat), 1.0, chuva);
    SC = lerp(SC, 0.7, lerp(0.0,4.0,dsol));
    float biasY = 0.88;
    float biasX = 0.67;
    float shdX = PSInput.color.g;
    float shdY = PSInput.uv1.y;
//tempo cor
	float3 DC = float3(1.4,1.4,1.4)*1.2;
    float3 CC = float3(FOG_COLOR.rgb);
//luz
    float3 La = float3(0.5,0.2,-0.3);
    float3 Lb = float3(0.5,0.2,-0.3) * 0.5;
    float pisc = 0.2 * cos(TIME * 0.3 * cos(0.3 * TIME));
    float3 L = lerp(La, Lb, lerp(pisc * (1.0 - 1.0 * diat * PSInput.uv1.y),0.0,lerp(0.0,1.0,pow(PSInput.uv1.x,1.4))));
    float3 AGL = float3(0.5,0.5,0.5);
//-X
if(-N.x > 0.1){if((-N.y > 0.1)||(N.y > 0.1)){}else{mx = 1.0;}}
//+X
if(N.x > 0.1){if((-N.y > 0.1)||(N.y > 0.1)){}else{nx = 1.0;}}
//-Z
if(-N.z > 0.1){if((-N.y > 0.1)||(N.y > 0.1)){}else{mz = 1.0;}}
//+Z
if(N.z > 0.1){if((-N.y > 0.1)||(N.y > 0.1)){}else{nz = 1.0;}}
//+Y
if(-N.y > 0.1){if((-N.x > 0.1)||(N.x > 0.1)||(-N.z > 0.1)||(N.z > 0.1)){}else{my = 1.0;}}
//-Y
if(N.y > 0.1){if((-N.x > 0.1)||(N.x > 0.1)||(-N.z > 0.1)||(N.z > 0.1)){}else{ny = 1.0;}}
//+XY
if((-N.x > 0.1) && (-N.y > 0.1)){if((N.z < 0.1)||(N.y > 0.1)){mxy = 1.0;}}
//-XY
if((N.x > 0.1) && (-N.y > 0.1)){if((-N.z > 0.1)||(N.y > 0.1)){}else{nxy = 1.0;}}
//+ZY
if((-N.z > 0.1) && (-N.y > 0.1)){if((N.x < 0.1)||(N.y > 0.1)){mzy = 1.0;}}
//-ZY
if((N.z > 0.1) && (-N.y > 0.1)){if((-N.x < 0.1)||(N.y > 0.1)){nzy = 1.0;}}
//+YX
if((N.y > 0.1) && (-N.x > 0.1)){if((N.z > 0.1)||(N.x > 0.1)){}else{myx = 1.0;}}
//-YX
if((N.y > 0.1) && (N.x > 0.1)){if((-N.z > 0.1)||(-N.x > 0.1)){}else{nyx = 1.0;}}
//+YZ
if((N.y > 0.1) && (-N.z > 0.1)){if((N.z > 0.1)||(-N.x > 0.1)){}else{myz = 1.0;}}
//-YZ
if((N.y > 0.1) && (N.z > 0.1)){if((-N.z > 0.1)||(N.x > 0.1)){}else{nyz = 1.0;}}
//+XYT
if((-N.x > 0.1) && (-N.y > 0.1)){if((N.z < 0.1)||(N.y > 0.1)){}else{mxyt = 1.0;}}
//-XYT
if((N.x > 0.1) && (-N.y > 0.1)){if((-N.z > 0.1)||(N.y > 0.1)){nxyt = 1.0;}}
float3 mN = float3(mx,my,mz);
float3 nN = float3(nx,ny,nz);
float3 mNy = float3(mxy,0.0,mzy);
float3 nNy = float3(nxy,0.0,nzy);
float3 mYN = float3(myx,0.0,myz);
float3 nYN = float3(nyx,0.0,nyz);
float2 mnxyt = float2(mxyt,nxyt);
//false
float wt = 0.0;
float BL = 0.0;
//water false
#ifdef BLEND
if(PSInput.color.b > PSInput.color.r){ wt = 1.0; }
    BL = 1.0;
#endif

#ifdef SEASONS_FAR
	diffuse.a = 1.0f;
#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

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

#if !defined(ALWAYS_LIT)
    float2 uu = PSInput.uv1;
           uu.x -= PSInput.uv1.x;
    float4 NC = min(TEXTURE_1.Sample(TextureSampler1, uu),lerp(lerp(float4(0.0,0.0,0.0,PSInput.color.a), float4(1.0,1.0,1.0,PSInput.color.a),pow(PSInput.uv1.y,2.0)),lerp(float4(0.0,0.0,0.0,PSInput.color.a),float4(0.5,0.5,0.5,PSInput.color.a),pow(PSInput.uv1.y,2.0)),chuva));
    float4 NCn = lerp(lerp(NC*0.3,max(TEXTURE_1.Sample(TextureSampler1, uu),float4(0.0,0.0,1.2,PSInput.color.a)),pow(PSInput.uv1.y,2.0)),NC*0.3,chuva);
           NCn *= NCn;
#endif

#ifndef SEASONS
	#if !USE_ALPHA_TEST && !defined(BLEND)
		diffuse.a = PSInput.color.a;
	#endif	

	if(Underwater(FOG_CONTROL)){}else{
		diffuse.rgb = lerp(tex.rgb, diffuse.rgb, noite);
		diffuse.rgb *= PSInput.color.rgb;
    }
#else
	float2 uv = PSInput.color.xy;
	diffuse.rgb *= lerp(1.0f, TEXTURE_2.Sample(TextureSampler2, uv).rgb*2.0f, PSInput.color.b);
	diffuse.rgb *= PSInput.color.aaa;
	diffuse.a = 1.0f;
#endif

//ender
if(End(FOG_COLOR)){
    
    diffuse.rgb *= float3(0.511,0.362,0.985);
    diffuse.rgb += diffuse.rgb * float3(0.511,0.362,0.985)*1.2 * pow(PSInput.uv1.x, 2.0);
}else{
//nether
if(Nether(FOG_CONTROL)){
    //nether do fumaça
    diffuse.rgb += lerp(float3(0.0,0.0,0.0), lerp(La * 2.5, La * 6.0, pow(PSInput.uv1.x,0.8)), clamp(FOG_COLOR.x - 0.1, 0.0, 1.0));
    //nether gases de azul
    diffuse.rgb *= lerp(diffuse.rgb ,float3(-0.2,-0.2,4.0), clamp(FOG_COLOR.y - (FOG_COLOR.x - 0.1), 0.0, 1.0));
    diffuse.rgb += lerp(float3(0.0,0.0,0.0) ,(float3(0.0,0.0,diffuse.b) * 15.0) * pow(PSInput.uv1.x,5.0), clamp(FOG_COLOR.y - (FOG_COLOR.x - 0.1), 0.0, 1.0));
    diffuse.rgb += lerp(diffuse.rgb , lerp(-float3(0.0,0.1,0.1) * 3.5, La * 5.0, pow(PSInput.uv1.x,3.0)), clamp(FOG_CONTROL.x - FOG_COLOR.y, 0.0, 1.0));
}else{
//arvores
if(PSInput.color.a == 0.0){
    diffuse.rgb *= 1.15;
    shdX = PSInput.color.g * 1.3;
    shdY = PSInput.uv1.y*1.3;
}
if(PSInput.color.b > PSInput.color.r*2.0){
    shdX = 1.0;
    biasY = 0.9158;
}
    //ref water
    float Fimwater = 0.0;
    #ifdef WATER_REAL
    Fimwater = abs(asin(WaterPos(PSInput.wpos.xzy, WaterMap(PSInput.posi.xzy * 5.0), PSInput.color, wt)));
    #else
    Fimwater = abs(asin(WaterPos(PSInput.wpos.xzy, diffuse.rgb, PSInput.color, wt)));
    #endif
    float vs = 1.2;
    float3 Ns = float3(0.0,0.0,0.0);
    Ns = normalize(float3(PSInput.wpos.x,PSInput.wpos.y * vs,PSInput.wpos.z)) * vs;
    float3 ctemp =  lerp(lerp(lerp(lerp( float3(0.001,0.018,0.105), float3(0.1,0.4,0.7) * 0.5 * FOG_COLOR.rgb, diat), PSInput.color.rgb, noite), FOG_COLOR.rgb * 0.5, dss),FOG_COLOR.rgb,chuva);
           ctemp = lerp(diffuse.rgb,ctemp,BL);
    float Wdi = lerp(lerp(lerp(1.0, 0.3, diat),0.6,lerp(0.0,4.0,dsol)), 1.0, length(-PSInput.wpos) / FAR_CHUNKS_DISTANCE * 1.1);
    float posc = length(PSInput.wpos * 0.009);

    float4 w;
    w = lerp(float4(ctemp,Wdi), lerp(lerp(float4(1.0,1.0,1.0,1.0), float4(1.0,1.0,1.0,1.0), diat), float4(ctemp,1.0), smoothstep(-0.584, 2.0, length(PSInput.wpos.xzy) / FAR_CHUNKS_DISTANCE * 1.1)), Fimwater);
//sombra gram
#ifdef ALPHA_TEST 
    if(PSInput.color.a == 0.0){}else{shdX = min(1.0, N.z-N.y);}
#endif
if(Underwater(FOG_CONTROL)){
    diffuse.rgb *= TEXTURE_1.Sample(TextureSampler1, PSInput.uv1).rgb;
    diffuse.rgb *= PSInput.color.rgb;
    diffuse.r *= 0.3;
    diffuse = lerp(diffuse, float4(0.5,0.5,0.5,0.6), wt);
    diffuse.rgb += diffuse.rgb * lerp(float3(0.0,0.0,1.0), AGL, pow(PSInput.uv1.x, 1.0));
    
}else{
    
    diffuse = lerp(diffuse,lerp(float4(ctemp,1.0),w,BL),wt);
    float4 d_l = diffuse;
    diffuse.rgb *= lerp(lerp(float3(1.0,1.0,1.0),lerp(DC, CC, chuva ),PSInput.uv1.y*1.1), float3(1.0,1.0,1.0), wt);
    
    diffuse.rgb = lerp(diffuse.rgb*NC.rgb,diffuse.rgb*NCn.rgb, noite);

    diffuse.rgb *= lerp(float3(1.0,1.0,1.0), float3(1.0,0.7,0.0), lerp(0.0,dss, PSInput.uv1.y*1.1));
	//sombra
    diffuse.rgb *= lerp(1.0, SC, min(100.0 * lerp(smoothstep(PSInput.uv1.y - biasY, 0.1, 0.0),smoothstep(shdX - biasX, 0.7, 0.0),0.5), 1.0));
    
    float3 dt = tex.rgb*PSInput.color.rgb;
    diffuse.rgb = light(diffuse.rgb, d_l.rgb, L, PSInput.uv1,diat,chuva,dss);
}
   diffuse.rgb = lerp(diffuse.rgb, lerp(float3(0.5,0.5,0.5),FOG_COLOR.rgb, noite), length(-PSInput.wpos * 0.55) / FAR_CHUNKS_DISTANCE * chuva * PSInput.uv1.y);
   float3 fogt = float3(0.0,0.0,0.0);
   fogt = lerp(diffuse.rgb, FOG_COLOR.rgb * float3(0.9,0.95,1.3), (length(-PSInput.wpos * 0.55) / FAR_CHUNKS_DISTANCE * 0.55) * diat * PSInput.uv1.y);
   fogt = lerp(fogt, diffuse.rgb, chuva);
   diffuse.rgb = lerp(fogt, diffuse.rgb, wt);
}}

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

	PSOutput.color = diffuse;

#ifdef VR_MODE
	// On Rift, the transition from 0 brightness to the lowest 8 bit value is abrupt, so clamp to 
	// the lowest 8 bit value.
	PSOutput.color = max(PSOutput.color, 1 / 255.0f);
#endif

#endif // BYPASS_PIXEL_SHADER
}