Пример #1
0
        /// <overloads>
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainRoadLayer"/> class.
        /// </summary>
        /// </overloads>
        ///
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainRoadLayer"/> class with the default
        /// material.
        /// </summary>
        /// <param name="graphicService">The graphic service.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graphicService"/> is <see langword="null"/>.
        /// </exception>
        public TerrainRoadLayer(IGraphicsService graphicService)
        {
            if (graphicService == null)
            {
                throw new ArgumentNullException("graphicService");
            }

            var effect = graphicService.Content.Load <Effect>("DigitalRune/Terrain/TerrainRoadLayer");

            Material = new Material
            {
                { "Detail", new EffectBinding(graphicService, effect, null, EffectParameterHint.Material) }
            };

            FadeOutStart       = int.MaxValue;
            FadeOutEnd         = int.MaxValue;
            TileSize           = 1;
            DiffuseColor       = new Vector3(1, 1, 1);
            SpecularColor      = new Vector3(1, 1, 1);
            SpecularPower      = 10;
            Alpha              = 1;
            DiffuseTexture     = graphicService.GetDefaultTexture2DWhite();
            SpecularTexture    = graphicService.GetDefaultTexture2DBlack();
            NormalTexture      = graphicService.GetDefaultNormalTexture();
            HeightTextureScale = 1;
            HeightTexture      = graphicService.GetDefaultTexture2DBlack();
            RoadLength         = 1;
        }
Пример #2
0
        /// <overloads>
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainDecalLayer"/> class.
        /// </summary>
        /// </overloads>
        ///
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainDecalLayer"/> class with the default
        /// material.
        /// </summary>
        /// <param name="graphicService">The graphic service.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graphicService"/> is <see langword="null"/>.
        /// </exception>
        public TerrainDecalLayer(IGraphicsService graphicService)
        {
            if (graphicService == null)
            {
                throw new ArgumentNullException("graphicService");
            }

            // Use a down orientation per default.
            Pose = new Pose(Matrix.CreateRotationX(-ConstantsF.PiOver2));

            var effect = graphicService.Content.Load <Effect>("DigitalRune/Terrain/TerrainDecalLayer");

            Material = new Material
            {
                { "Detail", new EffectBinding(graphicService, effect, null, EffectParameterHint.Material) }
            };

            FadeOutStart       = int.MaxValue;
            FadeOutEnd         = int.MaxValue;
            Width              = 1;
            Height             = 1;
            DiffuseColor       = new Vector3(1, 1, 1);
            SpecularColor      = new Vector3(1, 1, 1);
            SpecularPower      = 10;
            Alpha              = 1;
            DiffuseTexture     = graphicService.GetDefaultTexture2DWhite();
            SpecularTexture    = graphicService.GetDefaultTexture2DBlack();
            NormalTexture      = graphicService.GetDefaultNormalTexture();
            HeightTextureScale = 1;
            HeightTexture      = graphicService.GetDefaultTexture2DBlack();

            UpdateAabb();
        }
Пример #3
0
        public void DefaultTextures()
        {
            Assert.AreEqual(_graphicsService0.GetDefaultTexture2DBlack(), _graphicsService0.GetDefaultTexture2DBlack());
            Assert.AreNotEqual(_graphicsService0.GetDefaultTexture2DBlack(), _graphicsService1.GetDefaultTexture2DBlack());

            var t = _graphicsService1.GetDefaultTexture2DWhite();

            _graphicsDevice1.Dispose();

            // Note: Since the graphics device is also disposed and re-created when the game is
            // moved between screens - we must not auto-dispose our textures.
            //Assert.IsTrue(t.IsDisposed);
        }
        /// <overloads>
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainMaterialLayer"/> class.
        /// </summary>
        /// </overloads>
        ///
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainMaterialLayer"/> class with the default
        /// material.
        /// </summary>
        /// <param name="graphicService">The graphic service.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graphicService"/> is <see langword="null"/>.
        /// </exception>
        public TerrainMaterialLayer(IGraphicsService graphicService)
        {
            if (graphicService == null)
            {
                throw new ArgumentNullException("graphicService");
            }

            var effect = graphicService.Content.Load <Effect>("DigitalRune/Terrain/TerrainMaterialLayer");

            Material = new Material
            {
                { "Detail", new EffectBinding(graphicService, effect, null, EffectParameterHint.Material) }
            };

            FadeOutStart            = int.MaxValue;
            FadeOutEnd              = int.MaxValue;
            TileSize                = 1;
            DiffuseColor            = new Vector3(1, 1, 1);
            SpecularColor           = new Vector3(1, 1, 1);
            SpecularPower           = 10;
            Alpha                   = 1;
            DiffuseTexture          = graphicService.GetDefaultTexture2DWhite();
            SpecularTexture         = graphicService.GetDefaultTexture2DBlack();
            NormalTexture           = graphicService.GetDefaultNormalTexture();
            HeightTextureScale      = 1;
            HeightTextureBias       = 0;
            HeightTexture           = graphicService.GetDefaultTexture2DBlack();
            TriplanarTightening     = -1;
            TintStrength            = 1;
            TintTexture             = graphicService.GetDefaultTexture2DWhite();
            BlendThreshold          = 0.5f;
            BlendRange              = 1f;
            BlendHeightInfluence    = 0;
            BlendNoiseInfluence     = 0;
            BlendTextureChannel     = 0;
            BlendTexture            = graphicService.GetDefaultTexture2DWhite();
            NoiseTileSize           = 1;
            TerrainHeightMin        = -1e20f;
            TerrainHeightMax        = +1e20f;
            TerrainHeightBlendRange = 1f;
            TerrainSlopeMin         = -ConstantsF.Pi;
            TerrainSlopeMax         = ConstantsF.Pi;
            TerrainSlopeBlendRange  = MathHelper.ToRadians(10);
        }
