Ejemplo n.º 1
0
        public void UpdateSubmesh(IGraphicsService graphicsService, WaterNode node)
        {
            if (node.Volume == null)
            return;

              // We have to update the submesh if it is null or disposed.
              //   Submesh == null                            --> Update
              //   Submesh != null && VertexBuffer.IsDisposed --> Update
              //   Submesh != null && VertexBuffer == null    --> This is the EmptyShape. No updated needed.
              if (Submesh == null || (Submesh.VertexBuffer != null && Submesh.VertexBuffer.IsDisposed))
            ShapeMeshCache.GetMesh(graphicsService, node.Volume, out Submesh, out SubmeshMatrix);
        }
Ejemplo n.º 2
0
        private void RenderUnderwaterGeometry(WaterNode node, CameraNode cameraNode)
        {
            var graphicsDevice = _graphicsService.GraphicsDevice;
              graphicsDevice.RasterizerState = RasterizerState.CullNone;
              //graphicsDevice.RasterizerState = GraphicsHelper.RasterizerStateWireFrame;
              graphicsDevice.DepthStencilState = DepthStencilState.None;

              var data = ((WaterRenderData)node.RenderData);
              var submesh = data.Submesh;
              if (submesh != null)
              {
            // User-defined volume
            _parameterWorld.SetValue((Matrix)(
              node.PoseWorld
              * Matrix44F.CreateScale(node.ScaleWorld)
              * data.SubmeshMatrix));
              }
              else
              {
            // Underwater rendering of infinite ocean.
            // --> Use a shared box around the camera.
            if (_boxSubmesh == null)
              _boxSubmesh = MeshHelper.GetBox(_graphicsService);

            // The box must not be clipped at near or far plane:
            // Make the box extent (size, size / 2, size) with size / 2 = (near + far) / 2.
            var projection = cameraNode.Camera.Projection;
            float size = projection.Near + projection.Far;

            // The box is centered on the camera. (Ignore camera orientation in case
            // the camera has a roll.)
            Vector3F position = cameraNode.PoseWorld.Position;

            // Top of box must go through water node origin, except when waves are
            // rendered. (Waves are bent up or down at the near plane.)
            if (node.Waves == null || node.Waves.DisplacementMap == null)
              position.Y = node.PoseWorld.Position.Y - size / 4.0f;

            var world = Matrix44F.CreateTranslation(position) * Matrix44F.CreateScale(size, size / 2.0f, size);
            _parameterWorld.SetValue((Matrix)world);

            submesh = _boxSubmesh;
              }

              if (node.Water.CausticsSampleOffset <= 0 || node.Water.CausticsIntensity <= Numeric.EpsilonF)
            _passUnderwater.Apply();
              else
            _passUnderwaterCaustics.Apply();

              submesh.Draw();
        }
