// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only

const float PI = 3.14159265359;
const float HALF_PI = PI * 0.5;

float ease(float x, float c)
{
    x = clamp(x, 0.0, 1.0);
    if (c > 0.0) {
        if (c < 1.0)
            return 1.0 - pow(1.0 - x, 1.0 / c);
        return pow(x, c);
    }
    if (c < 0.0) {
        if (x < 0.5)
            return pow(x * 2.0, -c) * 0.5;
        return (1.0 - pow(1.0 - (x - 0.5) * 2.0, -c)) * 0.5 + 0.5;
    }
    return 0.0;
}

void MAIN()
{
    vec3 direction = normalize(qt_eyeDir);
    float vAngle = acos(clamp(direction.y, -1.0, 1.0));

    vec3 groundHorizonLinear = qt_sRGBToLinear(groundHorizonColor);
    vec3 groundBottomLinear = qt_sRGBToLinear(groundBottomColor);
    vec3 skyHorizonLinear = qt_sRGBToLinear(skyHorizonColor);
    vec3 skyTopLinear = qt_sRGBToLinear(skyTopColor);
    vec3 sunLinear = qt_sRGBToLinear(sunColor) * sunEnergy;

    vec3 color;

    if (direction.y < 0.0) {
        float t = ease((vAngle - HALF_PI) / HALF_PI, groundCurve);
        color = mix(groundHorizonLinear, groundBottomLinear, t) * groundEnergy;
    } else {
        float t = ease(1.0 - vAngle / HALF_PI, skyCurve);
        color = mix(skyHorizonLinear, skyTopLinear, t) * skyEnergy;

        float sunAngle = degrees(acos(clamp(dot(normalize(sunDirection), direction), -1.0, 1.0)));

        if (sunAngle < sunDiskInnerAngle) {
            color = sunLinear;
        } else if (sunAngle < sunDiskOuterAngle) {
            float tSun = ease(
                (sunAngle - sunDiskInnerAngle) / (sunDiskOuterAngle - sunDiskInnerAngle),
                sunDiskFalloff
            );
            color = mix(sunLinear, color, tSun);
        }
    }

    FRAGCOLOR = vec4(color, 1.0);
}
