vec3 calcAmbientLight(vec3 wNormal, vec2 lightmap, vec3 ambientUp, vec3 ambientDown, vec3 ambientRight,
                      vec3 ambientLeft, vec3 ambientB, vec3 ambientF, vec3 RSML, float diffuseSun, vec3 torch)
{
    vec3 ambientCoefs = wNormal / dot(abs(wNormal), vec3(1.0));

    vec3 clampedCoefs = max(ambientCoefs, 0.0);
    vec3 clampedCoefsNeg = max(-ambientCoefs, 0.0);

    float mixstrength = clamp(pow(shadowblend, 0.3), 0.0, 1.0);
    float oneMinusMixStrength = 1.0 - mixstrength;

#ifndef OVERWORLD
    float skymap = 1.0;
#else
    float skymap = lightmap.y;
#endif

    float skymap2 = skymap * skymap;
    float skymap4 = skymap2 * skymap2;

    // Precompute factors to minimize operations
    float diffuseSunClamped = clamp(diffuseSun, 0.5, 1.0);

    // Compute bounce lighting
#ifndef OVERWORLD
    vec3 sunLight = mix(ambientUp, sunLight, 0.5);
    vec3 bounce = sunLight;
#else
    float bounceFactor = (0.15 * diffuseSunClamped) * oneMinusMixStrength + 0.25;
    vec3 bounce = sunLight * bounceFactor * skymap4;
#endif
    // Adjust ambient sides based on mixstrength
    ambientRight = ambientDown * oneMinusMixStrength + ambientRight * mixstrength;
    ambientLeft = ambientDown * oneMinusMixStrength + ambientLeft * mixstrength;

    // Combine ambient light components
    vec3 ambientCombined = (ambientUp * clampedCoefs.y +
                            ambientDown * clampedCoefsNeg.y +
                            ambientRight * clampedCoefs.x +
                            ambientLeft * clampedCoefsNeg.x +
                            ambientB * clampedCoefs.z +
                            ambientF * clampedCoefsNeg.z) *
                               skymap2 +
                           RSML;

    // Mix ambientCombined with bounce lighting
    ambientCombined = ambientCombined * 0.9 + bounce * 0.1;

    // Calculate diffuse lighting
    vec3 diffuseLight = diffuseSun * sunLight + ambientCombined;

    // Compute darkness factors
    float darknessFactor = darknessLightFactor * darknessLightFactor * darknessLightFactor;
    diffuseLight *= (1.0 - 6.0 * darknessFactor);

    // Prepare torch and small light contributions
    vec3 torchContribution = torch * hdrMulttorch;
    float screenBrightnessTerm = 1.0 + screenBrightness * MIN_LIGHT_BOOST;
    vec3 smallLightContribution = vec3(0.002, 0.005, 0.006) * screenBrightnessTerm;

    // Sum up the light components and apply final adjustments
    vec3 light = max(diffuseLight + torchContribution + smallLightContribution, 0.001);
    light *= 1.0 - darknessLightFactor;

    return light;
}

vec3 calcAmbientLight(vec3 Normal, vec2 lightmap, vec3 ambientUp, float diffuseSun, vec3 torch)
{

    vec3 ambient = calcAmbientLight(Normal, lightmap.xy, ambientUp, ambientUp, ambientUp, ambientUp, ambientUp,
                                    ambientUp, vec3(0.6 * ambientUp.b * lightmap.y), diffuseSun, torch);

    return ambient;
}