Ejemplo n.º 3
0
        private void RenderSurface(WaterNode node, CameraNode cameraNode, bool isCameraUnderwater)
        {
            var graphicsDevice = _graphicsService.GraphicsDevice;
              var projection = cameraNode.Camera.Projection;

              graphicsDevice.RasterizerState = RasterizerState.CullNone;
              //graphicsDevice.RasterizerState = isCameraUnderwater ? RasterizerState.CullClockwise : RasterizerState.CullCounterClockwise;
              //graphicsDevice.RasterizerState = GraphicsHelper.RasterizerStateWireFrame;

              graphicsDevice.DepthStencilState = node.DepthBufferWriteEnable
                                         ? DepthStencilState.Default
                                         : DepthStencilState.DepthRead;

              // TODO: Support gamma corrected LDR rendering.
              //if (context.IsHdrEnabled()) _passGamma...

              if (node.Volume != null)
              {
            // ----- Render with user-defined water volume.
            var data = ((WaterRenderData)node.RenderData);

            _parameterWorld.SetValue((Matrix)(
              node.PoseWorld
              * Matrix44F.CreateScale(node.ScaleWorld)
              * data.SubmeshMatrix));
            ApplySurfacePass(node, false);
            data.Submesh.Draw();
              }
              else if (node.Waves == null || node.Waves.DisplacementMap == null)
              {
            // ----- Infinite ocean without displacement map.
            // Draw using simple, gigantic quad.
            if (_quadSubmesh == null)
            {
              // This is the really lazy way to get a quad submesh. :-P
              var quadShape = new TransformedShape(new GeometricObject(
            new RectangleShape(1, 1),
            new Pose(Matrix33F.CreateRotationX(-ConstantsF.PiOver2)))).GetMesh(0.001f, 4);

              _quadSubmesh = MeshHelper.CreateSubmesh(graphicsDevice, quadShape, -1);
            }

            // Position the quad under the camera and choose a size large enough to cover everything.
            Vector3F position = cameraNode.PoseWorld.Position;
            position.Y = node.PoseWorld.Position.Y;

            // Add a bit to make sure that the surface is rendered above the underwater geometry.
            // Without the epsilon if the camera cuts the surface, there might be a horizontal ~1 pixel
            // line when the surface quad ends before the underwater shape.
            position.Y += Numeric.EpsilonF * 10;

            float farPlaneRadius =
              new Vector3F(Math.Max(Math.Abs(projection.Right), Math.Abs(projection.Left)),
                       Math.Max(Math.Abs(projection.Top), Math.Abs(projection.Bottom)),
                       projection.Far
                      ).Length;
            float size = 2 * farPlaneRadius;

            Matrix44F world = Matrix44F.CreateTranslation(position) * Matrix44F.CreateScale(size, 1, size);
            _parameterWorld.SetValue((Matrix)world);

            ApplySurfacePass(node, false);
            _quadSubmesh.Draw();
              }
              else
              {
            // ----- Use Projected Grid.
            if (SetProjectedGridParameters(node, cameraNode, isCameraUnderwater))
            {
              ApplySurfacePass(node, true);
              ProjectedGridParameters.Submesh.Draw();
            }
              }
        }
Ejemplo n.º 4
0
 private void ApplySurfacePass(WaterNode node, bool useProjectedGrid)
 {
     if (!useProjectedGrid)
       {
     // Displacement mapping active if we have at least a wave normal map.
     if (node.Waves != null && node.Waves.NormalMap != null)
     {
       if (node.Water.CausticsIntensity > 0)
     _passMeshDisplacedFoamCaustics.Apply();
       else if (node.Water.FoamMap != null)
     _passMeshDisplacedFoam.Apply();
       else
     _passMeshDisplaced.Apply();
     }
     else
     {
       if (node.Water.FoamMap != null && node.Flow != null)
     _passMeshFoamFlow.Apply();
       else if (node.Water.FoamMap != null)
     _passMeshFoam.Apply();
       else if (node.Flow != null)
     _passMeshFlow.Apply();
       else
     _passMesh.Apply();
     }
       }
       else
       {
     if (node.Water.CausticsIntensity > 0)
       _passProjectedGridFoamCaustics.Apply();
     else if (node.Water.FoamMap != null)
       _passProjectedGridFoam.Apply();
     else
       _passProjectedGrid.Apply();
       }
 }
