Exemplo n.º 1
0
        protected virtual void Dispose(bool disposing)
        {
            if (!IsDisposed)
            {
                if (disposing)
                {
                    // Dispose managed resources.
                    SpriteBatch.Dispose();
                    MeshRenderer.Dispose();
                    _decalRenderer.Dispose();
                    AlphaBlendSceneRenderer.Dispose();
                    _cloudMapRenderer.Dispose();
                    _waterWavesRenderer.Dispose();
                    _sceneCaptureRenderer.Dispose();
                    _planarReflectionRenderer.Dispose();
                    _shadowMapRenderer.Dispose();
                    _shadowMaskRenderer.Dispose();
                    LightBufferRenderer.Dispose();
                    _lensFlareRenderer.Dispose();
                    _skyRenderer.Dispose();
                    _fogRenderer.Dispose();
                    _internalDebugRenderer.Dispose();
                    Scene.Dispose(false);
                    PostProcessors.Dispose();
                    DebugRenderer.Dispose();
                }

                // Release unmanaged resources.

                IsDisposed = true;
            }
        }
Exemplo n.º 2
0
 public void Dispose()
 {
     _spriteBatch.Dispose();
     _meshRenderer.Dispose();
     _decalRenderer.Dispose();
     _billboardRenderer.Dispose();
     AlphaBlendSceneRenderer.Dispose();
     _shadowMapRenderer.Dispose();
     _shadowMaskRenderer.Dispose();
     LightBufferRenderer.Dispose();
     _lensFlareRenderer.Dispose();
     _skyRenderer.Dispose();
     _fogRenderer.Dispose();
     _internalDebugRenderer.Dispose();
     Scene.Dispose(false);
     PostProcessors.Dispose();
     DebugRenderer.Dispose();
 }
        protected internal void RenderScene(CustomSceneQuery sceneQuery, RenderContext context,
                                            bool doPostProcessing, bool renderLensFlares, bool renderDebugOutput, bool renderReticle)
        {
            var renderTargetPool      = GraphicsService.RenderTargetPool;
            var graphicsDevice        = GraphicsService.GraphicsDevice;
            var originalRenderTarget  = context.RenderTarget;
            var originalViewport      = context.Viewport;
            var originalSourceTexture = context.SourceTexture;

            // All intermediate render targets have the size of the target viewport.
            int width  = context.Viewport.Width;
            int height = context.Viewport.Height;

            context.Viewport = new Viewport(0, 0, width, height);

            // The render context can be used to share any data, for example:
            // Store a shared RebuildZBufferRenderer in the context.
            context.Data[RenderContextKeys.RebuildZBufferRenderer] = _rebuildZBufferRenderer;

            // ----- G-Buffer Pass
            // The GBufferRenderer creates context.GBuffer0 and context.GBuffer1.
            _gBufferRenderer.Render(sceneQuery.RenderableNodes, sceneQuery.DecalNodes, context);

            // ----- Shadow Pass
            // The ShadowMapRenderer renders the shadow maps which are stored in the light nodes.
            context.RenderPass = "******";
            ShadowMapRenderer.Render(sceneQuery.Lights, context);
            context.RenderPass = null;

            // The ShadowMaskRenderer renders the shadows and stores them in one or more render
            // targets ("shadows masks").
            ShadowMaskRenderer.Render(sceneQuery.Lights, context);

            RecycleShadowMaps(sceneQuery.Lights);

            // ----- Light Buffer Pass
            // The LightBufferRenderer creates context.LightBuffer0 (diffuse light) and
            // context.LightBuffer1 (specular light).
            LightBufferRenderer.Render(sceneQuery.Lights, context);

            // Normally, we do not need the shadow masks anymore - except if we want to
            // display them for debugging.
            if (!VisualizeIntermediateRenderTargets)
            {
                ShadowMaskRenderer.RecycleShadowMasks();
            }

            // ----- Material Pass
            if (DebugMode == DeferredGraphicsDebugMode.None)
            {
                // In the material pass we render all meshes and decals into a single full-screen
                // render target. The shaders combine the material properties (diffuse texture, etc.)
                // with the light buffer info.
                context.RenderTarget =
                    renderTargetPool.Obtain2D(new RenderTargetFormat(width, height, false, SurfaceFormat.HdrBlendable,
                                                                     DepthFormat.Depth24Stencil8));
                graphicsDevice.SetRenderTarget(context.RenderTarget);
                context.Viewport = graphicsDevice.Viewport;
                graphicsDevice.Clear(new Color(3, 3, 3, 255));
                graphicsDevice.DepthStencilState = DepthStencilState.Default;
                graphicsDevice.RasterizerState   = RasterizerState.CullCounterClockwise;
                graphicsDevice.BlendState        = BlendState.Opaque;
                context.RenderPass = "******";
                _opaqueMeshSceneRenderer.Render(sceneQuery.RenderableNodes, context);
                _decalRenderer.Render(sceneQuery.DecalNodes, context);
                context.RenderPass = null;
            }
            else
            {
                // For debugging:
                // Ignore the material pass. Keep rendering into one of the light buffers
                // to visualize only the lighting results.
                if (DebugMode == DeferredGraphicsDebugMode.VisualizeDiffuseLightBuffer)
                {
                    context.RenderTarget = context.LightBuffer0;
                }
                else
                {
                    context.RenderTarget = context.LightBuffer1;
                }
            }

            // The meshes rendered in the last step might use additional floating-point
            // textures (e.g. the light buffers) in the different graphics texture stages.
            // We reset the texture stages (setting all GraphicsDevice.Textures to null),
            // otherwise XNA might throw exceptions.
            graphicsDevice.ResetTextures();

            // ----- Occlusion Queries
            if (renderLensFlares)
            {
                _lensFlareRenderer.UpdateOcclusion(sceneQuery.LensFlareNodes, context);
            }

            // ----- Sky
            _skyRenderer.Render(sceneQuery.SkyNodes, context);

            // ----- Fog
            _fogRenderer.Render(sceneQuery.FogNodes, context);

            // ----- Forward Rendering of Alpha-Blended Meshes and Particles
            graphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
            graphicsDevice.RasterizerState   = RasterizerState.CullCounterClockwise;
            graphicsDevice.BlendState        = BlendState.AlphaBlend;
            context.RenderPass = "******";
            AlphaBlendSceneRenderer.Render(sceneQuery.RenderableNodes, context, RenderOrder.BackToFront);
            context.RenderPass = null;
            graphicsDevice.ResetTextures();

            renderTargetPool.Recycle(context.SourceTexture);
            context.SourceTexture = null;

            _underwaterPostProcessor.Enabled = IsCameraUnderwater(sceneQuery, context.CameraNode);

            // ----- Post Processors
            context.SourceTexture = context.RenderTarget;
            context.RenderTarget  = originalRenderTarget;
            context.Viewport      = originalViewport;
            if (doPostProcessing)
            {
                // The post-processors modify the scene image and the result is written into
                // the final render target - which is usually the back  buffer (but this could
                // also be another off-screen render target used in another graphics screen).
                PostProcessors.Process(context);
            }
            else
            {
                // Only copy the current render target to the final render target without post-processing.
                graphicsDevice.SetRenderTarget(originalRenderTarget);
                graphicsDevice.Viewport = originalViewport;
                SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque, SamplerState.PointClamp, DepthStencilState.None, RasterizerState.CullNone);
                SpriteBatch.Draw(context.SourceTexture, new Rectangle(0, 0, originalViewport.Width, originalViewport.Height), Color.White);
                SpriteBatch.End();
            }
            renderTargetPool.Recycle((RenderTarget2D)context.SourceTexture);
            context.SourceTexture = null;

            // ----- Lens Flares
            if (renderLensFlares)
            {
                _lensFlareRenderer.Render(sceneQuery.LensFlareNodes, context);
            }

            // ----- Debug Output
            if (renderDebugOutput)
            {
                // ----- Optional: Restore the Z-Buffer
                // Currently, the hardware depth buffer is not initialized with useful data because
                // every time we change the render target, XNA deletes the depth buffer. If we want
                // the debug rendering to use correct depth buffer, we can restore the depth buffer
                // using the RebuildZBufferRenderer. If we remove this step, then the DebugRenderer
                // graphics will overlay the whole 3D scene.
                _rebuildZBufferRenderer.Render(context, true);

                // Render debug info added by game objects.
                DebugRenderer.Render(context);

                // Render intermediate render targets for debugging.
                // We do not use the public DebugRenderer here because the public DebugRenderer
                // might not be cleared every frame (the game logic can choose how it wants to
                // use the public renderer).
                if (VisualizeIntermediateRenderTargets)
                {
                    _internalDebugRenderer.DrawTexture(context.GBuffer0, new Rectangle(0, 0, 200, 200));
                    _internalDebugRenderer.DrawTexture(context.GBuffer1, new Rectangle(200, 0, 200, 200));
                    _internalDebugRenderer.DrawTexture(context.LightBuffer0, new Rectangle(400, 0, 200, 200));
                    _internalDebugRenderer.DrawTexture(context.LightBuffer1, new Rectangle(600, 0, 200, 200));
                    for (int i = 0; i < ShadowMaskRenderer.ShadowMasks.Count; i++)
                    {
                        var shadowMask = ShadowMaskRenderer.ShadowMasks[i];
                        if (shadowMask != null)
                        {
                            _internalDebugRenderer.DrawTexture(shadowMask, new Rectangle((i) * 200, 200, 200, 200));
                        }
                    }

                    _internalDebugRenderer.Render(context);
                    _internalDebugRenderer.Clear();
                }
            }

            // ----- Draw Reticle
            if (renderReticle && _sampleFramework.IsGuiVisible)
            {
                SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
                SpriteBatch.Draw(
                    _reticle,
                    new Vector2(originalViewport.Width / 2 - _reticle.Width / 2, originalViewport.Height / 2 - _reticle.Height / 2),
                    Color.Black);
                SpriteBatch.End();
            }

            // ----- Clean-up
            // It is very important to give every intermediate render target back to the
            // render target pool!
            renderTargetPool.Recycle(context.GBuffer0);
            context.GBuffer0 = null;
            renderTargetPool.Recycle(context.GBuffer1);
            context.GBuffer1 = null;
            renderTargetPool.Recycle((RenderTarget2D)context.Data[RenderContextKeys.DepthBufferHalf]);
            context.Data.Remove(RenderContextKeys.DepthBufferHalf);
            if (DebugMode != DeferredGraphicsDebugMode.VisualizeDiffuseLightBuffer)
            {
                renderTargetPool.Recycle(context.LightBuffer0);
            }
            context.LightBuffer0 = null;
            if (DebugMode != DeferredGraphicsDebugMode.VisualizeSpecularLightBuffer)
            {
                renderTargetPool.Recycle(context.LightBuffer1);
            }
            context.LightBuffer1 = null;
            ShadowMaskRenderer.RecycleShadowMasks();
            context.Data.Remove(RenderContextKeys.RebuildZBufferRenderer);
            context.SourceTexture = originalSourceTexture;
        }
