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


struct PS_Input
{
    float4 position : SV_Position;
    float4 color : COLOR;
    float3 pos : POS;
};

struct PS_Output
{
    float4 color : SV_Target;
};

float2 hash( float2 x)
{
    const float2 k = float2(0.540,0.690);
    x = x * k + k.yx;
    return 1.0 + 2.0 * frac(19.080 * k * frac(x.x * x.y * (x.x + x.y)));
}

float gnoise( in float2 pos)
{
    pos *= float2(-0.470,-0.700);
    float2 i = floor(pos);
    float2 f = frac(pos);
    float2 u = f * f * (3.0 - 2.0 * f);
    return (lerp(lerp(dot(hash(i + float2(0.0,0.0)), f - float2(0.0,0.0)), dot( hash(i + float2(1.0,0.0)), f - float2(1.0,0.0)), u.x), lerp( dot( hash(i + float2(0.0,1.0)), f - float2(0.0,1.0)), dot( hash(i + float2(1.0,1.0)), f - float2(1.0,1.0)), u.x), u.y))*0.652;
}

//noise value 2D
float random(in float2 pos)
{
    return frac(sin(dot(pos.xy, float2(-0.600,0.430))) * 43759.057);
}
float noise(in float2 st)
{
    float2 i = floor(st);
    float2 f = frac(st);
    float a = random(i);
    float b = random(i + float2(1.0, 0.0));
    float c = random(i + float2(0.0, 1.0));
    float d = random(i + float2(1.0, 1.0));
    float2 u = f * f * (3.0 - 2.0 * f);
    return lerp(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
}

float fbm (in float2 pos,float ch)
{
    float v = lerp(0.09, -0.3, ch);
    float la = 2.396;
    float ga = 0.4;
    float am = 0.332;
    float fr = 1.0;
    for(float y; y < 5.0; y++)
    {
        v += am * noise(abs(exp(y * 0.005) * fr * pos + TIME * 0.05));
        fr *= la;
        am *= ga;
    }
    return v;
}

float3 Cc(float2 pos, float3 ct, float4 fc, float dia, float noite, float dsol, float ch)
{
    float clouds = fbm(pos * 2.980, ch);
    float cloudsE = fbm(pos * 2.980 - float2(0.2,0.0), ch);
    float offset = gnoise(pos * 0.376 + TIME * 0.01);
    float Fimcloud = smoothstep(10.0 - offset,  - offset, clouds) - smoothstep(0.212 - offset, 0.300 - offset, clouds);
    float3 tempo = lerp(lerp(lerp(float3(0.6,0.6,0.6), float3(1.0,1.0,1.0), dia), float3(0.3,0.3,1.0), noite), float3(fc.r, 0.2 * fc.r, 0.0), dsol);
    float3 Esc = lerp(lerp(lerp(float3(0.405,0.405,0.405), float3(0.075,0.075,0.1), noite), float3(0.335,0.335,0.335), ch), tempo, pow(smoothstep(-0.842 - offset, 0.288 - offset, cloudsE), 6.584));
    return lerp(ct, Esc, Fimcloud);
}

float hash13(float3 p3)
{
	p3  = frac(p3 * float3(0.067,0.074,0.090));
    p3 += dot(p3, p3.yzx + 19.294);
    return frac((p3.x + p3.y) * p3.z);
}

float stars(float3 ray)
{
    float3 p = ray * 150.0;
    float brigtness = smoothstep(1.0 - 0.05, 1.000, hash13(floor(p)));
    return smoothstep(0.5, 0.0, length(frac(p) )) * brigtness * lerp(1.0, 0.1, 0.592 * length(frac(p * sin(TIME * 0.02))));
}

float3 es(float3 p){
    float s = stars(p);
    return lerp(float3(0.001,0.018,0.105), float3(0.994,1.000,0.888), s);
}

ROOT_SIGNATURE
void main( in PS_Input PSInput, out PS_Output PSOutput )
{	
    float posc = length(PSInput.pos);
    float4 temp = FOG_COLOR;
    float4 tp = TEXTURE_1.Sample(TextureSampler1, float2(0.0,1.0));
    float chuva = clamp((1.0 - pow(FOG_CONTROL.y + 0.1,5.0)) * 2.0,0.0,1.0);
    float dia = lerp(pow(max(min(temp.r * 1.5 + 0.3, 1.0), 0.0), 1.2), 1.0, chuva);
    float noite = lerp(0.0, 1.0, pow(max(min(1.0 - dia, 1.0), 0.0), 1.2));
    float dsol = lerp(0.0, 1.1, 0.5 - abs(0.5 - (1.0 - max(0.0, min(1.0, (tp.r - 0.46) * 2.0)))));
    float dss = lerp(lerp(lerp( 0.0, 2.5, clamp((1.0 - max(0.0, min(1.0, (tp.r - 0.48) * 2.0)) * (1.5 + chuva)) * 2.5, 0.0, 1.) * clamp((tp.r - 0.15) * 1.0, 0.0, 1.0)), 0.5, lerp(0.0, 5.0, pow(max(min(1.0 - tp.r * 1.5, 1.0), 0.0), 1.2))), 0.0, noite);
    float4 fc = FOG_COLOR;
    float3 fc3 = FOG_COLOR.rgb;
    float3 ctemp =  lerp(lerp(lerp(PSInput.color.rgb * 0.5, PSInput.color.rgb * 0.6, dia), es(PSInput.pos * 5.0), noite), FOG_COLOR.rgb, dsol);
    float3 cou;
if(FOG_CONTROL.x < 0.001){
    cou = lerp(ctemp, fc3, chuva);
}else{
    cou = Cc(PSInput.pos.xz * 9.0 + TIME * 0.002, ctemp, fc, dia, noite, dsol, chuva);
    cou = lerp(ctemp, FOG_COLOR.rgb, lerp(smoothstep(0.3, 1.0, posc * 1.7), smoothstep(0.0, 0.5, pow(posc * 1.7, 0.65)), chuva));
}
	PSOutput.color = float4(cou,5.0);
}