Beispiel #1
0
        private void UpdateSky()
        {
            // Update ephemeris model.
#if XBOX
            _ephemeris.Time = new DateTimeOffset(_time.Ticks, TimeSpan.Zero);
#else
            _ephemeris.Time = _time;
#endif
            _ephemeris.Update();

            // Update rotation of milky way. We also need to add an offset because the
            // cube map texture is rotated.
            _milkyWayNode.PoseWorld = new Pose(
                (Matrix33F)_ephemeris.EquatorialToWorld.Minor
                * Matrix33F.CreateRotationZ(ConstantsF.PiOver2 + -0.004f)
                * Matrix33F.CreateRotationX(ConstantsF.PiOver2 + -0.002f));

            // Update rotation of stars.
            _starfieldNode.PoseWorld = new Pose((Matrix33F)_ephemeris.EquatorialToWorld.Minor);

            // Update direction of sun.
            SunDirection = (Vector3F)_ephemeris.SunDirectionRefracted;
            var sunUp = SunDirection.Orthonormal1;
            _sunNode.LookAt(SunDirection, sunUp);

            // Update direction of moon.
            var moonDirection = (Vector3F)_ephemeris.MoonPosition.Normalized;
            var moonUp        = (Vector3F)_ephemeris.EquatorialToWorld.TransformDirection(Vector3D.Up);
            _moonNode.LookAt(moonDirection, moonUp);

            // The moon needs to know the sun position and brightness to compute the moon phase.
            _moonNode.SunDirection = (Vector3F)_ephemeris.SunPosition.Normalized;
            _moonNode.SunLight     = Ephemeris.ExtraterrestrialSunlight * SunlightScale;

            // The ScatteringSky needs the sun direction and brightness to compute the sky colors.
            _scatteringSkyNode.SunDirection = SunDirection;
            _scatteringSkyNode.SunColor     = Ephemeris.ExtraterrestrialSunlight * ScatteringSkyLightScale;

            // Update the light directions.
            _sunlightNode.LookAt(-SunDirection, sunUp);
            _moonlightNode.LookAt(-moonDirection, moonUp);

            // The ScatteringSkyNode can compute the actual sunlight.
            SunLight = _scatteringSkyNode.GetSunlight();

            // Undo the ScatteringSkyLightScale and apply a custom scale for the sunlight.
            SunLight = SunLight / ScatteringSkyLightScale * SunlightScale;

            // The ScatteringSkyNode can also compute the ambient light by sampling the
            // sky hemisphere.
            AmbientLight = _scatteringSkyNode.GetAmbientLight(256);
            AmbientLight = AmbientLight / ScatteringSkyLightScale * SunlightScale;

            // Desaturate the ambient light to avoid very blue shadows.
            AmbientLight = InterpolationHelper.Lerp(
                new Vector3F(Vector3F.Dot(AmbientLight, GraphicsHelper.LuminanceWeights)),
                AmbientLight,
                0.5f);

            // The Ephemeris model can compute the actual moonlight.
            Vector3F moonlight, moonAmbient;
            Ephemeris.GetMoonlight(
                _scatteringSkyNode.ObserverAltitude,
                2.2f,
                _ephemeris.MoonPosition,
                (float)_ephemeris.MoonPhaseAngle,
                out moonlight,
                out moonAmbient);
            moonlight   *= MoonlightScale;
            moonAmbient *= MoonlightScale;

            // Scale sun light to 0 at horizon.
            var directionalLightColor = SunLight;
            directionalLightColor *= MathHelper.Clamp(SunDirection.Y / 0.1f, 0, 1);

            var directionalLight = ((DirectionalLight)_sunlightNode.Light);
            directionalLight.Color = directionalLightColor;
            ((DirectionalLight)_moonlightNode.Light).Color = moonlight;
            ((AmbientLight)_ambientLightNode.Light).Color  = AmbientLight + moonAmbient + LightPollution;

            // Use the sunlight color to create a bright sun disk.
            var sunDiskColor = SunLight;
            sunDiskColor.TryNormalize();
            _sunNode.GlowColor0 = sunDiskColor * Ephemeris.ExtraterrestrialSunlight.Length * SunlightScale * 10;

            if (_enableClouds)
            {
                // Update lighting info of cloud layer nodes.
                _cloudLayerNode0.SunDirection = SunDirection;
                _cloudLayerNode0.SunLight     = SunLight;
                _cloudLayerNode0.AmbientLight = AmbientLight;

                // The second cloud layer uses simple unlit clouds (only ambient lighting).
                _cloudLayerNode1.SunDirection = SunDirection;
                _cloudLayerNode1.SunLight     = Vector3F.Zero;
                _cloudLayerNode1.AmbientLight = AmbientLight + SunLight;

                // Use the cloud map as the texture for the directional light to create cloud shadows.
                if (EnableCloudShadows)
                {
                    directionalLight.Texture = _cloudLayerNode0.CloudMap.Texture;
                }
                else
                {
                    directionalLight.Texture = null;
                }

                // Compute a texture offset so that the current sun position and the projected cloud
                // shadows match.
                // Since sky dome is always centered on the camera, position the sunlight node in
                // line with the camera.
                var cameraPosition = _cameraObject.CameraNode.PoseWorld.Position;
                var upVector       = Vector3F.AreNumericallyEqual(SunDirection, Vector3F.UnitZ) ? Vector3F.UnitY : Vector3F.UnitZ;
                _sunlightNode.LookAt(cameraPosition + SunDirection, cameraPosition, upVector);

                // Choose a scale for the cloud shadows.
                directionalLight.TextureScale = new Vector2F(-1000);

                // Get the scaled texture offset for the sun direction.
                directionalLight.TextureOffset = _cloudLayerNode0.GetTextureCoordinates(SunDirection) *
                                                 directionalLight.TextureScale;
            }

            // The ScatteringSkyNode can also estimate a fog color by sampling the horizon colors.
            Vector3F fogColor = _scatteringSkyNode.GetFogColor(256, FogSampleAngle);

            // Desaturate the fog color.
            fogColor = InterpolationHelper.Lerp(
                new Vector3F(Vector3F.Dot(fogColor, GraphicsHelper.LuminanceWeights)),
                fogColor,
                FogSaturation);

            // Find any FogNode in the scene and update its fog color.
            foreach (var fogNode in ((Scene)_scene).GetSubtree().OfType <FogNode>())
            {
                var fog = fogNode.Fog;
                fog.Color0             = fog.Color1 = new Vector4F(fogColor, 1);
                fog.ScatteringSymmetry = FogScatteringSymmetry;
            }

            // TODO: If the fog is dense, reduce the direct light and increase the ambient light.
        }