private void RenderDebugInfo(RenderContext context) { _debugRenderer.Clear(); _debugRenderer.DrawAxes(Pose.Identity, 0.5f, true); //_debugRenderer.DrawTexture(_cloudLayerNode._renderTarget, new Rectangle(1280-512, 0, 512, 512)); #if XBOX _debugRenderer.DrawText(_ephemeris.Time.DateTime.ToString()); #else _debugRenderer.DrawText(_ephemeris.Time.ToString()); #endif _debugRenderer.PointSize = 10; var extraterrestrialSunlight = Ephemeris.ExtraterrestrialSunlight; Vector3F sun; Vector3F ambient; Ephemeris.GetSunlight(_scatteringSky.ObserverAltitude, 2.2f, _scatteringSky.SunDirection, out sun, out ambient); var scatterSun = _scatteringSky.GetSunlight() / _scatteringSky.SunIntensity * extraterrestrialSunlight; var scatterAmbient = _scatteringSky.GetAmbientLight(1024); scatterAmbient = scatterAmbient / _scatteringSky.SunIntensity * extraterrestrialSunlight; var scatterFog = _scatteringSky.GetFogColor(128) / _scatteringSky.SunIntensity * extraterrestrialSunlight; var luminance = Vector3F.Dot(GraphicsHelper.LuminanceWeights, scatterFog); scatterFog = InterpolationHelper.Lerp(scatterFog, new Vector3F(luminance), 0.7f); _debugRenderer.DrawText("Extraterrestrial sun intensity:" + extraterrestrialSunlight.Length); _debugRenderer.DrawText("Spectrum sun intensity:" + sun.Length); _debugRenderer.DrawText("Scatter sun intensity:" + scatterSun.Length); _debugRenderer.DrawText("\nSpectrum ambient intensity:" + ambient.Length); _debugRenderer.DrawText("Scatter ambient intensity:" + scatterAmbient.Length); _debugRenderer.DrawText("\nScatter fog intensity:" + scatterFog.Length); _debugRenderer.DrawPoint(new Vector3F(-0.5f, 0, 0), new Color((Vector3)extraterrestrialSunlight.Normalized), true); sun.TryNormalize(); ambient /= ambient.Length; _debugRenderer.DrawPoint(new Vector3F(0, 0, 0), new Color((Vector3)sun), true); _debugRenderer.DrawPoint(new Vector3F(0, -0.5f, 0), new Color((Vector3)ambient), true); scatterSun.TryNormalize(); scatterAmbient.TryNormalize(); _debugRenderer.DrawPoint(new Vector3F(0.5f, 0, 0), new Color((Vector3)scatterSun), true); _debugRenderer.DrawPoint(new Vector3F(0.5f, -0.5f, 0), new Color((Vector3)scatterAmbient), true); scatterFog.TryNormalize(); _debugRenderer.DrawPoint(new Vector3F(0, 0.5f, 0), new Color((Vector3)scatterFog), true); _debugRenderer.PointSize = 40f; _debugRenderer.Render(context); }
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. }