/// <summary> Compute Optimized Optical Depth. </summary>
        /// <param name="yPos"> Y axis pos. </param>
        /// <param bame="sr"></param>
        /// <param name="sm"></param>
        public void OptimizedOpticalDepth(float yPos, out float sr, out float sm)
        {
            yPos = LSky_Mathf.Saturate(yPos * parameters.atmosphereHaziness);
            yPos = 1.0f / (yPos + parameters.atmosphereZenith);

            sr = parameters.rayleighZenithLength * yPos;
            sm = parameters.mieZenithLength * yPos;
        }
        /// <summary> Compute Optical Depth Based On Nielsen Paper. </summary>
        /// <param name="yPos"> Y axis pos. </param>
        /// <param bame="sr"></param>
        /// <param name="sm"></param>
        public void NielsenOpticalDepth(float yPos, out float sr, out float sm)
        {
            yPos = LSky_Mathf.Saturate(yPos);

            float f = Mathf.Pow(yPos, parameters.atmosphereHaziness);
            float t = (1.05f - f) * 190000;

            sr = t + f * (parameters.rayleighZenithLength - t);
            sm = t + f * (parameters.mieZenithLength - t);
        }
        /// <summary>
        /// Compute Custom Optical Depth.
        /// Optical depth with small changes for more customization.
        /// </summary>
        /// <param name="yPos"> Y axis pos. </param>
        /// <param bame="sr"></param>
        /// <param name="sm"></param>
        public void CustomOpticalDepth(float yPos, out float sr, out float sm)
        {
            yPos = LSky_Mathf.Saturate(yPos * parameters.atmosphereHaziness);

            float zenith = Mathf.Acos(yPos);

            zenith = Mathf.Cos(zenith) + 0.15f * Mathf.Pow(93.885f - ((zenith * 180.0f) / Mathf.PI), -1.253f);
            zenith = 1.0f / (zenith + (parameters.atmosphereZenith * 0.5f));

            sr = parameters.rayleighZenithLength * zenith;
            sm = parameters.mieZenithLength * zenith;
        }
        /// <summary>
        /// Compute Custom Optical Depth.
        /// </summary>
        /// <param name="yPos"> Y axis pos. </param>
        /// <param bame="sr"></param>
        /// <param name="sm"></param>
        public void OpticalDepth(float yPos, out float sr, out float sm)
        {
            yPos = LSky_Mathf.Saturate(yPos);

            float zenith = Mathf.Acos(yPos);

            zenith = Mathf.Cos(zenith) + 0.15f * Mathf.Pow(93.885f - ((zenith * 180.0f) / Mathf.PI), -1.253f);
            zenith = 1.0f / zenith;

            sr = parameters.rayleighZenithLength * zenith;
            sm = parameters.mieZenithLength * zenith;
        }
        public Color AtmosphericScattering(float sr, float sm, float sunCosTheta, float moonCosTheta, bool enableMiePhase, float sunEvaluateTime)
        {
            // Combined Extinction Factor.
            Vector3 fex;

            fex.x = Mathf.Exp(-(betaRay.x * sr + betaMie.x * sm));
            fex.y = Mathf.Exp(-(betaRay.y * sr + betaMie.y * sm));
            fex.z = Mathf.Exp(-(betaRay.z * sr + betaMie.z * sm));

            Vector3 nfex = Vector3.one - fex;
            Vector3 nfexm;

            nfexm.x = nfex.x * fex.x;
            nfexm.y = nfex.y * fex.y;
            nfexm.z = nfex.z * fex.z;

            Vector3 combExcFac       = LSky_Mathf.Saturate(Vector3.Lerp(nfex, nfexm, SunsetDawnHorizon));
            float   SunRayleighPhase = RayleighPhase(sunCosTheta);

            // Sun/Day
            Vector3 sunBRT;

            sunBRT.x = betaRay.x * SunRayleighPhase;
            sunBRT.y = betaRay.y * SunRayleighPhase;
            sunBRT.z = betaRay.z * SunRayleighPhase;

            float sunMiePhase = enableMiePhase ? MiePhase(parameters.sunMie.anisotropy, sunCosTheta) * parameters.scattering : 1.0f;

            Vector3 sunBMT;

            sunBMT.x = sunMiePhase * parameters.sunMie.tint.r * betaMie.x;
            sunBMT.y = sunMiePhase * parameters.sunMie.tint.g * betaMie.y;
            sunBMT.z = sunMiePhase * parameters.sunMie.tint.b * betaMie.z;

            Vector3 sunBRMT;

            sunBRMT.x = (sunBRT.x + sunBMT.x) / (betaRay.x + betaMie.x);
            sunBRMT.y = (sunBRT.y + sunBMT.y) / (betaRay.y + betaMie.y);
            sunBRMT.z = (sunBRT.z + sunBMT.z) / (betaRay.z + betaMie.z);

            Vector3 sunScatter; Color sunAtmosphereTint = parameters.sunAtmosphereTint.Evaluate(sunEvaluateTime);

            sunScatter.x = DayIntensity * (sunBRMT.x * combExcFac.x) * sunAtmosphereTint.r;
            sunScatter.y = DayIntensity * (sunBRMT.y * combExcFac.y) * sunAtmosphereTint.g;
            sunScatter.z = DayIntensity * (sunBRMT.z * combExcFac.z) * sunAtmosphereTint.b;

            Color result = new Color(0.0f, 0.0f, 0.0f, 1.0f);

            if (moonRayleighMode != LSky_CelestialRayleighMode.Off)
            {
                Vector3 moonScatter;

                // Simple Moon Scatter.
                moonScatter.x = NightIntensity * nfex.x * parameters.moonAtmosphereTint.r;
                moonScatter.y = NightIntensity * nfex.y * parameters.moonAtmosphereTint.g;
                moonScatter.z = NightIntensity * nfex.x * parameters.moonAtmosphereTint.b;

                float moonMiePhase = enableMiePhase ? LQHenyeyGreenstein(parameters.moonMie.anisotropy, moonCosTheta) * parameters.moonMie.scattering : 1.0f;

                moonScatter.x += moonMiePhase * parameters.moonMie.tint.r;
                moonScatter.y += moonMiePhase * parameters.moonMie.tint.g;
                moonScatter.z += moonMiePhase * parameters.moonMie.tint.b;

                result.r = sunScatter.x + moonScatter.x;
                result.g = sunScatter.y + moonScatter.y;
                result.b = sunScatter.z + moonScatter.z;
            }
            else
            {
                result.r = sunScatter.x;
                result.g = sunScatter.y;
                result.b = sunScatter.z;
            }

            return(result);
        }