Ejemplo n.º 5
0
        // Returns false if the water is not visible.
        private bool SetProjectedGridParameters(WaterNode node, CameraNode cameraNode, bool isCameraUnderwater)
        {
            var projection = cameraNode.Camera.Projection;

              // Push projection camera back behind the original camera to get a borders
              // around the visible FOV.
              Pose cameraPose = cameraNode.PoseWorld;
              Matrix33F cameraOrientation = cameraPose.Orientation;
              Vector3F cameraUp = cameraOrientation.GetColumn(1);
              Vector3F cameraBack = cameraOrientation.GetColumn(2);

              Vector3F pushedBackCameraPosition = cameraPose.Position + cameraBack * ProjectedGridParameters.Offset;

              if (_projectedGridNearCorners == null)
            _projectedGridNearCorners = new Vector3[4];

              float seaLevel = node.PoseWorld.Position.Y;

              // Get view space vectors from camera to near plane.
              Vector3F rightTopDirection = new Vector3F(projection.Right, projection.Top, -projection.Near);
              Vector3F leftTopDirection = new Vector3F(projection.Left, projection.Top, -projection.Near);
              Vector3F leftBottomDirection = new Vector3F(projection.Left, projection.Bottom, -projection.Near);
              Vector3F rightBottomDirection = new Vector3F(projection.Right, projection.Bottom, -projection.Near);

              // Transform vectors to world space directions.
              rightTopDirection = cameraPose.ToWorldDirection(rightTopDirection);
              leftTopDirection = cameraPose.ToWorldDirection(leftTopDirection);
              leftBottomDirection = cameraPose.ToWorldDirection(leftBottomDirection);
              rightBottomDirection = cameraPose.ToWorldDirection(rightBottomDirection);

              // Projected grid is a quad which must cover the frustum near plane parts which show the
              // water surface. This part is bound by the horizon plane (horizontal plane through camera
              // position) and the water plane.
              // In the simple academic case, the projected grid quad is equal to the near plane quad.
              // This makes sense if the camera is looking down.
              if (!Numeric.IsZero(cameraUp.Y))
              {
            // Camera is NOT exactly looking down:
            // In general the camera will show part of the water and part of the sky and a lot projected
            // grid triangles are wasted.
            // For this case it is better to compute a projected grid quad which covers the necessary
            // camera near plane quad more tightly.

            // If camera is exactly at sea level, push it away a bit to avoid a degenerate case
            // where the whole grid is projected into infinity...
            if (Numeric.AreEqual(pushedBackCameraPosition.Y, seaLevel))
            {
              if (isCameraUnderwater)
            pushedBackCameraPosition.Y -= Numeric.EpsilonF;
              else
            pushedBackCameraPosition.Y += Numeric.EpsilonF;
            }

            // Convert near plane corners to world space.
            // Transform vectors to world space directions.
            Vector3F rightTopPosition = rightTopDirection + pushedBackCameraPosition;
            Vector3F leftTopPosition = leftTopDirection + pushedBackCameraPosition;
            Vector3F rightBottomPosition = rightBottomDirection + pushedBackCameraPosition;
            Vector3F leftBottomPosition = leftBottomDirection + pushedBackCameraPosition;

            // Get min and max y of the corners.
            float minY = Math.Min(rightTopPosition.Y, leftTopPosition.Y);
            float maxY = Math.Max(rightTopPosition.Y, leftTopPosition.Y);
            minY = Math.Min(minY, rightBottomPosition.Y);
            maxY = Math.Max(maxY, rightBottomPosition.Y);
            minY = Math.Min(minY, leftBottomPosition.Y);
            maxY = Math.Max(maxY, leftBottomPosition.Y);
            Debug.Assert(minY < maxY);

            // Vertically the projected grid is bound by the horizon plane and the water plane.
            Plane topPlane = new Plane(Vector3F.UnitY, pushedBackCameraPosition.Y);
            Plane bottomPlane = new Plane(Vector3F.UnitY, seaLevel);
            if (seaLevel > pushedBackCameraPosition.Y)
            {
              // Camera is under water.
              MathHelper.Swap(ref topPlane, ref bottomPlane);
            }

            Debug.Assert(bottomPlane.DistanceFromOrigin < topPlane.DistanceFromOrigin);

            // Move planes vertically so that they touch the near plane quad.
            bottomPlane.DistanceFromOrigin = Math.Max(minY, bottomPlane.DistanceFromOrigin);
            topPlane.DistanceFromOrigin = Math.Min(maxY, topPlane.DistanceFromOrigin);

            // Abort if camera is not looking at water surface.
            if (bottomPlane.DistanceFromOrigin > topPlane.DistanceFromOrigin)
              return false;

            // Horizontally the projected grid quad is bound by two vertical planes which go through
            // the camera origin and the left-most and right-most near plane quad corners.
            // These plane are parallel to the camera up axis.
            // (The left vector in this case is orthogonal to world up. It is not the camera left.)
            Vector3F left = Vector3F.Cross(cameraBack, Vector3F.UnitY);

            // Get left-most and right-most corner.
            Vector3F leftMostCorner = rightTopPosition;
            float leftMostDistance = Vector3F.Dot(left, rightTopDirection);
            Vector3F rightMostCorner = rightTopPosition;
            float rightMostDistance = -leftMostDistance;

            float d = Vector3F.Dot(left, leftTopDirection);
            if (d > leftMostDistance)
            {
              leftMostCorner = leftTopPosition;
              leftMostDistance = d;
            }
            if (-d > rightMostDistance)
            {
              rightMostCorner = leftTopPosition;
              rightMostDistance = -d;
            }

            d = Vector3F.Dot(left, rightBottomDirection);
            if (d > leftMostDistance)
            {
              leftMostCorner = rightBottomPosition;
              leftMostDistance = d;
            }
            if (-d > rightMostDistance)
            {
              rightMostCorner = rightBottomPosition;
              rightMostDistance = -d;
            }

            d = Vector3F.Dot(left, leftBottomDirection);
            if (d > leftMostDistance)
            {
              leftMostCorner = leftBottomPosition;
              //leftMostDistance = d;
            }
            if (-d > rightMostDistance)
            {
              rightMostCorner = leftBottomPosition;
              //rightMostDistance = -d;
            }

            // The projected grid must cover a quad on the near plane. Let's compute a rotated
            // camera with the same near plane (= identical camera forward/backward direction) but
            // an up vector which is parallel to the world up vector.
            Vector3F rotatedCameraUp = Vector3F.Cross(left, cameraBack).Normalized;

            // The side planes go through the left/right-most points and through the camera origin.
            // They are parallel to the up vector of the rotated camera.
            Plane leftPlane = new Plane(pushedBackCameraPosition, leftMostCorner, leftMostCorner + rotatedCameraUp);
            Plane rightPlane = new Plane(pushedBackCameraPosition, rightMostCorner, rightMostCorner + rotatedCameraUp);

            // The 4 planes (water, horizon, left, right) can be cut with the near plane to get
            // the projected grid quad.
            Plane nearPlane = new Plane(leftTopPosition, rightTopPosition, leftBottomPosition);

            rightTopPosition = GeometryHelper.GetIntersection(nearPlane, topPlane, rightPlane);
            leftTopPosition = GeometryHelper.GetIntersection(nearPlane, topPlane, leftPlane);
            rightBottomPosition = GeometryHelper.GetIntersection(nearPlane, bottomPlane, rightPlane);
            leftBottomPosition = GeometryHelper.GetIntersection(nearPlane, bottomPlane, leftPlane);

            rightTopDirection = rightTopPosition - pushedBackCameraPosition;
            leftTopDirection = leftTopPosition - pushedBackCameraPosition;
            rightBottomDirection = rightBottomPosition - pushedBackCameraPosition;
            leftBottomDirection = leftBottomPosition - pushedBackCameraPosition;

            // Choose near corners such that the triangles where texCoord.y is lower are
            // rendered in the far for correct depth-sorting.
            if (pushedBackCameraPosition.Y > seaLevel)
            {
              if (rightTopDirection.Y < rightBottomDirection.Y)
              {
            MathHelper.Swap(ref rightTopDirection, ref rightBottomDirection);
            MathHelper.Swap(ref leftTopDirection, ref leftBottomDirection);
              }
            }
            else
            {
              if (rightTopDirection.Y > rightBottomDirection.Y)
              {
            MathHelper.Swap(ref rightTopDirection, ref rightBottomDirection);
            MathHelper.Swap(ref leftTopDirection, ref leftBottomDirection);
              }
            }
              }
              else
              {
            // Camera is looking down.
            if (pushedBackCameraPosition.Y < seaLevel)
            {
              // Underwater looking up. We have to swap top and bottom.
              MathHelper.Swap(ref rightTopDirection, ref rightBottomDirection);
              MathHelper.Swap(ref leftTopDirection, ref leftBottomDirection);
            }
              }

              _projectedGridNearCorners[0] = (Vector3)rightTopDirection;
              _projectedGridNearCorners[1] = (Vector3)leftTopDirection;
              _projectedGridNearCorners[2] = (Vector3)rightBottomDirection;
              _projectedGridNearCorners[3] = (Vector3)leftBottomDirection;

              _parameterPushedBackCameraPosition.SetValue((Vector3)pushedBackCameraPosition);
              _parameterNearCorners.SetValue(_projectedGridNearCorners);
              _parameterWorld.SetValue(node.PoseWorld);
              return true;
        }
