#version 150

#define MINECRAFT_LIGHT_POWER   (0.6)
#define MINECRAFT_AMBIENT_LIGHT (0.4)

vec4 minecraft_mix_light(vec3 lightDir0, vec3 lightDir1, vec3 normal, vec4 color) {
    lightDir0 = normalize(lightDir0);
    lightDir1 = normalize(lightDir1);
    float light0 = max(0.0, dot(lightDir0, normal));
    float light1 = max(0.0, dot(lightDir1, normal));
    float lightAccum = min(1.0, (light0 + light1) * MINECRAFT_LIGHT_POWER + MINECRAFT_AMBIENT_LIGHT);
    return vec4(color.rgb * lightAccum, color.a);
}

vec4 minecraft_sample_lightmap(sampler2D lightMap, ivec2 uv) {
    float blockLight = uv.x / 16.0;
    float skyLight = uv.y / 16.0;
    
    vec4 defaultLightColor = texture(lightMap, clamp(uv / 256.0, vec2(0.5 / 16.0), vec2(15.5 / 16.0)));
    vec4 pureSkyColor = texture(lightMap, clamp(vec2(0.0, 240.0) / 256.0, vec2(0.5 / 16.0), vec2(15.5 / 16.0)));
    vec4 light0 = texture(lightMap, clamp(vec2(0.0, 0.0) / 256.0, vec2(0.5 / 16.0), vec2(15.5 / 16.0)));

    float eveningness = length(pureSkyColor.xyz - vec3(142, 142, 176) / 255);
    eveningness = smoothstep(0.08, 0.4, eveningness);
    float nightness = length(pureSkyColor.xyz - vec3(39, 39, 64) / 255);
    nightness = smoothstep(0.29, 0.8, nightness);
    float rainingness = length(pureSkyColor.xyz - vec3(196, 196, 211) / 255);
    rainingness = smoothstep(0.01, 0.1, rainingness);
    float thunderness = length(pureSkyColor.xyz - vec3(163, 163, 190) / 255);
    thunderness = smoothstep(0.15, 0.2, thunderness);
    float netherness = length(pureSkyColor.xyz - vec3(128, 113, 135) / 255);
    float enderness = length(pureSkyColor.xyz - vec3(121, 131, 133) / 255);

    vec4 daySkyColor = pureSkyColor * vec4(1.2, 1.2, 1.2, 1.0);
    vec4 nightSkyColor = pureSkyColor * vec4(0.25, 0.25, 0.8, 1) * 1.2;
    vec4 eveningSkyColor = vec4(244, 83, 82, 255) / 255;
    vec4 rainingSkyColor = vec4(120, 106, 159, 255) / 255;
    vec4 thunderSkyColor = vec4(100, 96, 139, 255) / 255;
    vec4 currentSkyColor = mix(nightSkyColor, mix(eveningSkyColor, daySkyColor, eveningness), nightness);

    vec4 netherSkyColor = vec4(54, 25, 45, 255) / 255;
    vec4 enderSkyColor = vec4(21, 9, 52, 255) / 255;

    currentSkyColor = mix(rainingSkyColor, currentSkyColor, rainingness);
    currentSkyColor = mix(thunderSkyColor, currentSkyColor, thunderness);
    
    if(blockLight < 8.0 && light0.r > 0.5){
        blockLight = 16.0;
    }

    vec4 shadowLight = mix(vec4(0.04, 0.04, 0.08, 1), mix(currentSkyColor, currentSkyColor * vec4(0.7, 0.7, 1.0, 1), smoothstep(16.0, 10.0, skyLight)), skyLight / 16.0);
    vec4 caveBlockLight = mix(shadowLight, vec4(1.2, 0.75, 0.58, 1.0) * 1.2, smoothstep(0.0, 16.0, blockLight));
    vec4 dayBlockLight = mix(daySkyColor, vec4(1.2, 1.1, 1.0, 1.0), smoothstep(0.0, 16.0, blockLight));
    dayBlockLight = mix(shadowLight * vec4(1.1, 1.1, 1.1, 1.0), dayBlockLight, smoothstep(0.0, 16.0, blockLight));
    vec4 nightBlockLight = mix(nightSkyColor, vec4(1.3, 0.7, 0.58, 1) * 1.4, smoothstep(0.0, 16.0, blockLight));
    nightBlockLight = mix(shadowLight, nightBlockLight, smoothstep(0.0, 8.0, blockLight));
    
    vec4 endBlockLight = mix(enderSkyColor, vec4(248, 112, 143, 255) / 255 * 1.5, smoothstep(0.0, 16.0, blockLight));
    vec4 netherBlockLight = mix(netherSkyColor, vec4(120, 90, 90, 255) / 255 * 1.2, smoothstep(0.0, 16.0, blockLight));

    if(enderness < 0.05){
        if(blockLight > 0.0 && light0.r > 0.5) return vec4(1, 1, 1, 1);
        else if(blockLight > 0.0) return endBlockLight;
        else return enderSkyColor;
    }
    else if(netherness < 0.04){
        if(blockLight > 0.0 && light0.r > 0.5) return vec4(1, 1, 1, 1);
        else if(blockLight > 0.0) return netherBlockLight;
        else return netherSkyColor;
    }else if(blockLight > 0.0 && light0.r > 0.5) return vec4(1, 1, 1, 1);
    else if(blockLight > 0.0 && skyLight < 1.0) return caveBlockLight;
    else if(blockLight > 0.0) return mix(nightBlockLight, mix(nightBlockLight * vec4(1.2, 1.2, 1.2, 1), mix(nightBlockLight, dayBlockLight, thunderness), rainingness), clamp(nightness, 0.0, 1.0));
    else if(skyLight < 15.0) return shadowLight;
    else return currentSkyColor;
}
    