Exemplo n.º 4
0
        // Renders the graphics screen. - This method is called in GraphicsManager.Render().
        protected override void OnRender(RenderContext context)
        {
            // Abort if no active camera is set.
            if (ActiveCameraNode == null)
            {
                return;
            }

            var renderTargetPool   = GraphicsService.RenderTargetPool;
            var graphicsDevice     = GraphicsService.GraphicsDevice;
            var screenRenderTarget = context.RenderTarget;
            var viewport           = context.Viewport;

            // All intermediate render targets have the size of the target viewport.
            int width  = context.Viewport.Width;
            int height = context.Viewport.Height;

            context.Viewport = new Viewport(0, 0, width, height);

            // Our scene and the camera must be set in the render context. This info is
            // required by many renderers.
            context.Scene      = Scene;
            context.CameraNode = ActiveCameraNode;

            // LOD (level of detail) settings are also specified in the context.
            context.LodCameraNode      = ActiveCameraNode;
            context.LodHysteresis      = 0.5f;
            context.LodBias            = EnableLod ? 1.0f : 0.0f;
            context.LodBlendingEnabled = false;

            // Get all scene nodes which overlap the camera frustum.
            CustomSceneQuery sceneQuery = Scene.Query <CustomSceneQuery>(ActiveCameraNode, context);

            // Generate cloud maps.
            // (Note: Only necessary if LayeredCloudMaps are used. If the cloud maps are
            // static and the settings do not change, it is not necessary to generate the
            // cloud maps in every frame. But in this example we use animated cloud maps.)
            _cloudMapRenderer.Render(sceneQuery.SkyNodes, context);

            // ----- G-Buffer Pass
            // The GBufferRenderer creates context.GBuffer0 and context.GBuffer1.
            _gBufferRenderer.Render(sceneQuery.RenderableNodes, sceneQuery.DecalNodes, context);

            // ----- Shadow Pass
            // The ShadowMapRenderer renders the shadow maps which are stored in the light nodes.
            context.RenderPass = "******";
            _shadowMapRenderer.Render(sceneQuery.Lights, context);
            context.RenderPass = null;

            // The ShadowMaskRenderer renders the shadows and stores them in one or more render
            // targets ("shadows masks").
            _shadowMaskRenderer.Render(sceneQuery.Lights, context);

            // In this render pipeline we do not need most shadow maps anymore and can
            // recycle them. The exception is the DirectionalLight shadow map which
            // might still be needed for forward rendering of alpha-blended objects.
            foreach (var node in sceneQuery.Lights)
            {
                var lightNode = (LightNode)node;
                if (lightNode.Shadow != null && !(lightNode.Light is DirectionalLight))
                {
                    renderTargetPool.Recycle(lightNode.Shadow.ShadowMap);
                    lightNode.Shadow.ShadowMap = null;
                }
            }

            // ----- Light Buffer Pass
            // The LightBufferRenderer creates context.LightBuffer0 (diffuse light) and
            // context.LightBuffer1 (specular light).
            LightBufferRenderer.Render(sceneQuery.Lights, context);

            // ----- Material Pass
            // In the material pass we render all meshes and decals into a single full-screen
            // render target. The shaders combine the material properties (diffuse texture, etc.)
            // with the light buffer info.
            context.RenderTarget = renderTargetPool.Obtain2D(new RenderTargetFormat(width, height, false, SurfaceFormat.HdrBlendable, DepthFormat.Depth24Stencil8));
            graphicsDevice.SetRenderTarget(context.RenderTarget);
            context.Viewport = graphicsDevice.Viewport;
            graphicsDevice.Clear(Color.Black);
            graphicsDevice.DepthStencilState = DepthStencilState.Default;
            graphicsDevice.RasterizerState   = RasterizerState.CullCounterClockwise;
            graphicsDevice.BlendState        = BlendState.Opaque;
            context.RenderPass = "******";
            _meshRenderer.Render(sceneQuery.RenderableNodes, context);
            _decalRenderer.Render(sceneQuery.DecalNodes, context);
            context.RenderPass = null;

            // The meshes rendered in the last step might use additional floating-point
            // textures (e.g. the light buffers) in the different graphics texture stages.
            // We reset the texture stages (setting all GraphicsDevice.Textures to null),
            // otherwise XNA might throw exceptions.
            graphicsDevice.ResetTextures();

            // ----- Occlusion Queries
            _lensFlareRenderer.UpdateOcclusion(sceneQuery.LensFlareNodes, context);

            // ----- Sky
            _skyRenderer.Render(sceneQuery.SkyNodes, context);

            // ----- Fog
            _fogRenderer.Render(sceneQuery.FogNodes, context);

            // ----- Forward Rendering of Alpha-Blended Meshes and Particles
            graphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
            graphicsDevice.RasterizerState   = RasterizerState.CullCounterClockwise;
            graphicsDevice.BlendState        = BlendState.AlphaBlend;
            context.RenderPass = "******";
            AlphaBlendSceneRenderer.Render(sceneQuery.RenderableNodes, context, RenderOrder.BackToFront);
            context.RenderPass = null;
            graphicsDevice.ResetTextures();

            // The shadow maps could be used by some shaders of the alpha-blended
            // objects - but now, we can recycle all shadow maps.
            foreach (var node in sceneQuery.Lights)
            {
                var lightNode = (LightNode)node;
                if (lightNode.Shadow != null)
                {
                    renderTargetPool.Recycle(lightNode.Shadow.ShadowMap);
                    lightNode.Shadow.ShadowMap = null;
                }
            }

            // ----- Post Processors
            // The post-processors modify the scene image and the result is written into
            // the final render target - which is usually the back  buffer (but this could
            // also be another off-screen render target used in another graphics screen).
            context.SourceTexture = context.RenderTarget;
            context.RenderTarget  = screenRenderTarget;
            context.Viewport      = viewport;
            PostProcessors.Process(context);

            renderTargetPool.Recycle((RenderTarget2D)context.SourceTexture);
            context.SourceTexture = null;

            // ----- Lens Flares
            _lensFlareRenderer.Render(sceneQuery.LensFlareNodes, context);

            // ----- Optional: Restore the Z-Buffer
            // Currently, the hardware depth buffer is not initialized with useful data because
            // every time we change the render target, XNA deletes the depth buffer. If we want
            // the debug rendering to use correct depth buffer, we can restore the depth buffer
            // using the RebuildZBufferRenderer. If we remove this step, then the DebugRenderer
            // graphics will overlay the whole 3D scene.
            _rebuildZBufferRenderer.Render(context, true);

            // ----- Debug Output
            // Render debug info added by game objects.
            DebugRenderer.Render(context);

            // ----- Draw Reticle
            if (DrawReticle)
            {
                _spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
                _spriteBatch.Draw(
                    _reticle,
                    new Vector2(viewport.Width / 2 - _reticle.Width / 2, viewport.Height / 2 - _reticle.Height / 2),
                    Color.Black);
                _spriteBatch.End();
            }

            // Render intermediate render targets for debugging.
            // We do not use the public DebugRenderer here because the public DebugRenderer
            // might not be cleared every frame (the game logic can choose how it wants to
            // use the public renderer).
            if (VisualizeIntermediateRenderTargets)
            {
                _internalDebugRenderer.DrawTexture(context.GBuffer0, new Rectangle(0, 0, 200, 200));
                _internalDebugRenderer.DrawTexture(context.GBuffer1, new Rectangle(200, 0, 200, 200));
                _internalDebugRenderer.DrawTexture(context.LightBuffer0, new Rectangle(400, 0, 200, 200));
                _internalDebugRenderer.DrawTexture(context.LightBuffer1, new Rectangle(600, 0, 200, 200));
                for (int i = 0; i < _shadowMaskRenderer.ShadowMasks.Count; i++)
                {
                    var shadowMask = _shadowMaskRenderer.ShadowMasks[i];
                    if (shadowMask != null)
                    {
                        _internalDebugRenderer.DrawTexture(shadowMask, new Rectangle((i) * 200, 200, 200, 200));
                    }
                }

                _internalDebugRenderer.Render(context);
                _internalDebugRenderer.Clear();
            }

            // ----- Clean-up
            // It is very important to give every intermediate render target back to the
            // render target pool!
            renderTargetPool.Recycle(context.GBuffer0);
            context.GBuffer0 = null;
            renderTargetPool.Recycle(context.GBuffer1);
            context.GBuffer1 = null;
            renderTargetPool.Recycle((RenderTarget2D)context.Data[RenderContextKeys.DepthBufferHalf]);
            context.Data.Remove(RenderContextKeys.DepthBufferHalf);
            renderTargetPool.Recycle(context.LightBuffer0);
            context.LightBuffer0 = null;
            renderTargetPool.Recycle(context.LightBuffer1);
            context.LightBuffer1 = null;
            _shadowMaskRenderer.RecycleShadowMasks();
            context.Scene         = null;
            context.CameraNode    = null;
            context.LodHysteresis = 0;
            context.LodCameraNode = null;
            context.RenderPass    = null;
        }