public override void Update(GameTime gameTime) { if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); // Start the first animation. var wrappedAnimation = WrapAnimation(_currentAvatarAnimationPreset); AnimationService.StartAnimation(wrappedAnimation, _avatarPose).AutoRecycle(); _debugRenderer.Clear(); _debugRenderer.DrawText("\n\nCurrent Animation: " + _currentAvatarAnimationPreset); } } else { if (InputService.IsPressed(Buttons.A, false, LogicalPlayerIndex.One)) { // Switch to next preset. _currentAvatarAnimationPreset++; if (!Enum.IsDefined(typeof(AvatarAnimationPreset), _currentAvatarAnimationPreset)) { _currentAvatarAnimationPreset = 0; } // Cross-fade to new animation. var wrappedAnimation = WrapAnimation(_currentAvatarAnimationPreset); AnimationService.StartAnimation(wrappedAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.5)) ).AutoRecycle(); _debugRenderer.Clear(); _debugRenderer.DrawText("\n\nCurrent Animation: " + _currentAvatarAnimationPreset); } if (InputService.IsPressed(Buttons.B, false, LogicalPlayerIndex.One)) { // Switch to previous preset. _currentAvatarAnimationPreset--; if (!Enum.IsDefined(typeof(AvatarAnimationPreset), _currentAvatarAnimationPreset)) { _currentAvatarAnimationPreset = (AvatarAnimationPreset)EnumHelper.GetValues(typeof(AvatarAnimationPreset)).Length - 1; } // Cross-fade to new animation. var wrappedAnimation = WrapAnimation(_currentAvatarAnimationPreset); AnimationService.StartAnimation(wrappedAnimation, _avatarPose, AnimationTransitions.Replace(TimeSpan.FromSeconds(0.5)) ).AutoRecycle(); _debugRenderer.Clear(); _debugRenderer.DrawText("\n\nCurrent Animation: " + _currentAvatarAnimationPreset); } } }
public override void Update(GameTime gameTime) { _debugRenderer.Clear(); if (_avatarPose == null) { // Must wait till renderer is ready. Before that we do not get skeleton info. if (_avatarRenderer.State == AvatarRendererState.Ready) { // Create AvatarPose. _avatarPose = new AvatarPose(_avatarRenderer); // A 'bone transform' is the transformation of a bone relative to its bind pose. // Bone transforms define the pose of a skeleton. // Rotate arm of avatar. SkeletonPose skeletonPose = _avatarPose.SkeletonPose; int shoulderIndex = skeletonPose.Skeleton.GetIndex("ShoulderLeft"); skeletonPose.SetBoneTransform(shoulderIndex, new SrtTransform(QuaternionF.CreateRotationZ(-0.9f))); // The class SkeletonHelper provides some useful extension methods. // One is SetBoneRotationAbsolute() which sets the orientation of a bone relative // to model space. // Rotate elbow to make the lower arm point forward. int elbowIndex = skeletonPose.Skeleton.GetIndex("ElbowLeft"); SkeletonHelper.SetBoneRotationAbsolute(skeletonPose, elbowIndex, QuaternionF.CreateRotationY(ConstantsF.PiOver2)); // Draw avatar skeleton for debugging. _debugRenderer.DrawSkeleton(skeletonPose, _pose, Vector3F.One, 0.02f, Color.Orange, true); } } }
/// <inheritdoc/> protected override void OnRender(RenderContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } _numberOfDraws++; var graphicsDevice = GraphicsService.GraphicsDevice; context.CameraNode = CameraNode; DebugRenderer.Render(context); DrawTitleSafeArea(graphicsDevice); // Draw FPS text. _internalDebugRenderer.Clear(); _internalDebugRenderer.DrawText( _stringBuilder, new Vector2F((int)(context.Viewport.Width - _textWidth - 5), 0), Color.Yellow); _internalDebugRenderer.Render(context); context.CameraNode = null; }
public override void Update(GameTime gameTime) { Scene.Update(gameTime.ElapsedGameTime); DebugRenderer.Clear(); base.Update(gameTime); }
private void RenderDebugInfo(RenderContext context) { _debugRenderer.Clear(); _debugRenderer.DrawAxes(Pose.Identity, 0.5f, true); //_debugRenderer.DrawTexture(_cloudLayerNode._renderTarget, new Rectangle(1280-512, 0, 512, 512)); #if XBOX _debugRenderer.DrawText(_ephemeris.Time.DateTime.ToString()); #else _debugRenderer.DrawText(_ephemeris.Time.ToString()); #endif _debugRenderer.PointSize = 10; var extraterrestrialSunlight = Ephemeris.ExtraterrestrialSunlight; Vector3F sun; Vector3F ambient; Ephemeris.GetSunlight(_scatteringSky.ObserverAltitude, 2.2f, _scatteringSky.SunDirection, out sun, out ambient); var scatterSun = _scatteringSky.GetSunlight() / _scatteringSky.SunIntensity * extraterrestrialSunlight; var scatterAmbient = _scatteringSky.GetAmbientLight(1024); scatterAmbient = scatterAmbient / _scatteringSky.SunIntensity * extraterrestrialSunlight; var scatterFog = _scatteringSky.GetFogColor(128) / _scatteringSky.SunIntensity * extraterrestrialSunlight; var luminance = Vector3F.Dot(GraphicsHelper.LuminanceWeights, scatterFog); scatterFog = InterpolationHelper.Lerp(scatterFog, new Vector3F(luminance), 0.7f); _debugRenderer.DrawText("Extraterrestrial sun intensity:" + extraterrestrialSunlight.Length); _debugRenderer.DrawText("Spectrum sun intensity:" + sun.Length); _debugRenderer.DrawText("Scatter sun intensity:" + scatterSun.Length); _debugRenderer.DrawText("\nSpectrum ambient intensity:" + ambient.Length); _debugRenderer.DrawText("Scatter ambient intensity:" + scatterAmbient.Length); _debugRenderer.DrawText("\nScatter fog intensity:" + scatterFog.Length); _debugRenderer.DrawPoint(new Vector3F(-0.5f, 0, 0), new Color((Vector3)extraterrestrialSunlight.Normalized), true); sun.TryNormalize(); ambient /= ambient.Length; _debugRenderer.DrawPoint(new Vector3F(0, 0, 0), new Color((Vector3)sun), true); _debugRenderer.DrawPoint(new Vector3F(0, -0.5f, 0), new Color((Vector3)ambient), true); scatterSun.TryNormalize(); scatterAmbient.TryNormalize(); _debugRenderer.DrawPoint(new Vector3F(0.5f, 0, 0), new Color((Vector3)scatterSun), true); _debugRenderer.DrawPoint(new Vector3F(0.5f, -0.5f, 0), new Color((Vector3)scatterAmbient), true); scatterFog.TryNormalize(); _debugRenderer.DrawPoint(new Vector3F(0, 0.5f, 0), new Color((Vector3)scatterFog), true); _debugRenderer.PointSize = 40f; _debugRenderer.Render(context); }
public override void Update(GameTime gameTime) { if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); // Create a ragdoll for the avatar. _ragdoll = Ragdoll.CreateAvatarRagdoll(_avatarPose, Simulation); // Set the world space pose of the whole ragdoll. And copy the bone poses of the // current skeleton pose. _ragdoll.Pose = _pose; _ragdoll.UpdateBodiesFromSkeleton(_avatarPose.SkeletonPose); // In this sample we use a passive ragdoll where we need joints to hold the // limbs together and limits to control the angular movement. _ragdoll.EnableJoints(); _ragdoll.EnableLimits(); // Set all motors to constraint motors that only use damping. This adds a damping // effect to all ragdoll limbs. foreach (RagdollMotor motor in _ragdoll.Motors) { if (motor != null) { motor.Mode = RagdollMotorMode.Constraint; motor.ConstraintDamping = 5; motor.ConstraintSpring = 0; } } _ragdoll.EnableMotors(); // Add rigid bodies and the constraints of the ragdoll to the simulation. _ragdoll.AddToSimulation(Simulation); } } else { // Copy skeleton pose from ragdoll. _ragdoll.UpdateSkeletonFromBodies(_avatarPose.SkeletonPose); } // Render rigid bodies. _debugRenderer.Clear(); foreach (var body in Simulation.RigidBodies) { if (!(body.Shape is EmptyShape)) // Do not draw dummy bodies which might be used by the ragdoll. { _debugRenderer.DrawObject(body, Color.Black, true, false); } } }
public override void Update(GameTime gameTime) { // Just for debugging: Draw coordinate axes at (0, 0, 0). _debugRenderer.Clear(); _debugRenderer.DrawAxes(Pose.Identity, 0.5f, true); // Update the scene - this must be called once per frame. _scene.Update(gameTime.ElapsedGameTime); base.Update(gameTime); }
protected override void OnUpdate(TimeSpan deltaTime) { Scene.Update(deltaTime); _frameCount++; // At regular intervals reset the debug output and write the current FPS. if (_stopwatch.Elapsed.TotalSeconds > 1) { _debugRenderer.Clear(); _debugRenderer.DrawText("FPS: " + _frameCount / (float)_stopwatch.Elapsed.TotalSeconds); _stopwatch.Restart(); _frameCount = 0; } }
public override void Update(GameTime gameTime) { _scene.Update(gameTime.ElapsedGameTime); _debugRenderer.Clear(); foreach (var sceneNode in _scene.GetDescendants()) { _debugRenderer.DrawText(sceneNode.Name ?? sceneNode.GetType().Name, sceneNode.PoseWorld.Position, Color.Green, true); _debugRenderer.DrawAxes(sceneNode.PoseWorld, 1, false); } _debugRenderer.DrawAxes(Pose.Identity, 1, false); base.Update(gameTime); }
private void UpdateMatcapTexture() { // Load texture. var texture = _contentManager.Load <Texture2D>(string.Format(MatcapTexturePath, _matcapTextureIndex)); // Replace texture in all materials. var meshNode = (MeshNode)_model.Children[0]; foreach (var material in meshNode.Mesh.Materials) { material["Default"].Set("MatcapTexture", texture); } // Visualize texture for debuggging. _debugRenderer.Clear(); _debugRenderer.DrawTexture(texture, new Rectangle(20, 120, 200, 200)); }
public override void Update(GameTime gameTime) { // Move models in circles. _angle += (float)gameTime.ElapsedGameTime.TotalSeconds * 0.6f; // Set SceneNode.LastPoseWorld to the current pose. This is only required // when advanced effects are used, like post-process motion blur. Since this // is not the case in this sample, we could skip this step. However, it is a // good practice to always update SceneNode.LastPoseWorld and LastScaleWorld // before the pose or scale is changed. _model0.SetLastPose(true); _model1.SetLastPose(true); // Update the position and orientation of the models. _model0.PoseWorld = new Pose(new Vector3F(2, 0, 0)) * new Pose(Matrix33F.CreateRotationY(_angle)) * new Pose(new Vector3F(2, 0, 0)); _model1.PoseWorld = new Pose(new Vector3F(-2, 0, 0)) * new Pose(Matrix33F.CreateRotationY(-_angle + 0.5f)) * new Pose(new Vector3F(-2, 0, 0)); // Draw the bounding shapes of the meshes. // // Note - Bounding shapes of skinned models: // The model description file (dude.drmdl) specifies a custom bounding shape // (see the attributes AabbMinimum and AabbMaximum in this file). For // skinned models this bounding shape must be chosen manually. It must be big // enough to contain all poses of the model. - In future DigitalRune Graphics // versions we will automatically compute suitable bounding shapes for // animated models. _debugRenderer.Clear(); foreach (var sceneNode in _scene.GetSubtree().OfType <MeshNode>()) { _debugRenderer.DrawObject(sceneNode, Color.Orange, true, false); } // Draw a coordinate cross at the world space origin. _debugRenderer.DrawAxes(Pose.Identity, 1, false); // Update the scene - this must be called once per frame. // The scene will compute internal collision information for camera frustum // culling or light culling (which lights overlap with which mesh nodes). _scene.Update(gameTime.ElapsedGameTime); base.Update(gameTime); }
protected override void OnRender(RenderContext context) { _frameCount++; // At regular intervals reset the debug output and write the current FPS. if (_stopwatch.Elapsed.TotalSeconds > 1) { _debugRenderer.Clear(); _debugRenderer.DrawText("FPS: " + _frameCount / (float)_stopwatch.Elapsed.TotalSeconds); _stopwatch.Restart(); _frameCount = 0; } context.Scene = Scene; context.CameraNode = CameraNode; var graphicsDevice = GraphicsService.GraphicsDevice; // Clear background. graphicsDevice.Clear(Color.Transparent); // Frustum culling: Get all scene nodes that intersect the camera frustum. var query = Scene.Query <CameraFrustumQuery>(context.CameraNode, context); // Set render state. graphicsDevice.DepthStencilState = DepthStencilState.Default; graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; graphicsDevice.BlendState = BlendState.Opaque; graphicsDevice.SamplerStates[0] = SamplerState.AnisotropicWrap; // Use a MeshRenderer to render all MeshNodes that are in the camera frustum. // We use the shader effects and effect parameters for the render pass named // "Default" (see the material (.drmat files) of the assets). context.RenderPass = "******"; _meshRenderer.Render(query.SceneNodes, context); context.RenderPass = null; // Render debug info. _debugRenderer.Render(context); context.CameraNode = null; context.Scene = null; }
public override void Update(GameTime gameTime) { // Move the directional light in a circle. float deltaTimeF = (float)gameTime.ElapsedGameTime.TotalSeconds; _lightAngle += 0.3f * deltaTimeF; var position = QuaternionF.CreateRotationY(_lightAngle).Rotate(new Vector3F(6, 6, 0)); // Make the light look at the world space origin. var lightTarget = Vector3F.Zero; var lookAtMatrix = Matrix44F.CreateLookAt(position, lightTarget, Vector3F.Up); // A look-at matrix is the inverse of a normal world or pose matrix. _mainDirectionalLightNode.PoseWorld = new Pose(lookAtMatrix.Translation, lookAtMatrix.Minor).Inverse; // Update the light position of the renderer. // To create a local light shadow (light rays are not parallel), we have to set the light // position and a 4th component of 1. //_projectedShadowRenderer.LightPosition = new Vector4F(position, 1); // To create a directional light shadow (light rays are parallel), we have to set the inverse // light direction and 0. var lightRayDirection = (lightTarget - position); _projectedShadowRenderer.LightPosition = new Vector4F(-lightRayDirection, 0); // For debugging: Draw coordinate axes at (0, 0, 0). _debugRenderer.Clear(); _debugRenderer.DrawAxes(Pose.Identity, 1, true); // Draw light node. (Will be drawn as a coordinate cross.) _debugRenderer.DrawObject(_mainDirectionalLightNode, Color.Yellow, false, true); // Update the scene - this must be called once per frame. _scene.Update(gameTime.ElapsedGameTime); base.Update(gameTime); }
public override void Update(GameTime gameTime) { Random random = new Random(1234567); // The debug renderer stores all draw commands. In this sample we recreate // the draw jobs each frame. --> Clear draw jobs of last frame. _debugRenderer.Clear(); // The DebugRenderer can draw stuff "in" the scene (enabled z test) or "over" // the scene (disabled z test). // Draw some points and line "in" and "over" the scene. for (int i = 0; i < 10; i++) { var position = new Vector3F(-6, 0, -3) + random.NextVector3F(-0.5f, 0.5f); _debugRenderer.DrawPoint(position, Color.Green, false); } for (int i = 0; i < 10; i++) { var position = new Vector3F(-4, 0, -3) + random.NextVector3F(-0.5f, 0.5f); _debugRenderer.DrawPoint(position, Color.Yellow, true); } for (int i = 0; i < 10; i++) { var start = new Vector3F(-2, 0, -3) + random.NextVector3F(-0.5f, 0.5f); var end = new Vector3F(-2, 0, -3) + random.NextVector3F(-0.5f, 0.5f); _debugRenderer.DrawLine(start, end, Color.Green, false); } for (int i = 0; i < 10; i++) { var start = new Vector3F(0, 0, -3) + random.NextVector3F(-0.5f, 0.5f); var end = new Vector3F(0, 0, -3) + random.NextVector3F(-0.5f, 0.5f); _debugRenderer.DrawLine(start, end, Color.Yellow, true); } // Text without a specified position is drawn at a default position. _debugRenderer.DefaultTextPosition = new Vector2F(10, 100); _debugRenderer.DrawText("White objects are positioned in screen space."); _debugRenderer.DrawText("Yellow objects are positioned in world space. Depth test disabled."); _debugRenderer.DrawText("Other objects are positioned in world space. Depth test enabled."); // Text can also be drawn in world space coordinates or in screen space coordinates. _debugRenderer.DrawText("WorldSpacePosition (0, 0, 0)", new Vector3F(0, 0, 0), Color.Green, false); _debugRenderer.DrawText("WorldSpacePosition (0, 0, -1)", new Vector3F(0, 0, -1), Color.Yellow, true); _debugRenderer.DrawText("ScreenPosition (600, 40)", new Vector2F(600, 40), Color.White); _debugRenderer.DrawText("ScreenPosition (640, 360)", new Vector2F(640, 360), Color.White); // It is often useful to copy textures to the screen for debugging. _debugRenderer.DrawTexture(NoiseHelper.GetGrainTexture(GraphicsService, 128), new Rectangle(1000, 10, 128, 128)); // Axes can be drawn to display poses (positions and orientations). _debugRenderer.DrawAxes(new Pose(new Vector3F(0, 0, 0)), 1, true); // Axis-aligned bounding boxes (AABB) _debugRenderer.DrawAabb(new Aabb(new Vector3F(-0.5f), new Vector3F(0.5f)), new Pose(new Vector3F(2, 0, -3)), Color.Green, false); _debugRenderer.DrawAabb(new Aabb(new Vector3F(-0.5f), new Vector3F(0.5f)), new Pose(new Vector3F(4, 0, -3)), Color.Yellow, true); // Box shapes var orientation = random.NextQuaternionF(); _debugRenderer.DrawBox(1, 1, 1, new Pose(new Vector3F(-6, 0, -5), orientation), new Color(255, 0, 0, 100), false, false); _debugRenderer.DrawBox(1, 1, 1, new Pose(new Vector3F(-6, 0, -5), orientation), Color.Green, true, false); _debugRenderer.DrawBox(1, 1, 1, new Pose(new Vector3F(-4, 0, -5), orientation), Color.Yellow, true, true); // View volumes (frustums) var viewVolume = new PerspectiveViewVolume(1, 2, 0.1f, 1f); _debugRenderer.DrawViewVolume(viewVolume, new Pose(new Vector3F(-2, 0, -5), orientation), new Color(0, 255, 0, 100), false, false); _debugRenderer.DrawViewVolume(viewVolume, new Pose(new Vector3F(-2, 0, -5), orientation), Color.Green, true, false); _debugRenderer.DrawViewVolume(viewVolume, new Pose(new Vector3F(0, 0, -5), orientation), Color.Yellow, true, true); // Spheres _debugRenderer.DrawSphere(0.5f, new Pose(new Vector3F(2, 0, -5), orientation), new Color(0, 0, 255, 100), false, false); _debugRenderer.DrawSphere(0.5f, new Pose(new Vector3F(2, 0, -5), orientation), Color.Green, true, false); _debugRenderer.DrawSphere(0.5f, new Pose(new Vector3F(4, 0, -5), orientation), Color.Yellow, true, true); // Capsules _debugRenderer.DrawCapsule(0.3f, 1, new Pose(new Vector3F(-6, 0, -7), orientation), new Color(255, 255, 0, 100), false, false); _debugRenderer.DrawCapsule(0.3f, 1, new Pose(new Vector3F(-6, 0, -7), orientation), Color.Green, true, false); _debugRenderer.DrawCapsule(0.3f, 1, new Pose(new Vector3F(-4, 0, -7), orientation), Color.Yellow, true, true); // Cylinders _debugRenderer.DrawCylinder(0.3f, 1, new Pose(new Vector3F(-2, 0, -7), orientation), new Color(255, 0, 255, 100), false, false); _debugRenderer.DrawCylinder(0.3f, 1, new Pose(new Vector3F(-2, 0, -7), orientation), Color.Green, true, false); _debugRenderer.DrawCylinder(0.3f, 1, new Pose(new Vector3F(0, 0, -7), orientation), Color.Yellow, true, true); // Cones _debugRenderer.DrawCone(0.3f, 1, new Pose(new Vector3F(2, 0, -7), orientation), new Color(0, 255, 255, 100), false, false); _debugRenderer.DrawCone(0.3f, 1, new Pose(new Vector3F(2, 0, -7), orientation), Color.Green, true, false); _debugRenderer.DrawCone(0.3f, 1, new Pose(new Vector3F(4, 0, -7), orientation), Color.Yellow, true, true); // The debug renderer can draw any IGeometricObjects, like SceneNodes, RigidBodies, etc. _debugRenderer.DrawObject(_geometricObject, Color.Brown, false, false); _debugRenderer.DrawObject(_geometricObject, Color.Yellow, true, true); // The debug renderer can also an XNA model (without materials). _debugRenderer.DrawModel(_xnaModel, new Pose(new Vector3F(0, 2, -2), orientation), new Vector3F(1, 2, 1), new Color(128, 255, 64, 100), false, false); _debugRenderer.DrawModel(_xnaModel, new Pose(new Vector3F(0, 2, -2), orientation), new Vector3F(1, 2, 1), Color.LightCyan, true, false); // Draw a DigitalRune model. _debugRenderer.DrawModel(_modelNode, Color.Peru, true, false); // Draw the bounding shapes of the meshes in this model. foreach (var node in _modelNode.GetSubtree()) { _debugRenderer.DrawObject(node, Color.PeachPuff, true, false); } }
// 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; }
protected override void OnRender(RenderContext context) { if (ActiveCameraNode == null) { return; } context.Scene = Scene; context.CameraNode = ActiveCameraNode; context.LodCameraNode = ActiveCameraNode; // Copy all scene nodes into a list. CopyNodesToList(Scene, _sceneNodes); // ----- Occlusion Culling // Usually, we would make a scene query to get all scene nodes within the // viewing frustum. But in this example we will use the new OcclusionBuffer. if (EnableCulling) { // Render all occluders into the occlusion buffer. // - "_sceneNodes" is a list of all scene nodes. The OcclusionBuffer will // go through the list and render all occluders. // - "LightNode" is the main directional light that casts a cascaded shadow. // Passing the light node to the OcclusionBuffer activates shadow caster // culling. // - A custom scene node renderer can be passed to the OcclusionBuffer. In // this example, the ground mesh "Gravel/Gravel.fbx" has a material with an // "Occluder" render pass. When we pass the "MeshRenderer" to the OcclusionBuffer // the ground mesh will be rendered directly into the occlusion buffer. Profiler.Start("Occlusion.Render"); context.RenderPass = "******"; OcclusionBuffer.Render(_sceneNodes, LightNode, MeshRenderer, context); context.RenderPass = null; Profiler.Stop("Occlusion.Render"); // Perform occlusion culling on the specified list of scene nodes. // - The scene nodes will be tested against the occluders. If a scene node // is hidden, it will be replaced with a null entry in the list. // - When shadow caster culling is active, shadow casting scene nodes will // also be tested against the occluders. If the shadow is not visible, // the shadow caster will internally be marked as occluded. The ShadowMapRenderer // will automatically skip occluded scene nodes. Profiler.Start("Occlusion.Query"); OcclusionBuffer.Query(_sceneNodes, context); Profiler.Stop("Occlusion.Query"); } // The base DeferredGraphicsScreen expects a CustomSceneQuery. // --> Copy the occlusion culling results to a CustomSceneQuery. _sceneQuery.Set(ActiveCameraNode, _sceneNodes, context); var renderTargetPool = GraphicsService.RenderTargetPool; var graphicsDevice = GraphicsService.GraphicsDevice; var originalRenderTarget = context.RenderTarget; var fullViewport = context.Viewport; RenderTarget2D topDownRenderTarget = null; const int topDownViewSize = 384; if (ShowTopDownView) { // Render top-down scene into an offscreen render target. var format = new RenderTargetFormat(context.RenderTarget) { Width = topDownViewSize, Height = topDownViewSize, }; topDownRenderTarget = renderTargetPool.Obtain2D(format); context.Scene = Scene; context.CameraNode = _topDownCameraNode; context.Viewport = new Viewport(0, 0, topDownViewSize, topDownViewSize); context.RenderTarget = topDownRenderTarget; RenderScene(_sceneQuery, context, true, false, false, false); _debugRenderer.Clear(); _debugRenderer.DrawObject(ActiveCameraNode, Color.Red, true, true); _debugRenderer.Render(context); context.RenderTarget = originalRenderTarget; context.Viewport = fullViewport; } // Render regular 3D scene. context.Scene = Scene; context.CameraNode = ActiveCameraNode; RenderScene(_sceneQuery, context, true, false, true, false); // Render debug visualization on top of scene. bool renderObject = false; switch (DebugVisualization) { case DebugVisualization.CameraHzb: OcclusionBuffer.VisualizeCameraBuffer(DebugLevel, context); break; case DebugVisualization.LightHzb: OcclusionBuffer.VisualizeLightBuffer(DebugLevel, context); break; case DebugVisualization.Object: OcclusionBuffer.VisualizeObject(DebugObject, context); renderObject = true; break; case DebugVisualization.ShadowCaster: OcclusionBuffer.VisualizeShadowCaster(DebugObject, context); break; case DebugVisualization.ShadowVolume: OcclusionBuffer.VisualizeShadowVolume(DebugObject, context); renderObject = true; break; } if (renderObject) { _debugRenderer.Clear(); _debugRenderer.DrawObject(DebugObject, Color.Yellow, true, true); _debugRenderer.Render(context); } if (ShowTopDownView) { // Copy offscreen buffer to screen. context.Viewport = fullViewport; graphicsDevice.Viewport = fullViewport; SpriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque, SamplerState.PointClamp, DepthStencilState.None, RasterizerState.CullNone); SpriteBatch.Draw( topDownRenderTarget, new Rectangle(fullViewport.Width - topDownViewSize, fullViewport.Height - topDownViewSize, topDownViewSize, topDownViewSize), Color.White); SpriteBatch.End(); renderTargetPool.Recycle(topDownRenderTarget); } // Clean-up _sceneNodes.Clear(); _sceneQuery.Reset(); context.Scene = null; context.CameraNode = null; context.LodCameraNode = null; }
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; }
public override void Update(GameTime gameTime) { if (_avatarPose == null) { if (_avatarRenderer.State == AvatarRendererState.Ready) { _avatarPose = new AvatarPose(_avatarRenderer); _targetPose = SkeletonPose.Create(_avatarPose.SkeletonPose.Skeleton); // Create a ragdoll for the avatar. _ragdoll = Ragdoll.CreateAvatarRagdoll(_avatarPose, Simulation); // Set the world space pose of the whole ragdoll. And copy the bone poses // of the current skeleton pose. _ragdoll.Pose = _pose; _ragdoll.UpdateBodiesFromSkeleton(_avatarPose.SkeletonPose); // To simplify collision checks, we need a simple way to determine whether // a rigid body belongs to the ragdoll. // --> Set RigidBody.UserData = _ragdoll. // (Alternatively we could also set specific names for the rigid bodies, // or we could assign the collision objects to a certain collision group.) foreach (var body in _ragdoll.Bodies) { if (body != null) { body.UserData = _ragdoll; } } // Add rigid bodies and constraints to the simulation. _ragdoll.AddToSimulation(Simulation); // Start by playing the key frame animation. SwitchMode(RagdollMode.Mode1); // The facial expression can be applied directly to the _avatarPose. _animationController0 = AnimationService.StartAnimation(_expressionAnimation, _avatarPose); // The skeletal animation is applied to the _targetPose. The _targetPose // is used to drive the ragdoll. (See end of method.) _animationController1 = AnimationService.StartAnimation(_skeletonAnimation, (IAnimatableProperty <SkeletonPose>)_targetPose); } return; } if (InputService.IsPressed(Buttons.A, false, LogicalPlayerIndex.One)) { SwitchMode(RagdollMode.Mode1); } else if (InputService.IsPressed(Buttons.B, false, LogicalPlayerIndex.One)) { SwitchMode(RagdollMode.Mode2); } else if (InputService.IsPressed(Buttons.X, false, LogicalPlayerIndex.One)) { SwitchMode(RagdollMode.Mode3); } else if (InputService.IsPressed(Buttons.Y, false, LogicalPlayerIndex.One)) { SwitchMode(RagdollMode.Mode4); } if (_mode == RagdollMode.Mode1 || _mode == RagdollMode.Mode2) { // The ragdoll plays a certain animation. Check whether the character was // hit by a ball. foreach (var contactConstraint in Simulation.ContactConstraints) { if (contactConstraint.BodyA.UserData == _ragdoll && contactConstraint.BodyB.Name.StartsWith("Ball") || contactConstraint.BodyB.UserData == _ragdoll && contactConstraint.BodyA.Name.StartsWith("Ball")) { // Switch to the "Passive Ragdoll" mode and let the character collapse. SwitchMode(RagdollMode.Mode3); // Hint: You can read contactConstraint.LinearConstraintImpulse.Length to // determine the strength of the impact. } } } switch (_mode) { case RagdollMode.Mode1: // In mode 1 we update the rigid bodies directly. _ragdoll.UpdateBodiesFromSkeleton(_targetPose); break; case RagdollMode.Mode2: // Compute how much time the simulation will advance in the next Update(). TimeSpan nextSimulationTimeStep; int numberOfSubTimeSteps; Simulation.GetNextTimeStep(gameTime.ElapsedGameTime, out nextSimulationTimeStep, out numberOfSubTimeSteps); // In mode 2 velocity motors update the rigid bodies. _ragdoll.DriveToPose(_targetPose, (float)nextSimulationTimeStep.TotalSeconds); break; case RagdollMode.Mode3: // In mode 3 we don't have to update the rigid bodies. break; case RagdollMode.Mode4: // In mode 4 constraint motors control the joints of the ragdoll. // (The second parameter is only required for velocity motors.) _ragdoll.DriveToPose(_targetPose, 0); break; } // Copy the skeleton pose. (_avatarPose stores the skeleton pose which is // being rendered.) _ragdoll.UpdateSkeletonFromBodies(_avatarPose.SkeletonPose); _debugRenderer.Clear(); _debugRenderer.DrawText("\n"); _debugRenderer.DrawText(_statusMessage); // Render rigid bodies. foreach (var body in Simulation.RigidBodies) { if (!(body.Shape is EmptyShape)) // Do not draw dummy bodies which might be used by the ragdoll. { _debugRenderer.DrawObject(body, Color.Black, true, false); } } }