Пример #5
0
        //--------------------------------------------------------------
        #region Methods
        //--------------------------------------------------------------

        /// <summary>
        /// Computes the intersection of <see cref="MeshNode"/>s.
        /// </summary>
        /// <param name="meshNodePairs">
        /// A collection of <see cref="MeshNode"/> pairs.The renderer computes the intersection volume
        /// of each pair.
        /// </param>
        /// <param name="color">The diffuse color used for the intersection.</param>
        /// <param name="alpha">The opacity of the intersection.</param>
        /// <param name="maxConvexity">
        /// The maximum convexity of the submeshes. A convex mesh has a convexity of 1. A concave mesh
        /// has a convexity greater than 1. Convexity is the number of layers required for depth peeling
        /// (= the number of front face layers when looking at the object).
        /// </param>
        /// <param name="context">The render context.</param>
        /// <remarks>
        /// <para>
        /// This method renders an off-screen image (color and depth) of the intersection volume. This
        /// operation destroys the currently set render target and depth/stencil buffer.
        /// </para>
        /// </remarks>
        /// <exception cref="ObjectDisposedException">
        /// The <see cref="IntersectionRenderer"/> has already been disposed.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="meshNodePairs"/> or <see cref="context"/> is
        /// <see langword="null"/>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// The convexity must be greater than 0.
        /// </exception>
        /// <exception cref="GraphicsException">
        /// Invalid render context: Graphics service is not set.
        /// </exception>
        /// <exception cref="GraphicsException">
        /// Invalid render context: Wrong graphics device.
        /// </exception>
        /// <exception cref="GraphicsException">
        /// Invalid render context: Scene is not set.
        /// </exception>
        /// <exception cref="GraphicsException">
        /// Invalid render context: Camera node needs to be set in render context.
        /// </exception>
        public void ComputeIntersection(IEnumerable <Pair <MeshNode> > meshNodePairs,
                                        Vector3F color, float alpha, float maxConvexity, RenderContext context)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("IntersectionRenderer has already been disposed.");
            }
            if (meshNodePairs == null)
            {
                throw new ArgumentNullException("meshNodePairs");
            }
            if (maxConvexity < 1)
            {
                throw new ArgumentOutOfRangeException("maxConvexity", "The max convexity must be greater than 0.");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (context.GraphicsService == null)
            {
                throw new GraphicsException("Invalid render context: Graphics service is not set.");
            }
            if (_graphicsService != context.GraphicsService)
            {
                throw new GraphicsException("Invalid render context: Wrong graphics service.");
            }
            if (context.CameraNode == null)
            {
                throw new GraphicsException("Camera node needs to be set in render context.");
            }
            if (context.Scene == null)
            {
                throw new GraphicsException("A scene needs to be set in the render context.");
            }

            // Create 2 ordered pairs for each unordered pair.
            _pairs.Clear();
            foreach (var pair in meshNodePairs)
            {
                if (pair.First == null || pair.Second == null)
                {
                    continue;
                }

                // Frustum culling.
                if (!context.Scene.HaveContact(pair.First, context.CameraNode))
                {
                    continue;
                }
                if (!context.Scene.HaveContact(pair.Second, context.CameraNode))
                {
                    continue;
                }

                _pairs.Add(new Pair <MeshNode, MeshNode>(pair.First, pair.Second));
                _pairs.Add(new Pair <MeshNode, MeshNode>(pair.Second, pair.First));
            }

            var renderTargetPool = _graphicsService.RenderTargetPool;

            if (_pairs.Count == 0)
            {
                renderTargetPool.Recycle(_intersectionImage);
                _intersectionImage = null;
                return;
            }

            // Color and alpha are applied in RenderIntersection().
            _color = color;
            _alpha = alpha;

            var graphicsDevice = _graphicsService.GraphicsDevice;

            // Save original render states.
            var originalBlendState        = graphicsDevice.BlendState;
            var originalDepthStencilState = graphicsDevice.DepthStencilState;
            var originalRasterizerState   = graphicsDevice.RasterizerState;
            var originalScissorRectangle  = graphicsDevice.ScissorRectangle;

            // Get offscreen render targets.
            var viewport = context.Viewport;

            viewport.X      = 0;
            viewport.Y      = 0;
            viewport.Width  = (int)(viewport.Width / DownsampleFactor);
            viewport.Height = (int)(viewport.Height / DownsampleFactor);
            var renderTargetFormat = new RenderTargetFormat(viewport.Width, viewport.Height, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8);

            // Try to reuse any existing render targets.
            // (Usually they are recycled in RenderIntersection()).
            var currentScene = _intersectionImage;

            if (currentScene == null || !renderTargetFormat.IsCompatibleWith(currentScene))
            {
                currentScene.SafeDispose();
                currentScene = renderTargetPool.Obtain2D(renderTargetFormat);
            }
            var lastScene = renderTargetPool.Obtain2D(renderTargetFormat);

            // Set shared effect parameters.
            var cameraNode = context.CameraNode;
            var view       = (Matrix)cameraNode.View;
            var projection = cameraNode.Camera.Projection;
            var near       = projection.Near;
            var far        = projection.Far;

            _parameterViewportSize.SetValue(new Vector2(viewport.Width, viewport.Height));

            // The DepthEpsilon has to be tuned if depth peeling does not work because
            // of numerical problems equality z comparisons.
            _parameterCameraParameters.SetValue(new Vector3(near, far - near, 0.0000001f));
            _parameterView.SetValue(view);
            _parameterProjection.SetValue((Matrix)projection);

            var defaultTexture = _graphicsService.GetDefaultTexture2DBlack();

            // Handle all pairs.
            bool isFirstPass = true;

            while (true)
            {
                // Find a mesh node A and all mesh nodes to which it needs to be clipped.
                MeshNode meshNodeA = null;
                _partners.Clear();
                for (int i = 0; i < _pairs.Count; i++)
                {
                    var pair = _pairs[i];

                    if (pair.First == null)
                    {
                        continue;
                    }

                    if (meshNodeA == null)
                    {
                        meshNodeA = pair.First;
                    }

                    if (pair.First == meshNodeA)
                    {
                        _partners.Add(pair.Second);

                        //  Remove this pair.
                        _pairs[i] = new Pair <MeshNode, MeshNode>();
                    }
                }

                // Abort if we have handled all pairs.
                if (meshNodeA == null)
                {
                    break;
                }

                var worldTransformA = (Matrix)(meshNodeA.PoseWorld * Matrix44F.CreateScale(meshNodeA.ScaleWorld));

                if (EnableScissorTest)
                {
                    // Scissor rectangle of A.
                    var scissorA = GraphicsHelper.GetScissorRectangle(context.CameraNode, viewport, meshNodeA);

                    // Union of scissor rectangles of partners.
                    Rectangle partnerRectangle = GraphicsHelper.GetScissorRectangle(context.CameraNode, viewport, _partners[0]);
                    for (int i = 1; i < _partners.Count; i++)
                    {
                        var a = GraphicsHelper.GetScissorRectangle(context.CameraNode, viewport, _partners[i]);
                        partnerRectangle = Rectangle.Union(partnerRectangle, a);
                    }

                    // Use intersection of A and partners.
                    graphicsDevice.ScissorRectangle = Rectangle.Intersect(scissorA, partnerRectangle);

                    // We store the union of all scissor rectangles for use in RenderIntersection().
                    if (isFirstPass)
                    {
                        _totalScissorRectangle = graphicsDevice.ScissorRectangle;
                    }
                    else
                    {
                        _totalScissorRectangle = Rectangle.Union(_totalScissorRectangle, graphicsDevice.ScissorRectangle);
                    }
                }

                // Depth peeling of A.
                for (int layer = 0; layer < maxConvexity; layer++)
                {
                    // Set and clear render target.
                    graphicsDevice.SetRenderTarget(currentScene);
                    graphicsDevice.Clear(new Color(1, 1, 1, 0)); // RGB = "a large depth", A = "empty area"

                    // Render a depth layer of A.
                    graphicsDevice.DepthStencilState = DepthStencilStateWriteLess;
                    graphicsDevice.BlendState        = BlendState.Opaque;
                    graphicsDevice.RasterizerState   = EnableScissorTest ? CullCounterClockwiseScissor : RasterizerState.CullCounterClockwise;
                    _parameterWorld.SetValue(worldTransformA);
                    _parameterTexture.SetValue((layer == 0) ? defaultTexture : lastScene);
                    _passPeel.Apply();
                    foreach (var submesh in meshNodeA.Mesh.Submeshes)
                    {
                        submesh.Draw();
                    }

                    // Render partners to set stencil.
                    graphicsDevice.DepthStencilState = DepthStencilStateOnePassStencilFail;
                    graphicsDevice.BlendState        = BlendStateNoWrite;
                    graphicsDevice.RasterizerState   = EnableScissorTest ? CullNoneScissor : RasterizerState.CullNone;
                    foreach (var partner in _partners)
                    {
                        _parameterWorld.SetValue((Matrix)(partner.PoseWorld * Matrix44F.CreateScale(partner.ScaleWorld)));
                        _passMark.Apply();
                        foreach (var submesh in partner.Mesh.Submeshes)
                        {
                            submesh.Draw();
                        }
                    }

                    // Clear depth buffer. Leave stencil buffer unchanged.
                    graphicsDevice.Clear(ClearOptions.DepthBuffer, new Color(0, 1, 0), 1, 0);

                    // Render A to compute lighting.
                    graphicsDevice.DepthStencilState = DepthStencilStateStencilNotEqual0;
                    graphicsDevice.BlendState        = BlendState.Opaque;
                    graphicsDevice.RasterizerState   = EnableScissorTest ? CullCounterClockwiseScissor :  RasterizerState.CullCounterClockwise;
                    _parameterWorld.SetValue(worldTransformA);
                    _passDraw.Apply();
                    foreach (var submesh in meshNodeA.Mesh.Submeshes)
                    {
                        submesh.Draw();
                    }

                    // Combine last intersection image with current.
                    if (!isFirstPass)
                    {
                        graphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
                        graphicsDevice.BlendState        = BlendState.Opaque;
                        graphicsDevice.RasterizerState   = EnableScissorTest ? CullNoneScissor : RasterizerState.CullNone;
                        _parameterTexture.SetValue(lastScene);
                        _passCombine.Apply();
                        graphicsDevice.DrawFullScreenQuad();
                    }

                    isFirstPass = false;

                    // ----- Swap render targets.
                    MathHelper.Swap(ref lastScene, ref currentScene);
                }
            }

            // Store final images for RenderIntersection.
            _intersectionImage = lastScene;

            // Scale scissor rectangle back to full-screen resolution.
            if (DownsampleFactor > 1)
            {
                _totalScissorRectangle.X      = (int)(_totalScissorRectangle.X * DownsampleFactor);
                _totalScissorRectangle.Y      = (int)(_totalScissorRectangle.Y * DownsampleFactor);
                _totalScissorRectangle.Width  = (int)(_totalScissorRectangle.Width * DownsampleFactor);
                _totalScissorRectangle.Height = (int)(_totalScissorRectangle.Height * DownsampleFactor);
            }


            // Restore original render state.
            graphicsDevice.BlendState        = originalBlendState ?? BlendState.Opaque;
            graphicsDevice.DepthStencilState = originalDepthStencilState ?? DepthStencilState.Default;
            graphicsDevice.RasterizerState   = originalRasterizerState ?? RasterizerState.CullCounterClockwise;
            graphicsDevice.ScissorRectangle  = originalScissorRectangle;

            renderTargetPool.Recycle(currentScene);
            _partners.Clear();
            _pairs.Clear();
        }
