示例#1
0
        /// <summary>
        /// Adds a new <see cref="TerrainRendererMesh"/>.
        /// </summary>
        /// <param name="mesh">The terrain mesh.</param>
        /// <remarks>
        /// <para>
        /// The <see cref="TerrainRenderer"/> takes ownership of the <see cref="TerrainRendererMesh"/>
        /// instance. When the <see cref="TerrainRenderer"/> is disposed of, all internally stored
        /// <see cref="TerrainRendererMesh"/>es are disposed of.
        /// </para>
        /// <para>
        /// If the terrain renderer already has a mesh with the same settings
        /// (<see cref="TerrainRendererMesh.NumberOfLevels"/> and
        /// <see cref="TerrainRendererMesh.CellsPerLevel"/>), the old mesh is disposed of and replaced.
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="mesh"/> is <see langword="null"/>.
        /// </exception>
        public void SetMesh(TerrainRendererMesh mesh)
        {
            if (mesh == null)
            {
                throw new ArgumentNullException("mesh");
            }
            if (mesh.IsDisposed)
            {
                throw new ArgumentException("Mesh is disposed.", "mesh");
            }

            var key = new Pair <int, int>(mesh.NumberOfLevels, mesh.CellsPerLevel);

            TerrainRendererMesh oldMesh;

            if (_meshes.TryGetValue(key, out oldMesh) && mesh != oldMesh)
            {
                oldMesh.Dispose();
            }

            _meshes[key] = mesh;
        }