Ejemplo n.º 6
0
    public WaterSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;
      _graphicsScreen = new DeferredGraphicsScreen(Services);
      _graphicsScreen.DrawReticle = true;
      GraphicsService.Screens.Insert(0, _graphicsScreen);
      GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services));

      Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer);
      Services.Register(typeof(IScene), null, _graphicsScreen.Scene);

      // Add gravity and damping to the physics Simulation.
      Simulation.ForceEffects.Add(new Gravity());
      Simulation.ForceEffects.Add(new Damping());

      // Add a custom game object which controls the camera.
      var cameraGameObject = new CameraObject(Services);
      GameObjectService.Objects.Add(cameraGameObject);
      _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode;

      // More standard objects.
      GameObjectService.Objects.Add(new GrabObject(Services));
      GameObjectService.Objects.Add(new ObjectCreatorObject(Services));
      //GameObjectService.Objects.Add(new StaticSkyObject(Services));
      var dynamicSkyObject = new DynamicSkyObject(Services, true, false, true);
      GameObjectService.Objects.Add(dynamicSkyObject);

      // Add a ground plane with some detail to see the water refractions.
      Simulation.RigidBodies.Add(new RigidBody(new PlaneShape(new Vector3F(0, 1, 0), 0)));
      GameObjectService.Objects.Add(new StaticObject(Services, "Gravel/Gravel", 1, new Pose(new Vector3F(0, 0.001f, 0))));

      GameObjectService.Objects.Add(new DudeObject(Services));
      GameObjectService.Objects.Add(new DynamicObject(Services, 1));
      GameObjectService.Objects.Add(new DynamicObject(Services, 2));
      GameObjectService.Objects.Add(new DynamicObject(Services, 5));
      GameObjectService.Objects.Add(new DynamicObject(Services, 6));
      GameObjectService.Objects.Add(new DynamicObject(Services, 7));
      GameObjectService.Objects.Add(new FogObject(Services) { AttachToCamera = true });

      // The LavaBalls class controls all lava ball instances.
      var lavaBalls = new LavaBallsObject(Services);
      GameObjectService.Objects.Add(lavaBalls);

      // Add a few palm trees.
      var random = new Random(12345);
      for (int i = 0; i < 10; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(-3, -8), 0, random.NextFloat(0, -5));
        Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));
        float scale = random.NextFloat(0.5f, 1.2f);
        GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, new Pose(position, orientation)));
      }

      // Define the appearance of the water.
      var water = new Water
      {
        SpecularColor = new Vector3F(10f),

        // Small water ripples/waves are created using scrolling normal maps.
        NormalMap0 = ContentManager.Load<Texture2D>("Water/Wave0"),
        NormalMap1 = ContentManager.Load<Texture2D>("Water/Wave1"),
        NormalMap0Scale = 1.8f,
        NormalMap1Scale = 2.2f,
        NormalMap0Velocity = new Vector3F(-0.02f, 0, 0.03f),
        NormalMap1Velocity = new Vector3F(0.02f, 0, -0.03f),
        NormalMap0Strength = 0.5f,
        NormalMap1Strength = 0.5f,

        ReflectionDistortion = 0.2f,
        ReflectionColor = new Vector3F(0.7f),
        RefractionDistortion = 0.05f,
      };

      // Create a box-shaped body of water.
      // We use a TransformedShape containing a BoxShape because the top of the 
      // water body must be at height 0.
      var shape = new TransformedShape(new GeometricObject(
        new BoxShape(10, 1, 20),
        new Pose(new Vector3F(0, -0.5f, 0))));
      _waterNode0 = new WaterNode(water, shape)
      {
        PoseWorld = new Pose(new Vector3F(-1, 0.5f, 0), Matrix33F.CreateRotationY(0.1f)),
        SkyboxReflection = _graphicsScreen.Scene.GetDescendants().OfType<SkyboxNode>().First(),
        DepthBufferWriteEnable = true,
      };
      _graphicsScreen.Scene.Children.Add(_waterNode0);

      // Optional: Create a WaterFlow to move the water using a flow texture.
      _waterFlow0 = new WaterFlow
      {
        FlowMapSpeed = 0.5f,
        FlowMap = GenerateFlowMap(),
        CycleDuration = 3f,
        NoiseMapStrength = 0.1f,
        NoiseMapScale = 0.5f,
      };
      _waterNode0.Flow = _waterFlow0;

      // Optional: Use a planar reflection instead of the skybox reflection.
      // We add a PlanarReflectionNode as a child of the WaterNode.
      var renderToTexture = new RenderToTexture
      {
        Texture = new RenderTarget2D(GraphicsService.GraphicsDevice, 512, 512, false, SurfaceFormat.HdrBlendable, DepthFormat.None),
      };
      var planarReflectionNode = new PlanarReflectionNode(renderToTexture)
      {
        // Same shape as WaterNode.
        Shape = _waterNode0.Shape,

        // Reflection plane is horizontal.
        NormalLocal = new Vector3F(0, 1, 0),
      };
      _waterNode0.PlanarReflection = planarReflectionNode;
      _waterNode0.Children = new SceneNodeCollection(1) { planarReflectionNode };

      // Create a short river with an inclined water surface.
      // Using a WaterFlow with a SurfaceSlopeSpeed, the water automatically flows
      // down the inclined surface.
      _waterNode1 = new WaterNode(water, GetSpiralShape())
      {
        PoseWorld = new Pose(new Vector3F(10, 1.5f, 0), Matrix33F.CreateRotationY(0.1f)),
        EnableUnderwaterEffect = false,
        SkyboxReflection = _graphicsScreen.Scene.GetDescendants().OfType<SkyboxNode>().First(),
        Flow = new WaterFlow
        {
          SurfaceSlopeSpeed = 0.5f,
          CycleDuration = 2f,
          NoiseMapStrength = 0.1f,
          NoiseMapScale = 1,
        }
      };
      _graphicsScreen.Scene.Children.Add(_waterNode1);
    }
