/// <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);
        }
        /// <summary>
        /// Compute Moon Coordinates without perturbations.
        /// Get moon azimuth and altitude.
        /// </summary>
        public void ComputeMoonCoords()
        {
            #region |Orbital Elements|

            // Orbital elements in radians.
            float N_Rad = Mathf.Deg2Rad * MoonOE.N;
            float i_Rad = Mathf.Deg2Rad * MoonOE.i;
            float M_Rad = Mathf.Deg2Rad * MoonOE.M;

            #endregion

            #region |Eccentric Anomaly|

            // Compute eccentric anomaly.
            float E = MoonOE.M + Mathf.Rad2Deg * MoonOE.e * Mathf.Sin(M_Rad) * (1 + SunOE.e * Mathf.Cos(M_Rad));

            // Eccentric anomaly to radians.
            float E_Rad = Mathf.Deg2Rad * E;

            #endregion

            #region |Rectangular Coordinates|

            // Rectangular coordinates of the sun in the plane of the ecliptic.
            float xv = MoonOE.a * (Mathf.Cos(E_Rad) - MoonOE.e);                                               // Debug.Log(xv);
            float yv = MoonOE.a * (Mathf.Sin(E_Rad) * Mathf.Sqrt(1 - MoonOE.e * MoonOE.e)) * Mathf.Sin(E_Rad); // Debug.Log(yv);

            // Convert to distance and true anomaly(r = radians, v = degrees).
            float r = Mathf.Sqrt(xv * xv + yv * yv);         // Debug.Log(r);
            float v = Mathf.Rad2Deg * Mathf.Atan2(yv, xv);   // Debug.Log(v);

            v = LSky_Mathf.NormalizeDegrees(v);

            // Longitude in radians.
            float l = Mathf.Deg2Rad * (v + MoonOE.w);

            float Cos_l     = Mathf.Cos(l);
            float Sin_l     = Mathf.Sin(l);
            float Cos_N_Rad = Mathf.Cos(N_Rad);
            float Sin_N_Rad = Mathf.Sin(N_Rad);
            float Cos_i_Rad = Mathf.Cos(i_Rad);

            float xeclip = r * (Cos_N_Rad * Cos_l - Sin_N_Rad * Sin_l * Cos_i_Rad);
            float yeclip = r * (Sin_N_Rad * Cos_l + Cos_N_Rad * Sin_l * Cos_i_Rad);
            float zeclip = r * (Sin_l * Mathf.Sin(i_Rad));

            #endregion

            #region Geocentric Coordinates.

            // Geocentric position for the moon and Heliocentric position for the planets.
            float lonecl = Mathf.Rad2Deg * Mathf.Atan2(yeclip, xeclip);

            // Rev lonecl
            lonecl = LSky_Mathf.NormalizeDegrees(lonecl);                                                      // Debug.Log(lonecl);

            float latecl = Mathf.Rad2Deg * Mathf.Atan2(zeclip, Mathf.Sqrt(xeclip * xeclip + yeclip * yeclip)); // Debug.Log(latecl);

            // Get true sun longitude.
            // float lonSun = TrueSunLongitude;

            // Ecliptic longitude and latitude in radians.
            float lonecl_Rad = Mathf.Deg2Rad * lonecl;
            float latecl_Rad = Mathf.Deg2Rad * latecl;

            float nr = 1.0f;
            float xh = nr * Mathf.Cos(lonecl_Rad) * Mathf.Cos(latecl_Rad);
            float yh = nr * Mathf.Sin(lonecl_Rad) * Mathf.Cos(latecl_Rad);
            float zh = nr * Mathf.Sin(latecl_Rad);

            // Geocentric posisition.
            float xs = 0.0f;
            float ys = 0.0f;

            // Convert the geocentric position to heliocentric position.
            float xg = xh + xs;
            float yg = yh + ys;
            float zg = zh;

            #endregion

            #region |Equatorial Coordinates|

            // Convert xg, yg in equatorial coordinates.
            float oblecl_Cos = Mathf.Cos(Oblecl);
            float oblecl_Sin = Mathf.Sin(Oblecl);

            float xe = xg;
            float ye = yg * oblecl_Cos - zg * oblecl_Sin;
            float ze = yg * oblecl_Sin + zg * oblecl_Cos;

            #endregion

            #region |Ascension, Declination And Hour Angle|

            // Right ascension.
            float RA = Mathf.Rad2Deg * Mathf.Atan2(ye, xe); //Debug.Log(RA);

            // Normalize right ascension.
            RA = LSky_Mathf.NormalizeDegrees(RA);  //Debug.Log(RA);

            // Declination.
            float Decl = Mathf.Rad2Deg * Mathf.Atan2(ze, Mathf.Sqrt(xe * xe + ye * ye));

            // Declination in radians.
            float Decl_Rad = Mathf.Deg2Rad * Decl;

            // Hour angle.
            float HA = ((SideralTime * 15) - RA); //Debug.Log(HA);

            // Rev hour angle.
            HA = LSky_Mathf.NormalizeDegrees(HA);     //Debug.Log(HA);

            // Hour angle in radians.
            float HA_Rad = Mathf.Deg2Rad * HA;

            #endregion

            #region |Declination in rectangular coordinates|

            // HA y Decl in rectangular coordinates.
            float Decl_Cos = Mathf.Cos(Decl_Rad);
            float xr       = Mathf.Cos(HA_Rad) * Decl_Cos;
            float yr       = Mathf.Sin(HA_Rad) * Decl_Cos;
            float zr       = Mathf.Sin(Decl_Rad);

            // Rotate the rectangualar coordinates system along of the Y axis(radians).
            float sinLatitude = Mathf.Sin(Latitude_Rad);
            float cosLatitude = Mathf.Cos(Latitude_Rad);

            float xhor = xr * sinLatitude - zr * cosLatitude;
            float yhor = yr;
            float zhor = xr * cosLatitude + zr * sinLatitude;

            #endregion

            #region |Azimuth, Altitude And Zenith[Radians]|

            m_MoonCoords.azimuth  = Mathf.Atan2(yhor, xhor) + Mathf.PI;
            m_MoonCoords.altitude = LSky_Mathf.k_HalfPI - Mathf.Atan2(zhor, Mathf.Sqrt(xhor * xhor + yhor * yhor));  // Altitude.

            #endregion
        }
        /// <summary>
        /// Compute Sun Coordinates.
        /// Get sun azimuth and altitude.
        /// </summary>
        public void ComputeSunCoords()
        {
            #region |Orbital Elements|

            // Mean Anomaly in radians.
            float M_Rad = SunOE.M * Mathf.Deg2Rad;

            #endregion

            #region |Eccentric Anomaly|

            // Compute eccentric anomaly.
            float E = SunOE.M + Mathf.Rad2Deg * SunOE.e * Mathf.Sin(M_Rad) * (1 + SunOE.e * Mathf.Cos(M_Rad));

            // Eccentric anomaly to radians.
            float E_Rad = Mathf.Deg2Rad * E;// Debug.Log(E);

            #endregion

            #region |Rectangular Coordinates|

            // Rectangular coordinates of the sun in the plane of the ecliptic.
            float xv = (Mathf.Cos(E_Rad) - SunOE.e);                           // Debug.Log(xv);
            float yv = (Mathf.Sin(E_Rad) * Mathf.Sqrt(1 - SunOE.e * SunOE.e)); // Debug.Log(yv);

            // Convert to distance and true anomaly(r = radians, v = degrees).
            float r = Mathf.Sqrt(xv * xv + yv * yv);       // Debug.Log(r);
            float v = Mathf.Rad2Deg * Mathf.Atan2(yv, xv); // Debug.Log(v);

            // Get sun distance.
            SunDistance = r;

            #endregion

            #region |True Longitude|

            // True sun longitude.
            float lonsun = v + SunOE.w;

            // Normalize sun longitude
            lonsun = LSky_Mathf.NormalizeDegrees(lonsun); // Debug.Log(lonsun);

            // True sun longitude to radians.
            float lonsun_Rad = Mathf.Deg2Rad * lonsun;

            // Set true sun longitude(radians) for use in others celestials calculations.
            TrueSunLongitude = lonsun_Rad;

            #endregion

            #region |Ecliptic And Equatorial Coordinates|

            // Ecliptic rectangular coordinates(radians):
            float xs = r * Mathf.Cos(lonsun_Rad);
            float ys = r * Mathf.Sin(lonsun_Rad);

            // Ecliptic rectangular coordinates rotate these to equatorial coordinates(radians).
            float oblecl_Cos = Mathf.Cos(Oblecl);
            float oblecl_Sin = Mathf.Sin(Oblecl);

            float xe = xs;
            float ye = ys * oblecl_Cos - 0.0f * oblecl_Sin;
            float ze = ys * oblecl_Sin + 0.0f * oblecl_Cos;

            #endregion

            #region |Ascension And Declination|

            // Right ascension(degrees):
            float RA = Mathf.Rad2Deg * Mathf.Atan2(ye, xe) / 15;

            // Declination(radians).
            float Decl = Mathf.Atan2(ze, Mathf.Sqrt(xe * xe + ye * ye));

            #endregion

            #region |Mean Longitude|

            // Mean sun longitude(degrees).
            float L = SunOE.w + SunOE.M;

            // Rev mean sun longitude.
            L = LSky_Mathf.NormalizeDegrees(L);

            // Set mean sun longitude for use in other celestials calculations.
            MeanSunLongitude = L;

            #endregion

            #region |Sideral Time|

            // Sideral time(degrees).
            float GMST0 = /*(L + 180) / 15;*/ ((L / 15) + 12);

            SideralTime      = GMST0 + TotalHours_UTC + longitude / 15 + 15 / 15;
            LocalSideralTime = Mathf.Deg2Rad * SideralTime * 15;

            // Hour angle(degrees).
            float HA = (SideralTime - RA) * 15; // Debug.Log(HA);

            // Hour angle in radians.
            float HA_Rad = Mathf.Deg2Rad * HA;  // Debug.Log(HA);

            #endregion

            #region |Hour Angle And Declination In Rectangular Coordinates|

            // HA anf Decl in rectangular coordinates(radians).
            float Decl_Cos = Mathf.Cos(Decl);

            // X axis points to the celestial equator in the south.
            float x = Mathf.Cos(HA_Rad) * Decl_Cos;// Debug.Log(x);

            // Y axis points to the horizon in the west.
            float y = Mathf.Sin(HA_Rad) * Decl_Cos; // Debug.Log(y);

            // Z axis points to the north celestial pole.
            float z = Mathf.Sin(Decl);// Debug.Log(z);

            // Rotate the rectangualar coordinates system along of the Y axis(radians).
            float sinLatitude = Mathf.Sin(Latitude_Rad);
            float cosLatitude = Mathf.Cos(Latitude_Rad);

            float xhor = x * sinLatitude - z * cosLatitude; // Debug.Log(xhor);
            float yhor = y;
            float zhor = x * cosLatitude + z * sinLatitude; // Debug.Log(zhor);

            #endregion

            #region Azimuth, Altitude And Zenith[Radians].

            m_SunCoords.azimuth  = Mathf.Atan2(yhor, xhor) + Mathf.PI;                                             // Azimuth.
            m_SunCoords.altitude = LSky_Mathf.k_HalfPI - Mathf.Atan2(zhor, Mathf.Sqrt(xhor * xhor + yhor * yhor)); // Altitude.

            #endregion
        }