public StartScreenComponent(Microsoft.Xna.Framework.Game game, IServiceLocator services) : base(game) { _services = services; _inputService = services.GetInstance<IInputService>(); _graphicsService = services.GetInstance<IGraphicsService>(); _uiService = _services.GetInstance<IUIService>(); // Add a GraphicsScreen to draw some text. In a real game we would draw // a spectacular start screen image instead. _graphicsScreen = new SampleGraphicsScreen(services); _graphicsScreen.ClearBackground = true; _graphicsService.Screens.Insert(0, _graphicsScreen); // Load stuff in a parallel task. _loadStuffTask = Parallel.Start(LoadStuff); }
public void Render(IList<SceneNode> occluders, LightNode lightNode, SceneNodeRenderer renderer, RenderContext context) { if (context == null) throw new ArgumentNullException("context"); context.ThrowIfCameraMissing(); // ----- Sort occluders by type: IOcclusionProxy vs. SceneNode SortOccluders(occluders, renderer, context); Statistics.Occluders = _occlusionProxies.Count + _sceneNodes.Count; // ----- Update all IOcclusionProxy in background. if (_occlusionProxies.Count > 0) { if (EnableMultithreading) _updateTask = Parallel.Start(_updateOcclusionProxies); else UpdateOcclusionProxies(); } // ----- Backup render state. var originalRenderTarget = context.RenderTarget; var originalViewport = context.Viewport; var graphicsService = context.GraphicsService; var graphicsDevice = graphicsService.GraphicsDevice; var originalRenderState = new RenderStateSnapshot(graphicsDevice); // ----- Camera properties var cameraNode = context.CameraNode; Matrix cameraView = (Matrix)cameraNode.View; var cameraProjection = cameraNode.Camera.Projection; Matrix cameraViewProjection = cameraView * cameraProjection; if (lightNode == null) { _lightHzbAvailable = false; } else { // ----- Render light HZB. _lightHzbAvailable = true; var shadow = lightNode.Shadow as CascadedShadow; if (shadow == null) throw new ArgumentException("LightNode expected to have a CascadedShadow.", "lightNode"); // Set up orthographic camera similar to CascadedShadowMapRenderer. context.CameraNode = _orthographicCameraNode; // Part of camera frustum covered by shadow map. var maxShadowDistance = shadow.Distances[shadow.NumberOfCascades - 1]; _splitVolume.SetFieldOfView(cameraProjection.FieldOfViewY, cameraProjection.AspectRatio, cameraProjection.Near, Math.Min(cameraProjection.Far, maxShadowDistance)); // Find the bounding sphere of the camera frustum. Vector3F center; float radius; GetBoundingSphere(_splitVolume, out center, out radius); Matrix33F orientation = lightNode.PoseWorld.Orientation; Vector3F lightBackward = orientation.GetColumn(2); var orthographicProjection = (OrthographicProjection)_orthographicCameraNode.Camera.Projection; // Create a tight orthographic frustum around the cascade's bounding sphere. orthographicProjection.SetOffCenter(-radius, radius, -radius, radius, 0, 2 * radius); center = cameraNode.PoseWorld.ToWorldPosition(center); Vector3F cameraPosition = center + radius * lightBackward; Pose frustumPose = new Pose(cameraPosition, orientation); // For rendering the shadow map, move near plane back by MinLightDistance // to catch occluders in front of the cascade. orthographicProjection.Near = -shadow.MinLightDistance; _orthographicCameraNode.PoseWorld = frustumPose; Pose lightView = frustumPose.Inverse; Matrix lightViewProjection = (Matrix)lightView * orthographicProjection; _parameterCameraViewProj.SetValue(lightViewProjection); _parameterCameraNear.SetValue(orthographicProjection.Near); _parameterCameraFar.SetValue(orthographicProjection.Far); RenderOccluders(renderer, context); CreateDepthHierarchy(_lightHzb, context); // Set effect parameters for use in Query(). _lightAabb = _orthographicCameraNode.Aabb; _parameterLightViewProj.SetValue(lightViewProjection); _parameterLightToCamera.SetValue(Matrix.Invert(lightViewProjection) * cameraViewProjection); context.CameraNode = cameraNode; } // ----- Render camera HZB. // Set camera parameters. (These effect parameters are also needed in Query()!) _cameraAabb = cameraNode.Aabb; _parameterCameraViewProj.SetValue(cameraViewProjection); _parameterCameraNear.SetValue(cameraProjection.Near); _parameterCameraFar.SetValue(cameraProjection.Far); var lodCameraNode = context.LodCameraNode; if (lodCameraNode != null) { // Enable distance culling. _parameterCameraPosition.SetValue((Vector3)lodCameraNode.PoseWorld.Position); float yScale = Math.Abs(lodCameraNode.Camera.Projection.ToMatrix44F().M11); _parameterNormalizationFactor.SetValue(1.0f / yScale * cameraNode.LodBias * context.LodBias); } else { // Disable distance culling. _parameterCameraPosition.SetValue(new Vector3()); _parameterNormalizationFactor.SetValue(0); } RenderOccluders(renderer, context); CreateDepthHierarchy(_cameraHzb, context); _sceneNodes.Clear(); _occlusionProxies.Clear(); // Restore render state. graphicsDevice.SetRenderTarget(null); originalRenderState.Restore(); context.RenderTarget = originalRenderTarget; context.Viewport = originalViewport; }
// Updates the different sub-systems (input, physics, game logic, ...). protected override void Update(GameTime gameTime) { _deltaTime = gameTime.ElapsedGameTime; // Tell the profiler that a new frame has begun. _profiler.NewFrame(); _profiler.Start("Update"); // Update input manager. The input manager gets the device states and performs other work. // (Note: XNA requires that the input service is run on the main thread!) _profiler.Start("InputManager.Update "); _inputManager.Update(_deltaTime); _profiler.Stop(); if (EnableParallelGameLoop) { // In a parallel game loop animation, physics and particles are started at // the end of the Update method. The services are now running in parallel. // --> Wait for services to finish. _updateAnimationTask.Wait(); _updatePhysicsTask.Wait(); _updateParticlesTask.Wait(); // Now, nothing is running in parallel anymore and we can apply the animations. // (This means the animation values are written to the objects and properties // that are being animated.) _animationManager.ApplyAnimations(); } else { // Update animation, physics, particles sequentially. // For debugging we can pause the physics and particle simulations with <P>, // and execute single simulation steps with <T>. if (_inputManager.IsPressed(Keys.P, true)) _isSimulationPaused = !_isSimulationPaused; if (!_isSimulationPaused || _inputManager.IsPressed(Keys.T, true)) { // Update physics simulation. _profiler.Start("Simulation.Update "); _simulation.Update(_deltaTime); _profiler.Stop(); // Update particles. _profiler.Start("ParticleSystemManager.Update "); _particleSystemManager.Update(_deltaTime); _profiler.Stop(); } // Update animations. // (The animation results are stored internally but not yet applied). _profiler.Start("AnimationManger.Update "); _animationManager.Update(_deltaTime); _profiler.Stop(); // Apply animations. // (The animation results are written to the objects and properties that // are being animated. ApplyAnimations() must be called at a point where // it is thread-safe to change the animated objects and properties.) _profiler.Start("AnimationManager.ApplyAnimations"); _animationManager.ApplyAnimations(); _profiler.Stop(); } // Run any task completion callbacks that have been scheduled. _profiler.Start("Parallel.RunCallbacks "); Parallel.RunCallbacks(); _profiler.Stop(); // When the menu is visible, update SampleFramework before the game logic. if (_sampleFramework.IsMenuVisible) _sampleFramework.Update(); // Update XNA GameComponents. _profiler.Start("base.Update "); base.Update(gameTime); _profiler.Stop(); // Update UI manager. The UI manager updates all registered UIScreens. _profiler.Start("UIManager.Update "); _uiManager.Update(_deltaTime); _profiler.Stop(); // Update DigitalRune GameObjects. _profiler.Start("GameObjectManager.Update "); _gameObjectManager.Update(_deltaTime); _profiler.Stop(); // When the menu is hidden, update SampleFramework after the game logic. if (!_sampleFramework.IsMenuVisible) _sampleFramework.Update(); if (EnableParallelGameLoop) { // Start animation, physics and particle simulation. They will be executed // parallel to the graphics rendering in Draw(). _updateAnimationTask = Parallel.Start(_updateAnimation); _updatePhysicsTask = Parallel.Start(_updatePhysics); _updateParticlesTask = Parallel.Start(_updateParticles); } _profiler.Stop(); }