Пример #6
0
        //--------------------------------------------------------------
        /// <overloads>
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainRoadLayer"/> class.
        /// </summary>
        /// </overloads>
        /// 
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainRoadLayer"/> class with the default
        /// material.
        /// </summary>
        /// <param name="graphicService">The graphic service.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graphicService"/> is <see langword="null"/>.
        /// </exception>
        public TerrainRoadLayer(IGraphicsService graphicService)
        {
            if (graphicService == null)
            throw new ArgumentNullException("graphicService");

              var effect = graphicService.Content.Load<Effect>("DigitalRune/Terrain/TerrainRoadLayer");
              Material = new Material
              {
            { "Detail", new EffectBinding(graphicService, effect, null, EffectParameterHint.Material) }
              };

              FadeOutStart = int.MaxValue;
              FadeOutEnd = int.MaxValue;
              TileSize = 1;
              DiffuseColor = new Vector3F(1, 1, 1);
              SpecularColor = new Vector3F(1, 1, 1);
              SpecularPower = 10;
              Alpha = 1;
              DiffuseTexture = graphicService.GetDefaultTexture2DWhite();
              SpecularTexture = graphicService.GetDefaultTexture2DBlack();
              NormalTexture = graphicService.GetDefaultNormalTexture();
              HeightTextureScale = 1;
              HeightTexture = graphicService.GetDefaultTexture2DBlack();
              RoadLength = 1;
        }
