//-------------------------------------------------------------- #region Creation & Cleanup //-------------------------------------------------------------- public DeferredGraphicsScreen(IServiceLocator services) : base(services.GetInstance <IGraphicsService>()) { var contentManager = services.GetInstance <ContentManager>(); SpriteBatch = new SpriteBatch(GraphicsService.GraphicsDevice); // Let's create the necessary scene node renderers: // The current sample contains MeshNodes (opaque and transparent), DecalNodes // and ParticleSystemNodes (transparent). MeshRenderer = new MeshRenderer(); _decalRenderer = new DecalRenderer(GraphicsService); _billboardRenderer = new BillboardRenderer(GraphicsService, 2048) { EnableSoftParticles = true, // If you have an extreme amount of particles that cover the entire screen, // you can turn on offscreen rendering to improve performance. //EnableOffscreenRendering = true, }; // The _alphaBlendSceneRenderer combines all renderers for transparent // (= alpha blended) objects. AlphaBlendSceneRenderer = new SceneRenderer(); AlphaBlendSceneRenderer.Renderers.Add(MeshRenderer); AlphaBlendSceneRenderer.Renderers.Add(_billboardRenderer); AlphaBlendSceneRenderer.Renderers.Add(new WaterRenderer(GraphicsService)); #if !TRIAL // The FogSphereSample is not included in the trial version. AlphaBlendSceneRenderer.Renderers.Add(new FogSphereRenderer(GraphicsService)); #endif // Renderer for cloud maps. (Only necessary if LayeredCloudMaps are used.) _cloudMapRenderer = new CloudMapRenderer(GraphicsService); // Renderer for SceneCaptureNodes. See also SceneCapture2DSample. // In the constructor we specify a method is called in SceneCaptureRenderer.Render() // when the scene must be rendered for the SceneCaptureNodes. _sceneCaptureRenderer = new SceneCaptureRenderer(context => { // Get scene nodes which are visible by the current camera. CustomSceneQuery sceneQuery = Scene.Query <CustomSceneQuery>(context.CameraNode, context); // Render scene (with post-processing, with lens flares, no debug rendering, no reticle). RenderScene(sceneQuery, context, true, true, false, false); }); // Renderer for PlanarReflectionNodes. See also PlanarReflectionSample. // In the constructor we specify a method is called in PlanarReflectionRenderer.Render() // to create the reflection images. _planarReflectionRenderer = new PlanarReflectionRenderer(context => { // Get scene nodes which are visible by the current camera. CustomSceneQuery sceneQuery = Scene.Query <CustomSceneQuery>(context.CameraNode, context); // Planar reflections are often for WaterNodes. These nodes should not be rendered // into their own reflection map. But when the water surface is displaced by waves, // some waves could be visible in the reflection. // Simple solution: Do not render any water nodes into the reflection map. for (int i = 0; i < sceneQuery.RenderableNodes.Count; i++) { if (sceneQuery.RenderableNodes[i] is WaterNode) { sceneQuery.RenderableNodes[i] = null; } } // Render scene (no post-processing, no lens flares, no debug rendering, no reticle). RenderScene(sceneQuery, context, false, false, false, false); }); _waterWavesRenderer = new WaterWavesRenderer(GraphicsService); // Shadows _shadowMapRenderer = new ShadowMapRenderer(MeshRenderer); _shadowMaskRenderer = new ShadowMaskRenderer(GraphicsService, 2); // Renderers which create the intermediate render targets: // Those 2 renderers are implemented in this sample. Those functions could // be implemented directly in this class but we have created separate classes // to make the code more readable. _gBufferRenderer = new GBufferRenderer(GraphicsService, MeshRenderer, _decalRenderer); LightBufferRenderer = new LightBufferRenderer(GraphicsService); // Other specialized renderers: _lensFlareRenderer = new LensFlareRenderer(GraphicsService, SpriteBatch); _skyRenderer = new SkyRenderer(GraphicsService); _fogRenderer = new FogRenderer(GraphicsService); _internalDebugRenderer = new DebugRenderer(GraphicsService, SpriteBatch, null); _rebuildZBufferRenderer = new RebuildZBufferRenderer(GraphicsService); Scene = new Scene(); // This screen needs a HDR filter to map high dynamic range values back to // low dynamic range (LDR). PostProcessors = new PostProcessorChain(GraphicsService); PostProcessors.Add(new HdrFilter(GraphicsService) { EnableBlueShift = true, BlueShiftCenter = 0.00007f, BlueShiftRange = 0.5f, BlueShiftColor = new Vector3F(0, 0, 2f), MinExposure = 0, MaxExposure = 10, BloomIntensity = 1, BloomThreshold = 0.6f, }); _underwaterPostProcessor = new UnderwaterPostProcessor(GraphicsService, contentManager); PostProcessors.Add(_underwaterPostProcessor); // Use 2D texture for reticle. _reticle = contentManager.Load <Texture2D>("Reticle"); // Use the sprite font of the GUI. var uiContentManager = services.GetInstance <ContentManager>("UIContent"); var spriteFont = uiContentManager.Load <SpriteFont>("Default"); DebugRenderer = new DebugRenderer(GraphicsService, SpriteBatch, spriteFont) { DefaultColor = new Color(0, 0, 0), DefaultTextPosition = new Vector2F(10), }; EnableLod = true; }
//-------------------------------------------------------------- #region Creation & Cleanup //-------------------------------------------------------------- public DeferredGraphicsScreen(IServiceLocator services) : base(services.GetInstance <IGraphicsService>()) { //_sampleFramework = services.GetInstance<SampleFramework>(); var contentManager = services.GetInstance <ContentManager>(); SpriteBatch = GraphicsService.GetSpriteBatch(); // Let's create the necessary scene node renderers: #if !XBOX360 TerrainRenderer = new TerrainRenderer(GraphicsService); #endif MeshRenderer = new MeshRenderer(); // The _opaqueMeshSceneRenderer combines all renderers for opaque // (= not alpha blended) meshes. _opaqueMeshSceneRenderer = new SceneRenderer(); #if !XBOX360 _opaqueMeshSceneRenderer.Renderers.Add(TerrainRenderer); #endif _opaqueMeshSceneRenderer.Renderers.Add(MeshRenderer); _decalRenderer = new DecalRenderer(GraphicsService); _billboardRenderer = new BillboardRenderer(GraphicsService, 2048) { EnableSoftParticles = true, // If you have an extreme amount of particles that cover the entire screen, // you can turn on offscreen rendering to improve performance. //EnableOffscreenRendering = true, }; // The AlphaBlendSceneRenderer combines all renderers for transparent // (= alpha blended) objects. AlphaBlendSceneRenderer = new SceneRenderer(); AlphaBlendSceneRenderer.Renderers.Add(MeshRenderer); AlphaBlendSceneRenderer.Renderers.Add(_billboardRenderer); AlphaBlendSceneRenderer.Renderers.Add(new WaterRenderer(GraphicsService)); //AlphaBlendSceneRenderer.Renderers.Add(new FogSphereRenderer(GraphicsService)); //AlphaBlendSceneRenderer.Renderers.Add(new VolumetricLightRenderer(GraphicsService)); #if !XBOX360 // Update terrain clipmaps. (Only necessary if TerrainNodes are used.) _terrainClipmapRenderer = new TerrainClipmapRenderer(GraphicsService); #endif // Renderer for cloud maps. (Only necessary if LayeredCloudMaps are used.) _cloudMapRenderer = new CloudMapRenderer(GraphicsService); // Renderer for SceneCaptureNodes. See also SceneCapture2DSample. // In the constructor we specify a method which is called in SceneCaptureRenderer.Render() // when the scene must be rendered for the SceneCaptureNodes. SceneCaptureRenderer = new SceneCaptureRenderer(context => { // Get scene nodes which are visible by the current camera. CustomSceneQuery sceneQuery = Scene.Query <CustomSceneQuery>(context.CameraNode, context); // Render scene (with post-processing, with lens flares, no debug rendering, no reticle). RenderScene(sceneQuery, context, true, true, false, false); }); // Renderer for PlanarReflectionNodes. See also PlanarReflectionSample. // In the constructor we specify a method which is called in PlanarReflectionRenderer.Render() // to create the reflection images. _planarReflectionRenderer = new PlanarReflectionRenderer(context => { // Get scene nodes which are visible by the current camera. CustomSceneQuery sceneQuery = Scene.Query <CustomSceneQuery>(context.CameraNode, context); var planarReflectionNode = (PlanarReflectionNode)context.ReferenceNode; // Planar reflections are often for WaterNodes. These nodes should not be rendered // into their own reflection map because when the water surface is displaced by waves, // some waves could be visible in the reflection. // --> Remove the water node from the renderable nodes. (In our samples, the water // node is the parent of the reflection node.) if (planarReflectionNode.Parent is WaterNode) { var index = sceneQuery.RenderableNodes.IndexOf(planarReflectionNode.Parent); if (index >= 0) { sceneQuery.RenderableNodes[index] = null; } } // Render scene (no post-processing, no lens flares, no debug rendering, no reticle). RenderScene(sceneQuery, context, false, false, false, false); }); _waterWavesRenderer = new WaterWavesRenderer(GraphicsService); // The shadow map renderer renders a depth image from the viewpoint of the light and // stores it in LightNode.Shadow.ShadowMap. ShadowMapRenderer = new ShadowMapRenderer(context => { var query = context.Scene.Query <ShadowCasterQuery>(context.CameraNode, context); if (query.ShadowCasters.Count == 0) { return(false); } _opaqueMeshSceneRenderer.Render(query.ShadowCasters, context); return(true); }); // The shadow mask renderer evaluates the shadow maps, does shadow filtering // and stores the resulting shadow factor in a screen space image //(see LightNode.Shadow.ShadowMask/ShadowMaskChannel). ShadowMaskRenderer = new ShadowMaskRenderer(GraphicsService, 2); // Optionally, we can blur the shadow mask to make the shadows smoother. var blur = new Blur(GraphicsService) { IsAnisotropic = false, IsBilateral = true, EdgeSoftness = 0.05f, Scale = 1f, Enabled = false, // Disable blur by default. }; blur.InitializeGaussianBlur(11, 3, true); ShadowMaskRenderer.Filter = blur; // Renderers which create the intermediate render targets: // Those 2 renderers are implemented in this sample. Those functions could // be implemented directly in this class but we have created separate classes // to make the code more readable. _gBufferRenderer = new GBufferRenderer(GraphicsService, _opaqueMeshSceneRenderer, _decalRenderer); LightBufferRenderer = new LightBufferRenderer(GraphicsService); // Other specialized renderers: _lensFlareRenderer = new LensFlareRenderer(GraphicsService); _skyRenderer = new SkyRenderer(GraphicsService); _fogRenderer = new FogRenderer(GraphicsService); _internalDebugRenderer = new DebugRenderer(GraphicsService, null); _rebuildZBufferRenderer = new RebuildZBufferRenderer(GraphicsService); Scene = new Scene(); // This screen needs a HDR filter to map high dynamic range values back to // low dynamic range (LDR). PostProcessors = new PostProcessorChain(GraphicsService); PostProcessors.Add(new HdrFilter(GraphicsService) { EnableBlueShift = true, BlueShiftCenter = 0.0004f, BlueShiftRange = 0.5f, //BlueShiftColor = new Vector3F(1.05f / 4f, 0.97f / 4f, 1.27f / 4f), // Default physically-based blue-shift BlueShiftColor = new Vector3F(0.25f, 0.25f, 0.7f), // More dramatic blue-shift MinExposure = 0, MaxExposure = 10, BloomIntensity = 1, BloomThreshold = 0.6f, }); //_underwaterPostProcessor = new UnderwaterPostProcessor(GraphicsService, contentManager); //PostProcessors.Add(_underwaterPostProcessor); // Use 2D texture for reticle. //_reticle = contentManager.Load<Texture2D>("Reticle"); // Use the sprite font of the GUI. //var uiContentManager = services.GetInstance<ContentManager>("UIContent"); //var spriteFont = uiContentManager.Load<SpriteFont>("UI Themes/BlendBlue/Default"); var spriteFont = contentManager.Load <SpriteFont>("DigitalRune.Editor.Game/Fonts/DejaVuSans"); DebugRenderer = new DebugRenderer(GraphicsService, spriteFont) { DefaultColor = new Color(0, 0, 0), DefaultTextPosition = new Vector2F(10), }; EnableLod = true; }
// Renders the graphics screen. - This method is called in GraphicsManager.Render(). protected override void OnRender(RenderContext context) { if (ActiveCameraNode == null) { return; } // 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; // ----- Preprocessing // For some scene nodes we have to update some off-screen render targets before the // actual scene is rendered. // // We only have to do this for the scene nodes which are visible // by the camera frustum: PreprocessingSceneQuery preprocessingQuery = Scene.Query <PreprocessingSceneQuery>(context.CameraNode, context); #if !XBOX360 // TODO: _terrainClipmapRenderer.Render(preprocessingQuery.TerrainNodes, context); #endif // Generate cloud maps. // 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 the SkySample we use animated cloud maps. // The CloudMapRenderer can be called several times per frame, it will only // do the work once per frame. // See also SkySample. _cloudMapRenderer.Render(preprocessingQuery.CloudLayerNodes, context); // Compute ocean waves. // Only necessary if WaterNodes with OceanWaves are used. _waterWavesRenderer.Render(preprocessingQuery.WaterNodes, context); // Perform render-to-texture operations. // Only necessary if SceneCaptureNodes are used. // See also SceneCapture2DSample. SceneCaptureRenderer.Render(preprocessingQuery.SceneCaptureNodes, context); // Render reflections. // Only necessary if PlanarReflectionNodes are used. // See also PlanarReflectionSample. _planarReflectionRenderer.Render(preprocessingQuery.PlanarReflectionNodes, context); // ----- Scene Rendering // Get all scene nodes which overlap the camera frustum. CustomSceneQuery sceneQuery = Scene.Query <CustomSceneQuery>(context.CameraNode, context); // Render the scene nodes of the sceneQuery. RenderScene(sceneQuery, context, true, true, true, DrawReticle); // ----- Clean-up context.Scene = null; context.CameraNode = null; context.LodCameraNode = null; context.LodHysteresis = 0; }
private void UpdateCubeMap(TimeSpan deltaTime) { if (_cloudMapRenderer == null) { // This is the first call of UpdateCubeMap. Create the renderers which // we need to render the cube map. // The CloudMapRenderer creates and animates the LayeredCloudMaps. _cloudMapRenderer = new CloudMapRenderer(_graphicsService); // The SkyRenderer renders SkyNodes. _skyRenderer = new SkyRenderer(_graphicsService); // We use a ColorEncoder to encode a HDR image in a normal Color texture. _colorEncoder = new ColorEncoder(_graphicsService) { SourceEncoding = ColorEncoding.Rgb, TargetEncoding = SkyboxNode.Encoding, }; // The SceneCaptureRenderer handles SceneCaptureNodes. We need to specify // a delegate which is called in SceneCaptureNode.Render(). _sceneCaptureRenderer = new SceneCaptureRenderer(context => { var graphicsDevice = _graphicsService.GraphicsDevice; var renderTargetPool = _graphicsService.RenderTargetPool; // We have to render into this render target. var ldrTarget = context.RenderTarget; // Reset render states. graphicsDevice.BlendState = BlendState.Opaque; graphicsDevice.DepthStencilState = DepthStencilState.Default; graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; // Use an intermediate HDR render target with the same resolution as the final target. var format = new RenderTargetFormat(ldrTarget) { SurfaceFormat = SurfaceFormat.HdrBlendable, DepthStencilFormat = DepthFormat.Depth24Stencil8 }; var hdrTarget = renderTargetPool.Obtain2D(format); graphicsDevice.SetRenderTarget(hdrTarget); context.RenderTarget = hdrTarget; graphicsDevice.Clear(Color.Black); // Render the sky. _skyRenderer.Render(_skyGroupNode.Children, context); // Convert the HDR image to RGBM image. context.SourceTexture = hdrTarget; context.RenderTarget = ldrTarget; _colorEncoder.Process(context); context.SourceTexture = null; // Clean up. renderTargetPool.Recycle(hdrTarget); context.RenderTarget = ldrTarget; }); // Normally, the render context is managed by the graphics service. // When we call renderer outside of a GraphicsScreen, we have to use our // own context instance. _context = new RenderContext(_graphicsService); } // Update render context. // Frame needs to be updated to tell the renderers that this is a new "frame". // (Otherwise, they might abort early to avoid duplicate work in the same frame.) _context.Frame++; // DeltaTime is relevant for renderers such as the CloudMapRenderer because it // might have to animate the clouds. _context.DeltaTime = deltaTime; // Create cloud maps. _cloudMapRenderer.Render(_skyGroupNode.Children, _context); // Capture sky in cube map. _sceneCaptureRenderer.Render(_sceneCaptureNode, _context); }