Click or drag to resize
DigitalRuneStep 5: Debug rendering
Add a sprite font

To output text in an XNA game, we need a sprite font. Let's add one:

  1. In the VS Solution Explorer right-click MyGameContent.
  2. Select Add | New Item…
  3. Select the Sprite Font template.
  4. Leave the default name (SpriteFont1.spritefont).
  5. And press Add.
Add a debug renderer

Modify MyGraphicsScreen.cs and add a DebugRenderer:

MyGraphicsScreen.cs
using System;
using DigitalRune.Graphics;
using DigitalRune.Graphics.Rendering;                                                   // NEW
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;                                                 // NEW

namespace MyGame
{
    public class MyGraphicsScreen : GraphicsScreen
    {
        public DebugRenderer DebugRenderer { get; private set; }                        // NEW
        
        public MyGraphicsScreen(IGraphicsService graphicsService)
            : base(graphicsService)
        {
            var spriteFont = graphicsService.Content.Load<SpriteFont>("SpriteFont1");   // NEW
            DebugRenderer = new DebugRenderer(graphicsService, spriteFont);             // NEW
        }
        
        protected override void OnUpdate(TimeSpan deltaTime)
        {
        }
        
        protected override void OnRender(RenderContext context)
        {
            var graphicsDevice = GraphicsService.GraphicsDevice;
            graphicsDevice.Clear(Color.CornflowerBlue);

            DebugRenderer.Render(context);                                              // NEW
        }
    }
}

Draw some debug text in MyGameComponent.cs:

MyGameComponent.cs
public class MyGameComponent : Microsoft.Xna.Framework.GameComponent
{
    …

    public MyGameComponent(Game game)
        : base(game)
    {
        _inputService = ServiceLocator.Current.GetInstance<IInputService>();

        _graphicsService = ServiceLocator.Current.GetInstance<IGraphicsService>();
        
        _myGraphicsScreen = new MyGraphicsScreen(_graphicsService);
        _graphicsService.Screens.Add(_myGraphicsScreen);
        
        _myGraphicsScreen.DebugRenderer.DrawText("MyGame");                             // NEW
    }
    …

Now, the game looks like this:

Tutorial-01-05

Next, we use the DebugRenderer to render a few arrows at the world origin. Add the following lines in MyGameComponent.cs:

MyGameComponent.cs
using DigitalRune.Geometry;                                                     // NEWnamespace MyGame
{
    public class MyGameComponent : Microsoft.Xna.Framework.GameComponent
    {
        …

        public MyGameComponent(Game game)
            : base(game)
        {
            …
            _myGraphicsScreen.DebugRenderer.DrawText("MyGame");
            _myGraphicsScreen.DebugRenderer.DrawAxes(Pose.Identity, 1, false);  // NEW
        }
        …

If you try to run the project, you will get an exception. The DebugRenderer lets you know that it cannot render 3D graphics without a camera. The camera is necessary to define the viewpoint of the player.

Let's add a camera in MyGraphicsScreen.cs:

MyGraphicsScreen.cs
using System;
using DigitalRune.Geometry;
using DigitalRune.Graphics;
using DigitalRune.Graphics.Rendering;
using DigitalRune.Graphics.SceneGraph;                                                  // NEW
using DigitalRune.Mathematics;                                                          // NEW
using DigitalRune.Mathematics.Algebra;                                                  // NEW
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace MyGame
{
    public class MyGraphicsScreen : GraphicsScreen
    {
        public DebugRenderer DebugRenderer { get; set; }
        public CameraNode CameraNode { get; set; }                                      // NEW

        public MyGraphicsScreen(IGraphicsService graphicsService)
            : base(graphicsService)
        {
            var spriteFont = graphicsService.Content.Load<SpriteFont>("SpriteFont1");
            DebugRenderer = new DebugRenderer(graphicsService, spriteFont);

            var projection = new PerspectiveProjection();                               // NEW
            projection.SetFieldOfView(                                                  // NEW
                ConstantsF.PiOver4,                                                     // NEW
                    graphicsService.GraphicsDevice.Viewport.AspectRatio,                // NEW
                    0.1f,                                                               // NEW
                    100);                                                               // NEW
            var camera = new Camera(projection);                                        // NEW
            CameraNode = new CameraNode(camera);                                        // NEW
            CameraNode.PoseWorld = new Pose(new Vector3F(0, 1, 3));                     // NEW
        }

        …

        protected override void OnRender(RenderContext context)
        {
            var graphicsDevice = GraphicsService.GraphicsDevice;
            graphicsDevice.Clear(Color.CornflowerBlue);

            context.CameraNode = CameraNode;                                            // NEW

            DebugRenderer.Render(context);

            context.CameraNode = null;                                                  // NEW
        }
    }
}

The camera is positioned at (0, 1, 5). Per default it looks forward (which is the -z direction in XNA and DigitalRune). To let the renderer know which camera it should use, we have to set this information in the RenderContext in MyGraphicsScreen.OnRender.

Our current game:

Tutorial-01-06