Beispiel #1
0
        public static void GetSunlight(float altitude, float turbidity, Vector3D sunDirection,
                                       out Vector3F directSunlight, out Vector3F scatteredSunlight)
        {
            _spectrum.SetSolarSpectrum();

            sunDirection.TryNormalize();
            double cosZenith = sunDirection.Y;

            Vector3F direct, indirect;

            if (cosZenith > 0)
            {
                // Daylight - Sun is above horizon.
                double zenithAngle = Math.Acos(cosZenith);
                _spectrum.ApplyAtmosphericTransmittance(zenithAngle, turbidity, altitude, _spectrumDirect, _spectrumIndirect);
                direct   = _spectrumDirect.ToXYZ();
                indirect = _spectrumIndirect.ToXYZ();
            }
            else
            {
                // Twilight - Sun is below horizon.
                // We lookup luminance based on experimental results on cloudless nights.

                // Get sun angle in degrees for table lookup.
                float solarAltitude = (float)MathHelper.ToDegrees(Math.Asin(sunDirection.Y));

                // Get luminance from table (linearly interpolating the next two table entries).
                int   lower = (int)Math.Floor(solarAltitude);
                int   higher = (int)Math.Ceiling(solarAltitude);
                float a, b;
                TwilightLuminance.TryGetValue(lower, out a);
                TwilightLuminance.TryGetValue(higher, out b);
                float Y = InterpolationHelper.Lerp(a, b, solarAltitude - lower);

                // We use fixed chromacity values.
                float x = 0.2f;
                float y = 0.2f;

                // Convert xyY to XYZ.
                float X = x * (Y / y);
                float Z = (1.0f - x - y) * (Y / y);

                // Get sunlight from slightly above the horizon.
                const float  epsilon     = 0.001f;
                const double zenithAngle = ConstantsD.PiOver2 - epsilon;
                _spectrum.ApplyAtmosphericTransmittance(zenithAngle, turbidity, altitude, _spectrumDirect, _spectrumIndirect);
                direct   = _spectrumDirect.ToXYZ();
                indirect = _spectrumIndirect.ToXYZ();

                // Blend between table values and sunset light.
                float blend = MathHelper.Clamp(-solarAltitude / 5.0f, 0, 1);
                direct   = InterpolationHelper.Lerp(direct, new Vector3F(0, 0, 0), blend);
                indirect = InterpolationHelper.Lerp(indirect, new Vector3F(X, Y, Z), blend);
            }

            // Convert XYZ to RGB.
            directSunlight    = GraphicsHelper.XYZToRGB * direct;
            scatteredSunlight = GraphicsHelper.XYZToRGB * indirect;
        }