#version 330 core

out vec4 fragmentColor;

in vec3 fColor;
in vec3 fWorldPos;
in vec3 fNormal;
in float fAlpha;
flat in float fHiddenFaces;

uniform bool fogEnabled;
uniform vec3 cameraPos;
uniform vec3 fogColor;
uniform float fogStart;
uniform float fogEnd;
uniform vec3 sunDirection;
uniform float ambientLight;
uniform float sunLight;
uniform float verticalAmbientLight;
uniform float alpha;

bool isHiddenFace() {
    int hiddenFaces = int(fHiddenFaces + 0.5f);

    if(fNormal.x < -0.5f)
        return (hiddenFaces & 1) != 0;

    if(fNormal.x > 0.5f)
        return (hiddenFaces & 2) != 0;

    if(fNormal.y < -0.5f)
        return (hiddenFaces & 4) != 0;

    if(fNormal.y > 0.5f)
        return (hiddenFaces & 8) != 0;

    if(fNormal.z < -0.5f)
        return (hiddenFaces & 16) != 0;

    if(fNormal.z > 0.5f)
        return (hiddenFaces & 32) != 0;

    return false;
}

void main() {
    if(isHiddenFace())
        discard;

    vec3 normal = normalize(fNormal);
    float diffuse = max(dot(normal, normalize(-sunDirection)), 0.0f);
    float verticalAmbient = (normal.y * 0.5f + 0.5f) * verticalAmbientLight;
    float light = ambientLight + verticalAmbient + diffuse * sunLight;
    vec3 color = fColor * light;

    if(fogEnabled) {
        float distanceToCamera = length(fWorldPos - cameraPos);
        float fogFactor = smoothstep(fogStart, fogEnd, distanceToCamera);
        color = mix(color, fogColor, fogFactor);
    }

    fragmentColor = vec4(color, alpha * fAlpha);
}