示例#2
0
        public override void Render(IList <SceneNode> nodes, RenderContext context, RenderOrder order)
        {
            ThrowIfDisposed();

            if (nodes == null)
            {
                throw new ArgumentNullException("nodes");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            int numberOfNodes = nodes.Count;

            if (numberOfNodes == 0)
            {
                return;
            }

            context.ThrowIfCameraMissing();
            context.ThrowIfRenderPassMissing();

            var graphicsService = context.GraphicsService;
            var graphicsDevice  = graphicsService.GraphicsDevice;

            var cameraNode = context.CameraNode;

            // Update SceneNode.LastFrame for all visible nodes.
            int frame = context.Frame;

            cameraNode.LastFrame = frame;

            var savedRenderState = new RenderStateSnapshot(graphicsDevice);

            for (int i = 0; i < numberOfNodes; i++)
            {
                var node = nodes[i] as TerrainNode;
                if (node == null)
                {
                    continue;
                }

                // Node is visible in current frame.
                node.LastFrame = frame;

                if (!node.MaterialInstance.Contains(context.RenderPass))
                {
                    continue;
                }

                TerrainRendererMesh mesh;
                var  meshKey    = new Pair <int, int>(node.BaseClipmap.NumberOfLevels, node.BaseClipmap.CellsPerLevel);
                bool meshExists = _meshes.TryGetValue(meshKey, out mesh);
                if (!meshExists || mesh.IsDisposed)
                {
                    // Warning: This may take a few seconds!
                    mesh             = new TerrainRendererMesh(graphicsDevice, node.BaseClipmap.NumberOfLevels, node.BaseClipmap.CellsPerLevel);
                    _meshes[meshKey] = mesh;
                }

                // Get the EffectBindings and the Effect for the current render pass.
                EffectBinding materialInstanceBinding = node.MaterialInstance[context.RenderPass];
                EffectBinding materialBinding         = node.Material[context.RenderPass];
                Effect        effect = materialBinding.Effect;

                // Add this info to the render context. This info will be needed by parameter bindings.
                context.SceneNode = node;
                context.MaterialInstanceBinding = materialInstanceBinding;
                context.MaterialBinding         = materialBinding;

                // Update and apply global effect parameter bindings - these bindings set the
                // effect parameter values for "global" parameters. For example, if an effect uses
                // a "ViewProjection" parameter, then a binding will compute this matrix from the
                // current CameraInstance in the render context and update the effect parameter.
                foreach (var binding in effect.GetParameterBindings())
                {
                    if (binding.Description.Hint == EffectParameterHint.Global)
                    {
                        binding.Update(context);
                        binding.Apply(context);
                    }
                }

                // Update and apply material bindings - these are usually constant parameter values,
                // like textures or colors, that are defined in the fbx file or material description
                // (XML files).
                //SetHoleParameter(materialBinding, context);
                foreach (var binding in materialBinding.ParameterBindings)
                {
                    binding.Update(context);
                    binding.Apply(context);
                }

                // Update and apply local, per-instance, and per-pass bindings - these are bindings
                // for parameters, like the "World" matrix or lighting parameters.
                foreach (var binding in materialInstanceBinding.ParameterBindings)
                {
                    if (binding.Description.Hint != EffectParameterHint.PerPass)
                    {
                        binding.Update(context);
                        binding.Apply(context);
                    }
                }

                // Select and apply technique.
                var techniqueBinding = materialInstanceBinding.TechniqueBinding;
                techniqueBinding.Update(context);
                var technique = techniqueBinding.GetTechnique(effect, context);
                effect.CurrentTechnique = technique;

                var passBinding = techniqueBinding.GetPassBinding(technique, context);
                foreach (var pass in passBinding)
                {
                    // Update and apply per-pass bindings.
                    foreach (var binding in materialInstanceBinding.ParameterBindings)
                    {
                        if (binding.Description.Hint == EffectParameterHint.PerPass)
                        {
                            binding.Update(context);
                            binding.Apply(context);
                        }
                    }

                    pass.Apply();

                    // The WireFrame pass is only rendered if DrawWireFrame is set.
                    if ((!string.Equals(pass.Name, "WireFrame", StringComparison.OrdinalIgnoreCase) || DrawWireFrame) &&
                        !string.Equals(pass.Name, "Restore", StringComparison.OrdinalIgnoreCase))
                    {
                        mesh.Submesh.Draw();
                    }
                }

                // Reset texture effect parameter:
                // This seems to be necessary because the vertex textures are not automatically
                // removed from the texture stage which causes exceptions later.
                ResetParameter(effect, "TerrainBaseClipmap0");
                ResetParameter(effect, "TerrainBaseClipmap1");
                ResetParameter(effect, "TerrainBaseClipmap2");
                ResetParameter(effect, "TerrainBaseClipmap3");
                foreach (var pass in passBinding)
                {
                    pass.Apply();
                    break;
                }
            }

            context.SceneNode               = null;
            context.MaterialBinding         = null;
            context.MaterialInstanceBinding = null;

            savedRenderState.Restore();
        }
示例#3
0
        /// <summary>
        /// Adds a new <see cref="TerrainRendererMesh"/>.
        /// </summary>
        /// <param name="mesh">The terrain mesh.</param>
        /// <remarks>
        /// <para>
        /// The <see cref="TerrainRenderer"/> takes ownership of the <see cref="TerrainRendererMesh"/>
        /// instance. When the <see cref="TerrainRenderer"/> is disposed of, all internally stored
        /// <see cref="TerrainRendererMesh"/>es are disposed of.
        /// </para>
        /// <para>
        /// If the terrain renderer already has a mesh with the same settings
        /// (<see cref="TerrainRendererMesh.NumberOfLevels"/> and
        /// <see cref="TerrainRendererMesh.CellsPerLevel"/>), the old mesh is disposed of and replaced.
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="mesh"/> is <see langword="null"/>.
        /// </exception>
        public void SetMesh(TerrainRendererMesh mesh)
        {
            if (mesh == null)
            throw new ArgumentNullException("mesh");
              if (mesh.IsDisposed)
            throw new ArgumentException("Mesh is disposed.", "mesh");

              var key = new Pair<int, int>(mesh.NumberOfLevels, mesh.CellsPerLevel);

              TerrainRendererMesh oldMesh;
              if (_meshes.TryGetValue(key, out oldMesh) && mesh != oldMesh)
            oldMesh.Dispose();

              _meshes[key] = mesh;
        }
示例#4
0
        public override void Render(IList<SceneNode> nodes, RenderContext context, RenderOrder order)
        {
            ThrowIfDisposed();

              if (nodes == null)
            throw new ArgumentNullException("nodes");
              if (context == null)
            throw new ArgumentNullException("context");

              int numberOfNodes = nodes.Count;
              if (numberOfNodes == 0)
            return;

              context.ThrowIfCameraMissing();
              context.ThrowIfRenderPassMissing();

              var graphicsService = context.GraphicsService;
              var graphicsDevice = graphicsService.GraphicsDevice;

              var cameraNode = context.CameraNode;

              // Update SceneNode.LastFrame for all visible nodes.
              int frame = context.Frame;
              cameraNode.LastFrame = frame;

              var savedRenderState = new RenderStateSnapshot(graphicsDevice);

              for (int i = 0; i < numberOfNodes; i++)
              {
            var node = nodes[i] as TerrainNode;
            if (node == null)
              continue;

            // Node is visible in current frame.
            node.LastFrame = frame;

            if (!node.MaterialInstance.Contains(context.RenderPass))
              continue;

            TerrainRendererMesh mesh;
            var meshKey = new Pair<int, int>(node.BaseClipmap.NumberOfLevels, node.BaseClipmap.CellsPerLevel);
            bool meshExists = _meshes.TryGetValue(meshKey, out mesh);
            if (!meshExists || mesh.IsDisposed)
            {
              // Warning: This may take a few seconds!
              mesh = new TerrainRendererMesh(graphicsDevice, node.BaseClipmap.NumberOfLevels, node.BaseClipmap.CellsPerLevel);
              _meshes[meshKey] = mesh;
            }

            // Get the EffectBindings and the Effect for the current render pass.
            EffectBinding materialInstanceBinding = node.MaterialInstance[context.RenderPass];
            EffectBinding materialBinding = node.Material[context.RenderPass];
            Effect effect = materialBinding.Effect;

            // Add this info to the render context. This info will be needed by parameter bindings.
            context.SceneNode = node;
            context.MaterialInstanceBinding = materialInstanceBinding;
            context.MaterialBinding = materialBinding;

            // Update and apply global effect parameter bindings - these bindings set the
            // effect parameter values for "global" parameters. For example, if an effect uses
            // a "ViewProjection" parameter, then a binding will compute this matrix from the
            // current CameraInstance in the render context and update the effect parameter.
            foreach (var binding in effect.GetParameterBindings())
            {
              if (binding.Description.Hint == EffectParameterHint.Global)
              {
            binding.Update(context);
            binding.Apply(context);
              }
            }

            // Update and apply material bindings - these are usually constant parameter values,
            // like textures or colors, that are defined in the fbx file or material description
            // (XML files).
            //SetHoleParameter(materialBinding, context);
            foreach (var binding in materialBinding.ParameterBindings)
            {
              binding.Update(context);
              binding.Apply(context);
            }

            // Update and apply local, per-instance, and per-pass bindings - these are bindings
            // for parameters, like the "World" matrix or lighting parameters.
            foreach (var binding in materialInstanceBinding.ParameterBindings)
            {
              if (binding.Description.Hint != EffectParameterHint.PerPass)
              {
            binding.Update(context);
            binding.Apply(context);
              }
            }

            // Select and apply technique.
            var techniqueBinding = materialInstanceBinding.TechniqueBinding;
            techniqueBinding.Update(context);
            var technique = techniqueBinding.GetTechnique(effect, context);
            effect.CurrentTechnique = technique;

            var passBinding = techniqueBinding.GetPassBinding(technique, context);
            foreach (var pass in passBinding)
            {
              // Update and apply per-pass bindings.
              foreach (var binding in materialInstanceBinding.ParameterBindings)
              {
            if (binding.Description.Hint == EffectParameterHint.PerPass)
            {
              binding.Update(context);
              binding.Apply(context);
            }
              }

              pass.Apply();

              // The WireFrame pass is only rendered if DrawWireFrame is set.
              if ((!string.Equals(pass.Name, "WireFrame", StringComparison.OrdinalIgnoreCase) || DrawWireFrame)
              && !string.Equals(pass.Name, "Restore", StringComparison.OrdinalIgnoreCase))
              {
            mesh.Submesh.Draw();
              }
            }

            // Reset texture effect parameter:
            // This seems to be necessary because the vertex textures are not automatically
            // removed from the texture stage which causes exceptions later.
            ResetParameter(effect, "TerrainBaseClipmap0");
            ResetParameter(effect, "TerrainBaseClipmap1");
            ResetParameter(effect, "TerrainBaseClipmap2");
            ResetParameter(effect, "TerrainBaseClipmap3");
            foreach (var pass in passBinding)
            {
              pass.Apply();
              break;
            }
              }

              context.SceneNode = null;
              context.MaterialBinding = null;
              context.MaterialInstanceBinding = null;

              savedRenderState.Restore();
        }