Пример #7
0
        //--------------------------------------------------------------
        /// <overloads>
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainMaterialLayer"/> class.
        /// </summary>
        /// </overloads>
        /// 
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainMaterialLayer"/> class with the default
        /// material.
        /// </summary>
        /// <param name="graphicService">The graphic service.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graphicService"/> is <see langword="null"/>.
        /// </exception>
        public TerrainMaterialLayer(IGraphicsService graphicService)
        {
            if (graphicService == null)
            throw new ArgumentNullException("graphicService");

              var effect = graphicService.Content.Load<Effect>("DigitalRune/Terrain/TerrainMaterialLayer");
              Material = new Material
              {
            { "Detail", new EffectBinding(graphicService, effect, null, EffectParameterHint.Material) }
              };

              FadeOutStart = int.MaxValue;
              FadeOutEnd = int.MaxValue;
              TileSize = 1;
              DiffuseColor = new Vector3F(1, 1, 1);
              SpecularColor = new Vector3F(1, 1, 1);
              SpecularPower = 10;
              Alpha = 1;
              DiffuseTexture = graphicService.GetDefaultTexture2DWhite();
              SpecularTexture = graphicService.GetDefaultTexture2DBlack();
              NormalTexture = graphicService.GetDefaultNormalTexture();
              HeightTextureScale = 1;
              HeightTextureBias = 0;
              HeightTexture = graphicService.GetDefaultTexture2DBlack();
              TriplanarTightening = -1;
              TintStrength = 1;
              TintTexture = graphicService.GetDefaultTexture2DWhite();
              BlendThreshold = 0.5f;
              BlendRange = 1f;
              BlendHeightInfluence = 0;
              BlendNoiseInfluence = 0;
              BlendTextureChannel = 0;
              BlendTexture = graphicService.GetDefaultTexture2DWhite();
              NoiseTileSize = 1;
              TerrainHeightMin = -1e20f;
              TerrainHeightMax = +1e20f;
              TerrainHeightBlendRange = 1f;
              TerrainSlopeMin = -ConstantsF.Pi;
              TerrainSlopeMax = ConstantsF.Pi;
              TerrainSlopeBlendRange = MathHelper.ToRadians(10);
        }