Ejemplo n.º 7
0
    public OceanSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      SampleFramework.IsMouseVisible = false;
      _graphicsScreen = new DeferredGraphicsScreen(Services);
      _graphicsScreen.DrawReticle = true;
      GraphicsService.Screens.Insert(0, _graphicsScreen);
      GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services));

      Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer);
      Services.Register(typeof(IScene), null, _graphicsScreen.Scene);

      // Add gravity and damping to the physics Simulation.
      Simulation.ForceEffects.Add(new Gravity());
      Simulation.ForceEffects.Add(new Damping());

      // Add a custom game object which controls the camera.
      var cameraGameObject = new CameraObject(Services);
      GameObjectService.Objects.Add(cameraGameObject);
      _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode;

      // More standard objects.
      GameObjectService.Objects.Add(new GrabObject(Services));
      GameObjectService.Objects.Add(new ObjectCreatorObject(Services));
      //GameObjectService.Objects.Add(new StaticSkyObject(Services));
      var dynamicSkyObject = new DynamicSkyObject(Services, true, false, true);
      GameObjectService.Objects.Add(dynamicSkyObject);

      // Add an island model.
      GameObjectService.Objects.Add(new StaticObject(Services, "Island/Island", new Vector3F(30), new Pose(new Vector3F(0, 0.75f, 0)), true, true));

      GameObjectService.Objects.Add(new DynamicObject(Services, 1));
      GameObjectService.Objects.Add(new DynamicObject(Services, 2));
      GameObjectService.Objects.Add(new DynamicObject(Services, 5));
      GameObjectService.Objects.Add(new DynamicObject(Services, 6));
      GameObjectService.Objects.Add(new DynamicObject(Services, 7));
      GameObjectService.Objects.Add(new FogObject(Services) { AttachToCamera = true });

      // The LavaBalls class controls all lava ball instances.
      var lavaBalls = new LavaBallsObject(Services);
      GameObjectService.Objects.Add(lavaBalls);

      // Add a few palm trees.
      Random random = new Random(12345);
      for (int i = 0; i < 20; i++)
      {
        Vector3F position = new Vector3F(random.NextFloat(-7, 4), 0, random.NextFloat(13, 18));
        Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi));
        float scale = random.NextFloat(0.8f, 1.2f);
        GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, new Pose(position, orientation)));
      }

      // Define the appearance of the water.
      var waterOcean = new Water
      {
        SpecularColor = new Vector3F(20f),
        SpecularPower = 500,

        NormalMap0 = null,
        NormalMap1 = null,

        RefractionDistortion = 0.1f,
        ReflectionColor = new Vector3F(0.2f),
        RefractionColor = new Vector3F(0.6f),

        // Water is scattered in high waves and this makes the wave crests brighter.
        // ScatterColor defines the intensity of this effect.
        ScatterColor = new Vector3F(0.05f, 0.1f, 0.1f),

        // Foam is automatically rendered where the water intersects geometry and
        // where wave are high.
        FoamMap = ContentManager.Load<Texture2D>("Water/Foam"),
        FoamMapScale = 5,
        FoamColor = new Vector3F(1),
        FoamCrestMin = 0.3f,
        FoamCrestMax = 0.8f,

        // Approximate underwater caustics are computed in real-time from the waves.
        CausticsSampleCount = 3,
        CausticsIntensity = 3,
        CausticsPower = 100,
      };

      // If we do not specify a shape in the WaterNode constructor, we get an infinite
      // water plane.
      _waterNode = new WaterNode(waterOcean, null)
      {
        PoseWorld = new Pose(new Vector3F(0, 0.5f, 0)),
        SkyboxReflection = _graphicsScreen.Scene.GetDescendants().OfType<SkyboxNode>().First(),

        // ExtraHeight must be set to a value greater than the max. wave height. 
        ExtraHeight = 2,
      };
      _graphicsScreen.Scene.Children.Add(_waterNode);

      // OceanWaves can be set to displace water surface using a displacement map.
      // The displacement map is computed by the WaterWaveRenderer (see DeferredGraphicsScreen)
      // using FFT and a statistical ocean model.
      _waterNode.Waves = new OceanWaves
      {
        TextureSize = 256,
        HeightScale = 0.004f,
        Wind = new Vector3F(10, 0, 10),
        Directionality = 1,
        Choppiness = 1,
        TileSize = 20,

        // If we enable CPU queries, we can call OceanWaves.GetDisplacement()
        // (see Update() method below).
        EnableCpuQueries = true,
      };

      // Optional: Use a planar reflection instead of the skybox reflection.
      // We add a PlanarReflectionNode as a child of the WaterNode.
      var renderToTexture = new RenderToTexture
      {
        Texture = new RenderTarget2D(GraphicsService.GraphicsDevice, 512, 512, false, SurfaceFormat.HdrBlendable, DepthFormat.None),
      };
      var planarReflectionNode = new PlanarReflectionNode(renderToTexture)
      {
        Shape = _waterNode.Shape,
        NormalLocal = new Vector3F(0, 1, 0),
        IsEnabled = false,
      };
      _waterNode.PlanarReflection = planarReflectionNode;
      _waterNode.Children = new SceneNodeCollection(1) { planarReflectionNode };

      // To let rigid bodies swim, we add a Buoyancy force effect. This force effect
      // computes buoyancy of a flat water surface.
      Simulation.ForceEffects.Add(new Buoyancy
      {
        Surface = new Plane(new Vector3F(0, 1, 0), _waterNode.PoseWorld.Position.Y),
        Density = 1500,
        AngularDrag = 0.3f,
        LinearDrag = 3,
      });
    }
