#version 150

layout(std140) uniform Fog {
    vec4  FogColor;
    float FogEnvironmentalStart;
    float FogEnvironmentalEnd;
    float FogRenderDistanceStart;
    float FogRenderDistanceEnd;
    float FogSkyEnd;
    float FogCloudsEnd;
};

// Función original para calcular la intensidad de la niebla de forma lineal.
// Retorna 0.0 si la distancia es menor o igual al inicio, 1.0 si es mayor o igual al fin,
// y una interpolación lineal entre esos puntos.
float linear_fog_value(float vertexDistance, float fogStart, float fogEnd) {
    if (vertexDistance <= fogStart) {
        return 0.0;
    } else if (vertexDistance >= fogEnd) {
        return 1.0;
    }

    return (vertexDistance - fogStart) / (fogEnd - fogStart);
}

// Función para calcular el valor total de la niebla, combinando distancias esféricas y cilíndricas.
float total_fog_value(float sphericalVertexDistance, float cylindricalVertexDistance, float environmentalStart, float environmantalEnd, float renderDistanceStart, float renderDistanceEnd) {
    // Estos multiplicadores controlan la distancia y densidad de la niebla de renderizado.
    // Los valores actuales hacen que la niebla sea más cercana y densa al jugador,
    // pero permitiendo ver un poco más que en versiones anteriores.
    float start_multiplier = 0.65;
    float end_multiplier = 1.0;

    float modifiedRenderDistanceStart = renderDistanceStart * start_multiplier;
    float modifiedRenderDistanceEnd   = renderDistanceEnd   * end_multiplier;

    // Cálculo explícito de la niebla ambiental y la niebla centrada en el jugador.
    // Esto asegura que la niebla atmosférica (el "colorsito") siempre contribuya.
    float environmentalFog = linear_fog_value(sphericalVertexDistance, environmentalStart, environmantalEnd);
    float playerCentricFog = linear_fog_value(cylindricalVertexDistance, modifiedRenderDistanceStart, modifiedRenderDistanceEnd);

    // Se toma el valor de niebla más alto entre la niebla ambiental y la niebla centrada en el jugador.
    // Esto permite que la niebla más densa o prominente prevalezca en cada punto del espacio.
    return max(environmentalFog, playerCentricFog);
}

// Aplica el color de la niebla al color de entrada del fragmento.
// Realiza una mezcla entre el color original y el color de la niebla.
vec4 apply_fog(vec4 inColor, float sphericalVertexDistance, float cylindricalVertexDistance, float environmentalStart, float environmantalEnd, float renderDistanceStart, float renderDistanceEnd, vec4 fogColor) {
    float fogValue = total_fog_value(sphericalVertexDistance, cylindricalVertexDistance, environmentalStart, environmantalEnd, renderDistanceStart, renderDistanceEnd);
    // 'fogColor.a' (componente alfa del color de la niebla) puede usarse para controlar la intensidad máxima.
    return vec4(mix(inColor.rgb, fogColor.rgb, fogValue * fogColor.a), inColor.a);
}

// Calcula la distancia esférica (euclidiana) desde el origen (0,0,0),
// que generalmente representa la posición de la cámara/jugador.
float fog_spherical_distance(vec3 pos) {
    return length(pos);
}

// Calcula la distancia cilíndrica. Esto es útil para niebla que se comporta diferente
// en el plano horizontal (XZ) y en el eje vertical (Y).
// Toma el máximo entre la distancia horizontal y la distancia vertical absoluta.
float fog_cylindrical_distance(vec3 pos) {
    float distXZ = length(pos.xz); // Distancia en el plano XZ
    float distY  = abs(pos.y);     // Distancia vertical (absoluta para evitar negativos)
    return max(distXZ, distY);
}