Пример #8
0
        //--------------------------------------------------------------
        /// <overloads>
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainDecalLayer"/> class.
        /// </summary>
        /// </overloads>
        /// 
        /// <summary>
        /// Initializes a new instance of the <see cref="TerrainDecalLayer"/> class with the default
        /// material.
        /// </summary>
        /// <param name="graphicService">The graphic service.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graphicService"/> is <see langword="null"/>.
        /// </exception>
        public TerrainDecalLayer(IGraphicsService graphicService)
        {
            if (graphicService == null)
            throw new ArgumentNullException("graphicService");

              // Use a down orientation per default.
              Pose = new Pose(Matrix33F.CreateRotationX(-ConstantsF.PiOver2));

              var effect = graphicService.Content.Load<Effect>("DigitalRune/Terrain/TerrainDecalLayer");
              Material = new Material
              {
            { "Detail", new EffectBinding(graphicService, effect, null, EffectParameterHint.Material) }
              };

              FadeOutStart = int.MaxValue;
              FadeOutEnd = int.MaxValue;
              Width = 1;
              Height = 1;
              DiffuseColor = new Vector3F(1, 1, 1);
              SpecularColor = new Vector3F(1, 1, 1);
              SpecularPower = 10;
              Alpha = 1;
              DiffuseTexture = graphicService.GetDefaultTexture2DWhite();
              SpecularTexture = graphicService.GetDefaultTexture2DBlack();
              NormalTexture = graphicService.GetDefaultNormalTexture();
              HeightTextureScale = 1;
              HeightTexture = graphicService.GetDefaultTexture2DBlack();

              UpdateAabb();
        }