Ejemplo n.º 8
0
    protected override void OnLoad()
    {
      var scene = (Scene)_services.GetInstance<IScene>();
      var content = _services.GetInstance<ContentManager>();

      // Define the appearance of the water.
      var waterOcean = new Water
      {
        SpecularColor = new Vector3F(20f),
        SpecularPower = 500,

        NormalMap0 = null,
        NormalMap1 = null,

        RefractionDistortion = 0.1f,
        ReflectionColor = new Vector3F(0.2f),
        RefractionColor = new Vector3F(0.6f),

        //UnderwaterFogDensity = new Vector3F(1, 0.8f, 0.6f),
        //WaterColor = new Vector3F(0.2f, 0.4f, 0.5f),
        UnderwaterFogDensity = new Vector3F(12, 8, 8) * 0.02f,
        WaterColor = new Vector3F(60, 30, 19) * 0.002f,

        // Water is scattered in high waves and this makes the wave crests brighter.
        // ScatterColor defines the intensity of this effect.
        ScatterColor = new Vector3F(0.05f, 0.1f, 0.1f),

        // Foam is automatically rendered where the water intersects geometry and
        // where wave are high.
        FoamMap = content.Load<Texture2D>("Water/Foam"),
        FoamMapScale = 5,
        FoamColor = new Vector3F(1),
        FoamCrestMin = 0.3f,
        FoamCrestMax = 0.8f,

        // Approximate underwater caustics are computed in real-time from the waves.
        CausticsSampleCount = 0,
        CausticsIntensity = 3,
        CausticsPower = 100,
      };

      // If we do not specify a shape in the WaterNode constructor, we get an infinite
      // water plane.
      _waterNode = new WaterNode(waterOcean, null)
      {
        PoseWorld = new Pose(new Vector3F(0, -100, 0)),
        SkyboxReflection = scene.GetDescendants().OfType<SkyboxNode>().First(),

        // ExtraHeight must be set to a value greater than the max. wave height. 
        ExtraHeight = 2,
      };
      scene.Children.Add(_waterNode);

      // OceanWaves can be set to displace water surface using a displacement map.
      // The displacement map is computed by the WaterWaveRenderer (see DeferredGraphicsScreen)
      // using FFT and a statistical ocean model.
      _waterNode.Waves = new OceanWaves
      {
        TextureSize = 256,
        HeightScale = 0.008f,
        Wind = new Vector3F(10, 0, 10),
        Directionality = 1,
        Choppiness = 1,
        TileSize = 20,
        EnableCpuQueries = false,
      };

      CreateGuiControls();
    }
Ejemplo n.º 9
0
 // OnUnload() is called when the GameObject is removed from the IGameObjectService.
 protected override void OnUnload()
 {
   // Remove model and rigid body.
   _waterNode.Parent.Children.Remove(_waterNode);
   _waterNode.Dispose(false);
   _waterNode = null;
 }